1 /*
2 * Copyright 2007 Joachim Grueneis
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.exolab.castor.xml.util.resolvers;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.URL;
21 import java.util.ArrayList;
22 import java.util.Enumeration;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Properties;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.exolab.castor.mapping.ClassDescriptor;
31 import org.exolab.castor.xml.ResolverException;
32 import org.exolab.castor.xml.XMLConstants;
33
34 /**
35 * Resolves a class by reading the package level class-descriptor-resolver file
36 * and loading all descriptors mentioned inside.
37 *
38 * @author <a href="mailto:jgrueneis AT gmail DOT com">Joachim Grueneis</a>
39 * @author <a href="mailto:stevendolg AT gxm DOT at">Steven Dolg</a>
40 * @version $Revision$ $Date$
41 * @since 1.2
42 */
43 public class ByCDR extends AbstractResolverPackageCommand {
44 private static final Log LOG = LogFactory.getLog(ByCDR.class);
45
46 private List<String> _loadedPackages = new ArrayList<String>();
47
48 /**
49 * No specific stuff needed.
50 */
51 public ByCDR() {
52 super();
53 }
54
55 /**
56 * Creates a Properties object and initializes it with the contents of
57 * the given URL. The provided URL must exist and be suitable for loading
58 * properties from.
59 *
60 * @param url The URL to load the properties from. This must not be null!
61 * @return The loaded properties.
62 * @throws IOException If loading the properties from the given ULR failed.
63 *
64 * @see Properties
65 * @see Properties#load(InputStream)
66 */
67 private Properties getProperties(URL url) throws java.io.IOException {
68 Properties cdrList = new Properties();
69
70 java.io.InputStream stream = url.openStream();
71 cdrList.load(stream);
72 stream.close();
73
74 return cdrList;
75 }
76
77 /**
78 * Tries to load the CDR file for the given package name using the provided
79 * class loader. If the CDR file is available and could be loaded properly the
80 * descriptors listed in it are added to this cache.
81 * <br>
82 * If a descriptor is listed in the CDR file for the given package but
83 * could not be loaded (e.g. because the reference class file is not
84 * available) the descriptor is ignored but no exception is thrown.
85 * <br>
86 * If a CDR file is not available for the given package this method will
87 * not load any descriptors and not throw any exceptions.
88 * <br>
89 * Further calls to this method with the same package name will not be
90 * processed.
91 * <br>
92 * {@inheritDoc}
93 */
94 protected Map<String, ClassDescriptor> internalResolve(final String packageName, final ClassLoader classLoader,
95 final Map properties) throws ResolverException {
96
97 Map<String, ClassDescriptor> results = new HashMap<String, ClassDescriptor>();
98 if (!isEmptyPackageName(packageName) && _loadedPackages.contains(packageName)) {
99 if (LOG.isDebugEnabled()) {
100 LOG.debug("Package: " + packageName + " has already been loaded.");
101 }
102 return results;
103 }
104 if (!isEmptyPackageName(packageName)) {
105 _loadedPackages.add(packageName);
106 }
107
108 URL url = classLoader.getResource(ResolveHelpers.getQualifiedFileName(
109 XMLConstants.PKG_CDR_LIST_FILE, packageName));
110 if (url == null) {
111 return results;
112 }
113
114 try {
115 Properties cdrList = this.getProperties(url);
116
117 for (Object clazz : cdrList.keySet()) {
118 String clazzName = (String) clazz;
119 String descriptorClassName = (String) cdrList.get(clazzName);
120 try {
121 Class<?> descriptorClass = classLoader.loadClass(descriptorClassName);
122 if (LOG.isDebugEnabled()) {
123 LOG.debug("Found descriptor: " + descriptorClass);
124 }
125 if (descriptorClass != null) {
126 ClassDescriptor instance = (ClassDescriptor) descriptorClass.newInstance();
127 results.put(clazzName, instance);
128 } else if (LOG.isDebugEnabled()) {
129 LOG.debug("Loading of descriptor class: " + descriptorClassName
130 + " for class: " + clazzName + " has failed - continue without");
131 }
132 } catch (Exception e) {
133 if (LOG.isDebugEnabled()) {
134 LOG.debug("Ignored problem at loading of: " + descriptorClassName
135 + " with exception: " + e);
136 }
137 }
138 }
139 } catch (IOException iox) {
140 String message = "Failed to load package: " + packageName + " with exception: " + iox;
141 LOG.warn(message);
142 throw new ResolverException(message);
143 }
144 return results;
145 }
146 }