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 }