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