View Javadoc
1   /*
2    * Copyright 2007 Werner Guttmann
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;
15  
16  import org.apache.commons.logging.Log;
17  import org.apache.commons.logging.LogFactory;
18  import org.castor.mapping.BindingType;
19  import org.castor.mapping.MappingUnmarshaller;
20  import org.castor.xml.AbstractInternalContext;
21  import org.castor.xml.InternalContext;
22  import org.exolab.castor.mapping.Mapping;
23  import org.exolab.castor.mapping.MappingException;
24  import org.exolab.castor.mapping.MappingLoader;
25  import org.exolab.castor.tools.MappingTool;
26  import org.exolab.castor.util.ChangeLog2XML;
27  import org.exolab.castor.xml.util.ResolverStrategy;
28  import org.exolab.castor.xml.util.resolvers.CastorXMLStrategy;
29  
30  /**
31   * Bootstrap class for Castor XML that allows you to load information about the domain objects used
32   * with Castor XML (marshallers and unmarshallers) by various means.
33   * 
34   * @author <a href="mailto:werner DOT guttmann At gmx DOT net">Werner Guttmann</a>
35   * @since 1.1.2
36   */
37  public class XMLContext {
38    /** Logger to be used. */
39    private static final Log LOG = LogFactory.getFactory().getInstance(XMLContext.class);
40  
41    /**
42     * The internal XML context is the class which holds a couple of Castor states as it provides some
43     * central methods needed in various places of Castor.
44     */
45    private InternalContext _internalContext;
46  
47    /**
48     * Creates an instance of {@link XMLContext} with an internal XML context.
49     */
50    public XMLContext() {
51      AbstractInternalContext internalContext = new AbstractInternalContext() {};
52  
53      internalContext.setClassLoader(getClass().getClassLoader());
54  
55      XMLClassDescriptorResolver cdr = (XMLClassDescriptorResolver) ClassDescriptorResolverFactory
56          .createClassDescriptorResolver(BindingType.XML);
57      internalContext.setXMLClassDescriptorResolver(cdr);
58      cdr.setInternalContext(internalContext);
59  
60      Introspector introspector = new Introspector();
61      introspector.setInternalContext(internalContext);
62      internalContext.setIntrospector(introspector);
63      cdr.setIntrospector(introspector);
64  
65      ResolverStrategy resolverStrategy = new CastorXMLStrategy();
66      internalContext.setResolverStrategy(resolverStrategy);
67      cdr.setResolverStrategy(resolverStrategy);
68  
69      _internalContext = internalContext;
70    }
71  
72    /**
73     * Instructs Castor to load class descriptors from the mapping given.
74     * 
75     * @param mapping Castor XML mapping (file), from which the required class descriptors will be
76     *        derived.
77     * @throws MappingException If the {@link Mapping} cannot be loaded and analyzed successfully.
78     */
79    public void addMapping(final Mapping mapping) throws MappingException {
80      MappingUnmarshaller mappingUnmarshaller = new MappingUnmarshaller();
81      MappingLoader mappingLoader = mappingUnmarshaller.getMappingLoader(mapping, BindingType.XML);
82      _internalContext.getXMLClassDescriptorResolver().setMappingLoader(mappingLoader);
83    }
84  
85    /**
86     * Loads the class descriptor for the class instance specified. The use of this method is useful
87     * when no mapping is used, as happens when the domain classes has been generated using the XML
88     * code generator (in which case instead of a mapping file class descriptor files will be
89     * generated).
90     * 
91     * @param clazz the class for which the associated descriptor should be loaded.
92     * @throws ResolverException in case that resolving the Class fails fatally
93     */
94    public void addClass(final Class clazz) throws ResolverException {
95      _internalContext.getXMLClassDescriptorResolver().addClass(clazz);
96    }
97  
98    /**
99     * Loads the class descriptor for the class instance specified. The use of this method is useful
100    * when no mapping is used, as happens when the domain classes hase been generated using the XML
101    * code generator (in which case instead of a mapping file class descriptor files will be
102    * generated).
103    * 
104    * @param clazzes the classes for which the associated descriptor should be loaded.
105    * @throws ResolverException in case that resolving the Class fails fatally
106    */
107   public void addClasses(final Class[] clazzes) throws ResolverException {
108     _internalContext.getXMLClassDescriptorResolver().addClasses(clazzes);
109   }
110 
111   /**
112    * Loads class descriptors from the package specified. The use of this method is useful when no
113    * mapping is used, as happens when the domain classes hase been generated using the XML code
114    * generator (in which case instead of a mapping file class descriptor files will be generated).
115    * <p>
116    * Please note that this functionality will work only if you provide the <tt>.castor.cdr</tt> file
117    * with your generated classes (as generated by the XML code generator).
118    * <p>
119    * 
120    * @param packageName The package name for the (descriptor) classes
121    * @throws ResolverException If there's a problem loading class descriptors for the given package.
122    */
123   public void addPackage(final String packageName) throws ResolverException {
124     _internalContext.getXMLClassDescriptorResolver().addPackage(packageName);
125   }
126 
127   /**
128    * Loads class descriptors from the packages specified. The use of this method is useful when no
129    * mapping is used, as happens when the domain classes hase been generated using the XML code
130    * generator (in which case instead of a mapping file class descriptor files will be generated).
131    * <p>
132    * Please note that this functionality will work only if you provide the <tt>.castor.cdr</tt>
133    * files with your generated classes (as generated by the XML code generator).
134    * <p>
135    * 
136    * @param packageNames The package names for the (descriptor) classes
137    * @throws ResolverException If there's a problem loading class descriptors for the given package.
138    */
139   public void addPackages(final String[] packageNames) throws ResolverException {
140     _internalContext.getXMLClassDescriptorResolver().addPackages(packageNames);
141   }
142 
143   /**
144    * Creates an instance of a Castor XML specific {@link Mapping} instance.
145    * 
146    * @return a Castor XML specific {@link Mapping} instance.
147    */
148   public Mapping createMapping() {
149     Mapping mapping = new Mapping();
150     // mapping.setBindingType(BindingType.XML);
151     return mapping;
152   }
153 
154   /**
155    * Creates a new {@link Marshaller} instance to be used for marshalling.
156    * 
157    * @return A new {@link Marshaller} instance.
158    */
159   public Marshaller createMarshaller() {
160     if (LOG.isDebugEnabled()) {
161       LOG.debug("Creating new Marshaller instance.");
162     }
163     Marshaller marshaller = new Marshaller(_internalContext);
164     return marshaller;
165   }
166 
167   /**
168    * Creates a new {@link Unmarshaller} instance to be used for unmarshalling.
169    * 
170    * @return A new {@link Unmarshaller} instance, preconfigured with a
171    *         {@link XMLClassDescriptorResolver} instance with the class descriptors cached as loaded
172    *         above.
173    */
174   public Unmarshaller createUnmarshaller() {
175     if (LOG.isDebugEnabled()) {
176       LOG.debug("Creating new Unmarshaller instance.");
177     }
178     Unmarshaller unmarshaller = new Unmarshaller(_internalContext);
179     return unmarshaller;
180   }
181 
182   // /**
183   // * To create a schema reader instance for reading XSD files.
184   // * @param inputSource the InputSource to read from
185   // * @return the SchemaReader instance created and initialized
186   // */
187   // public SchemaReader createSchemaReader(final InputSource inputSource) {
188   // if (LOG.isDebugEnabled()) {
189   // LOG.debug("Creating new SchemaReader instance.");
190   // }
191   // SchemaReader sr = new SchemaReader();
192   // sr.setInternalContext(_internalContext);
193   // sr.setInputSource(inputSource);
194   // return sr;
195   // }
196   //
197   // /**
198   // * To create a schema writer instance for writing XSD files.
199   // * @param writer the Writer to write the text representation of the schema to
200   // * @return the SchemaWriter instance created and initialized
201   // * @throws IOException in case that initialization of SchemaWriter fails
202   // */
203   // public SchemaWriter createSchemaWriter(final Writer writer) throws IOException {
204   // if (LOG.isDebugEnabled()) {
205   // LOG.debug("Creating new SchemaWriter instance.");
206   // }
207   // SchemaWriter sw = new SchemaWriter();
208   // sw.setInternalContext(_internalContext);
209   // sw.setDocumentHandler(writer);
210   // return sw;
211   // }
212 
213   /**
214    * To create a MappingTool instance.
215    * 
216    * @return the MappingTool instance ready to use
217    */
218   public MappingTool createMappingTool() {
219     if (LOG.isDebugEnabled()) {
220       LOG.debug("Creating new MappingTool instance.");
221     }
222     MappingTool mt = new MappingTool();
223     mt.setInternalContext(_internalContext);
224     return mt;
225   }
226 
227   /**
228    * To create a new {@link ChangeLog2XML} instance.
229    * 
230    * @return the {@link ChangeLog2XML} instance ready to use
231    */
232   public ChangeLog2XML createChangeLog2XML() {
233     if (LOG.isDebugEnabled()) {
234       LOG.debug("Creating new ChangeLog2XML instance.");
235     }
236     ChangeLog2XML changeLog2XML = new ChangeLog2XML();
237     changeLog2XML.setInternalContext(_internalContext);
238     return changeLog2XML;
239   }
240 
241   /**
242    * To set properties for marshalling and unmarshalling behavior.
243    * 
244    * @param propertyName name of the property to set
245    * @param value the value to set to
246    */
247   public void setProperty(final String propertyName, final Object value) {
248     _internalContext.setProperty(propertyName, value);
249   }
250 
251   /**
252    * To set properties for marshalling and unmarshalling behavior.
253    * 
254    * @param propertyName name of the property to set
255    * @param value the value to set to
256    */
257   public void setProperty(final String propertyName, final boolean value) {
258     _internalContext.setProperty(propertyName, value);
259   }
260 
261   /**
262    * To get the value of a specific property.
263    * 
264    * @param propertyName name of the Property
265    * @return the value (Object) of the property
266    */
267   public Object getProperty(final String propertyName) {
268     return _internalContext.getProperty(propertyName);
269   }
270 
271   /**
272    * To get the {@link InternalContext} as used when instantiating other classes. Mind that this
273    * method is only used in tests and should NOT be used in production code!
274    * 
275    * @return the {@link InternalContext} used
276    * @deprecated
277    */
278   public InternalContext getInternalContext() {
279     return _internalContext;
280   }
281 
282   /**
283    * Sets a custom {@link ClassLoader} to be used for loading classes.
284    * 
285    * @param classLoader A custom {@link ClassLoader}.
286    */
287   public void setClassLoader(ClassLoader classLoader) {
288     this._internalContext.setClassLoader(classLoader);
289   }
290 }