View Javadoc
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 }