View Javadoc
1   /*
2    * Copyright 2007 Joachim Grueneis
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  package org.exolab.castor.xml.util.resolvers;
15  
16  import java.util.HashMap;
17  import java.util.Map;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.castor.xml.AbstractInternalContext;
22  import org.exolab.castor.mapping.ClassDescriptor;
23  import org.exolab.castor.xml.ResolverException;
24  import org.exolab.castor.xml.XMLClassDescriptor;
25  import org.exolab.castor.xml.util.ResolverStrategy;
26  
27  /**
28   * The Castor XML resolver strategy implements the resolving behaviour as it had been implmented
29   * before this refactoring step. Meaning that:<br/>
30   * It uses multiple steps to find a class descriptor for a class.<br/>
31   * It uses a cache of class descriptors<br/>
32   * A class that couldn't be resolved once is marked as unresolvable and will not be resolved again -
33   * even on a second call.<br/>
34   * 
35   * @author <a href="mailto:jgrueneis AT gmail DOT com">Joachim Grueneis</a>
36   * @author <a href="mailto:stevendolg AT gxm DOT at">Steven Dolg</a>
37   * @version $Revision$ $Date$
38   * @since 1.2
39   */
40  public class CastorXMLStrategy implements ResolverStrategy {
41    /** Logger to be used. */
42    private static final Log LOG = LogFactory.getLog(CastorXMLStrategy.class);
43  
44    /** The strategy configuration held as map of properties. */
45    private Map _properties;
46  
47    /**
48     * CastorXMLStrategy requires a configuration to be set. Within the constructor the commands
49     * building the strategy are instantiated, a command configuration is created and the descriptor
50     * cache.
51     */
52    public CastorXMLStrategy() {
53      _properties = new HashMap();
54    } // -- CastorXmlStrategy()
55  
56    /**
57     * {@inheritDoc}
58     */
59    public void setProperty(final String key, final Object value) {
60      if (_properties == null) {
61        _properties = new HashMap();
62      }
63      if (LOG.isDebugEnabled()) {
64        LOG.debug("Setting property: " + key + " to value: " + value);
65      }
66      _properties.put(key, value);
67    } // -- setProperty
68  
69    /**
70     * {@inheritDoc}
71     */
72    public ClassDescriptor resolveClass(final ResolverStrategy.ResolverResults resolverResults,
73        final String className) throws ResolverException {
74  
75      if ((className == null) || ("".equals(className))) {
76        String message = "Class name to resolve must not be null or empty!";
77        LOG.warn(message);
78        throw new IllegalArgumentException(message);
79      }
80  
81      XMLClassDescriptor descriptor = this.getDescriptor(resolverResults, className);
82      return descriptor;
83    } // -- resolve
84  
85    /**
86     * Gets the XMLClassDescriptor for the class with the given name.<br>
87     * 
88     * The descriptor is searched in the following resources are search:
89     * <ul>
90     * <li>The resolver results are checked in the beginning and after each command executed
91     * <li>The MappingLoader
92     * <li>The package mapping of the package the given class is located in
93     * <li>The CDR file of the package the given class is located in
94     * <li>The class file of the corresponding descriptor class (which is className + "Descriptor")
95     * </ul>
96     * <br/>
97     * If any of these resources yield an XMLClassDescriptor it is added to the internal cache and
98     * returned as result.
99     * 
100    * @param resolverResults The resolver results (a Map of className and XMLClassDescriptor)
101    * @param className The class to get the descriptor for.
102    * @return An <code>XMLClassDescriptor</code> for the given class or <code>null</code> if no
103    *         descriptor could be found.
104    * @throws ResolverException in case that resolution failed unexpectedly
105    */
106   private XMLClassDescriptor getDescriptor(final ResolverStrategy.ResolverResults resolverResults,
107       final String className) throws ResolverException {
108 
109     String packageName = ResolveHelpers.getPackageName(className);
110 
111     XMLClassDescriptor descriptor = resolverResults.getDescriptor(className);
112     if (descriptor != null) {
113       return descriptor;
114     }
115 
116     resolverResults.addAllDescriptors(new ByMappingLoader().resolve(className, _properties));
117     descriptor = resolverResults.getDescriptor(className);
118     if (descriptor != null) {
119       return descriptor;
120     }
121 
122     this.resolvePackage(resolverResults, packageName);
123     descriptor = resolverResults.getDescriptor(className);
124     if (descriptor != null) {
125       return descriptor;
126     }
127 
128     resolverResults.addAllDescriptors(new ByDescriptorClass().resolve(className, _properties));
129     descriptor = resolverResults.getDescriptor(className);
130     if (descriptor != null) {
131       return descriptor;
132     }
133 
134     resolverResults.addAllDescriptors(new ByIntrospection().resolve(className, _properties));
135     descriptor = resolverResults.getDescriptor(className);
136     if (descriptor != null) {
137       return descriptor;
138     }
139 
140     // none of the commands have found a match - return null
141     resolverResults.addDescriptor(className, null);
142     return null;
143   } // -- getDescriptor
144 
145   /**
146    * {@inheritDoc}
147    */
148   public void resolvePackage(final ResolverResults resolverResults, final String packageName)
149       throws ResolverException {
150     resolverResults.addAllDescriptors(new ByCDR().resolve(packageName, _properties));
151     resolverResults.addAllDescriptors(new ByPackageMapping().resolve(packageName, _properties));
152   }
153 }