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