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 }