/* * Copyright 2007 Joachim Grueneis * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.castor.xml; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; import javax.xml.parsers.SAXParser; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.castor.core.util.Messages; import org.castor.mapping.BindingType; import org.castor.mapping.MappingUnmarshaller; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.mapping.MappingException; import org.exolab.castor.mapping.MappingLoader; import org.exolab.castor.util.RegExpEvaluator; import org.exolab.castor.xml.AbstractXMLNaming; import org.exolab.castor.xml.Introspector; import org.exolab.castor.xml.NodeType; import org.exolab.castor.xml.OutputFormat; import org.exolab.castor.xml.ResolverException; import org.exolab.castor.xml.Serializer; import org.exolab.castor.xml.XMLClassDescriptorResolver; import org.exolab.castor.xml.XMLContext; import org.exolab.castor.xml.XMLSerializerFactory; import org.exolab.castor.xml.util.DefaultNaming; import org.exolab.castor.xml.util.ResolverStrategy; import org.exolab.castor.xml.util.XMLParserUtils; import org.xml.sax.DocumentHandler; import org.xml.sax.Parser; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; /** * The internal context is meant as center piece providing (and keeping) all * information that is required by Marshaller, Unmarshaller, SourceGenerator, * MappingTool, SchemaReader and SchemaWriter. It is created, filled with * initial data and put into all other parts of Castor by {@link XMLContext}. * It is NOT meant to be directly instantiated by user implementations! * For all other objects it provides access to Castor state information * (e.g. known descriptors) and configuration values. * * @author <a href="mailto:jgrueneis At gmail DOT com">Joachim Grueneis</a> * @since 1.1.2 */ public abstract class AbstractInternalContext implements InternalContext { /** Logger to be used. */ private static final Log LOG = LogFactory.getFactory().getInstance(AbstractInternalContext.class); /** The properties to use internally to provide parser, serializer, ... */ private org.castor.core.util.AbstractProperties _properties; /** * {@link XMLClassDescriptorResolver} instance used for caching XML-related * class descriptors. */ private XMLClassDescriptorResolver _xmlClassDescriptorResolver; /** * The XMLContext knows the one Introspector to be used. */ private Introspector _introspector; /** * The XMLClassDescriptor resolver strategy to use. */ private ResolverStrategy _resolverStrategy; /** * The {@link MappingLoader} to use. */ private MappingLoader _mappingLoader; /** * The {@link AbstractXMLNaming} to be used. */ private XMLNaming _xmlNaming; /** * The {@link JavaNaming} to be used. */ private JavaNaming _javaNaming; /** * The class loader to use. */ private ClassLoader _classLoader; /** * The {@link NodeType} to use for primitives. */ private NodeType _primitiveNodeType; /** * The {@link RegExpevaluator}?to use. */ private RegExpEvaluator _regExpEvaluator; /** * Creates an instance of {@link AbstractInternalContext}. The internal context is meant to * hold the configuration and state informations, but not necessarily retrieving * those values... */ public AbstractInternalContext() { _properties = XMLProperties.newInstance(); _javaNaming = new JavaNamingImpl(); } /** * @see org.castor.xml.InternalContext#addMapping(org.exolab.castor.mapping.Mapping) */ public void addMapping(final Mapping mapping) throws MappingException { MappingUnmarshaller mappingUnmarshaller = new MappingUnmarshaller(); MappingLoader mappingLoader = mappingUnmarshaller.getMappingLoader(mapping, BindingType.XML); _xmlClassDescriptorResolver.setMappingLoader(mappingLoader); } /** * @see org.castor.xml.InternalContext#addClass(java.lang.Class) */ public void addClass(final Class clazz) throws ResolverException { _xmlClassDescriptorResolver.addClass(clazz); } /** * @see org.castor.xml.InternalContext#addClasses(java.lang.Class[]) */ public void addClasses(final Class[] clazzes) throws ResolverException { _xmlClassDescriptorResolver.addClasses(clazzes); } /** * @see org.castor.xml.InternalContext#addPackage(java.lang.String) */ public void addPackage(final String packageName) throws ResolverException { _xmlClassDescriptorResolver.addPackage(packageName); } /** * @see org.castor.xml.InternalContext#addPackages(java.lang.String[]) */ public void addPackages(final String[] packageNames) throws ResolverException { _xmlClassDescriptorResolver.addPackages(packageNames); } /** * @see org.castor.xml.InternalContext#setResolver(org.exolab.castor.xml.XMLClassDescriptorResolver) */ public void setResolver(final XMLClassDescriptorResolver xmlClassDescriptorResolver) { this._xmlClassDescriptorResolver = xmlClassDescriptorResolver; } /** * {@inheritDoc} * @see org.castor.xml.InternalContext#setProperty(java.lang.String, java.lang.Object) */ public void setProperty(final String propertyName, final Object value) { // resetting all values that are only reinitialized if null if (propertyName == null) { IllegalArgumentException iae = new IllegalArgumentException("setProperty must not be called with a propertyName == null"); LOG.warn(iae.getMessage()); throw iae; } if (propertyName.equals(XMLProperties.XML_NAMING)) { if (value instanceof String) { setXMLNaming((String)value); } else if (value instanceof XMLNaming) { setXMLNaming((XMLNaming) value); } else { IllegalArgumentException iae = new IllegalArgumentException("XML Naming can only be set to a String or an implementation of XMLNaming"); LOG.warn(iae.getMessage()); throw iae; } } if (propertyName.equals(XMLProperties.JAVA_NAMING)) { if (value instanceof String) { setJavaNaming((String)value); } else if (value instanceof JavaNaming) { setJavaNaming((JavaNaming) value); } else { IllegalArgumentException iae = new IllegalArgumentException("Java Naming can only be set to a String or an implementation of JavaNaming"); LOG.warn(iae.getMessage()); throw iae; } } _primitiveNodeType = null; _regExpEvaluator = null; // now writing the new property _properties.put(propertyName, value); } /** * @see org.castor.xml.InternalContext#getProperty(java.lang.String) */ public Object getProperty(final String propertyName) { return _properties.getObject(propertyName); } /** * {@inheritDoc} * @see org.castor.xml.InternalContext#getXMLNaming() */ public XMLNaming getXMLNaming() { if (_xmlNaming != null) { return _xmlNaming; } String prop = _properties.getString(XMLProperties.XML_NAMING, null); setXMLNaming(prop); return _xmlNaming; } /** * {@inheritDoc} * @see org.castor.xml.InternalContext#getXMLNaming(java.lang.ClassLoader) * @deprecated Makes no sence! */ public XMLNaming getXMLNaming(final ClassLoader classLoader) { return getXMLNaming(); } //-- getXMLNaming /** * @see org.castor.xml.InternalContext#getJavaNaming() */ public JavaNaming getJavaNaming() { return _javaNaming; } /** * @see org.castor.xml.InternalContext#getParser() */ public Parser getParser() { return getParser(null); } /** * @see org.castor.xml.InternalContext#getParser(java.lang.String) */ public Parser getParser(final String features) { return XMLParserUtils.getParser(_properties, features); } /** * @see org.castor.xml.InternalContext#getXMLReader() */ public XMLReader getXMLReader() { return getXMLReader(null); } /** * @see org.castor.xml.InternalContext#getXMLReader(java.lang.String) */ public XMLReader getXMLReader(final String features) { XMLReader reader = null; Boolean validation = _properties.getBoolean(XMLProperties.PARSER_VALIDATION); Boolean namespaces = _properties.getBoolean(XMLProperties.NAMESPACES); String readerClassName = _properties.getString(XMLProperties.PARSER); if (readerClassName == null || readerClassName.length() == 0) { SAXParser saxParser = XMLParserUtils.getSAXParser(validation.booleanValue(), namespaces.booleanValue()); if (saxParser != null) { try { reader = saxParser.getXMLReader(); } catch (SAXException e) { LOG.error(Messages.format("conf.configurationError", e)); } } } if (reader == null) { if ((readerClassName == null) || (readerClassName.length() == 0) || (readerClassName.equalsIgnoreCase("xerces"))) { readerClassName = "org.apache.xerces.parsers.SAXParser"; } reader = XMLParserUtils.instantiateXMLReader(readerClassName); } XMLParserUtils.setFeaturesOnXmlReader( _properties.getString(XMLProperties.PARSER_FEATURES, features), _properties.getString(XMLProperties.PARSER_FEATURES_DISABLED, ""), validation.booleanValue(), namespaces.booleanValue(), reader); return reader; } //-- getXMLReader /** * @see org.castor.xml.InternalContext#getPrimitiveNodeType() */ public NodeType getPrimitiveNodeType() { if (_primitiveNodeType != null) { return _primitiveNodeType; } String prop = _properties.getString(XMLProperties.PRIMITIVE_NODE_TYPE, null); if (prop == null) { return null; } _primitiveNodeType = NodeType.getNodeType(prop); return _primitiveNodeType; } //-- getPrimitiveNodeType /** * {@inheritDoc} * @see org.castor.xml.InternalContext#getRegExpEvaluator() */ public RegExpEvaluator getRegExpEvaluator() { if (_regExpEvaluator != null) { return _regExpEvaluator; } String className = _properties.getString(XMLProperties.REG_EXP_CLASS_NAME, ""); if (className.length() == 0) { _regExpEvaluator = null; } else { try { Class<?> regExpEvalClass = Class.forName(className); _regExpEvaluator = (RegExpEvaluator) regExpEvalClass.newInstance(); } catch (ClassNotFoundException e) { throw new RuntimeException( Messages.format("conf.failedInstantiateRegExp", className, e)); } catch (InstantiationException e) { throw new RuntimeException( Messages.format("conf.failedInstantiateRegExp", className, e)); } catch (IllegalAccessException e) { throw new RuntimeException( Messages.format("conf.failedInstantiateRegExp", className, e)); } } return _regExpEvaluator; } // -- getRegExpEvaluator /** * @see org.castor.xml.InternalContext#getSerializer() */ public Serializer getSerializer() { return XMLParserUtils.getSerializer(_properties); } /** * @see org.castor.xml.InternalContext#getOutputFormat() */ public OutputFormat getOutputFormat() { return XMLParserUtils.getOutputFormat(_properties); } /** * Returns the currently configured XMLSerializerFactory instance. * @param serializerFactoryName the class name of the serializer factory * @return XMLSerializerFactory to use by Castor */ protected XMLSerializerFactory getSerializerFactory(final String serializerFactoryName) { return XMLParserUtils.getSerializerFactory(serializerFactoryName); } /** * @see org.castor.xml.InternalContext#getSerializer(java.io.OutputStream) */ public DocumentHandler getSerializer(final OutputStream output) throws IOException { Serializer serializer; DocumentHandler docHandler; serializer = getSerializer(); serializer.setOutputByteStream(output); docHandler = serializer.asDocumentHandler(); if (docHandler == null) { throw new RuntimeException(Messages.format("conf.serializerNotSaxCapable", serializer .getClass().getName())); } return docHandler; } /** * @see org.castor.xml.InternalContext#getSerializer(java.io.Writer) */ public DocumentHandler getSerializer(final Writer output) throws IOException { Serializer serializer; DocumentHandler docHandler; serializer = getSerializer(); serializer.setOutputCharStream(output); docHandler = serializer.asDocumentHandler(); if (docHandler == null) { throw new RuntimeException(Messages.format("conf.serializerNotSaxCapable", serializer .getClass().getName())); } return docHandler; } /** * @see org.castor.xml.InternalContext#getXMLClassDescriptorResolver() */ public XMLClassDescriptorResolver getXMLClassDescriptorResolver() { return _xmlClassDescriptorResolver; } /** * @see org.castor.xml.InternalContext#getIntrospector() */ public Introspector getIntrospector() { return _introspector; } /** * @see org.castor.xml.InternalContext#getResolverStrategy() */ public ResolverStrategy getResolverStrategy() { return _resolverStrategy; } /** * @see org.castor.xml.InternalContext#setResolverStrategy(org.exolab.castor.xml.util.ResolverStrategy) */ public void setResolverStrategy(final ResolverStrategy resolverStrategy) { _resolverStrategy = resolverStrategy; } /** * @see org.castor.xml.InternalContext#setMappingLoader(org.exolab.castor.mapping.MappingLoader) */ public void setMappingLoader(final MappingLoader mappingLoader) { _mappingLoader = mappingLoader; } /** * @see org.castor.xml.InternalContext#getMappingLoader() */ public MappingLoader getMappingLoader() { return _mappingLoader; } /** * @see org.castor.xml.InternalContext#setJavaNaming(org.castor.xml.JavaNaming) */ public void setJavaNaming(final JavaNaming javaNaming) { _javaNaming = javaNaming; } public void setJavaNaming(final String javaNamingProperty) { if (javaNamingProperty == null || javaNamingProperty.length() == 0) { _javaNaming = new JavaNamingImpl(); } else { try { Class<JavaNaming> cls = (Class<JavaNaming>) Class.forName(javaNamingProperty); _javaNaming = cls.newInstance(); } catch (Exception e) { IllegalArgumentException iae = new IllegalArgumentException( "Failed to load JavaNaming: " + e); LOG.warn(iae.getMessage()); throw iae; } } } /** * @see org.castor.xml.InternalContext#setXMLNaming(org.castor.xml.XMLNaming) */ public void setXMLNaming(final XMLNaming xmlNaming) { _xmlNaming = xmlNaming; // propagate to e.g. Introspector also!! if (_introspector != null) { _introspector.setNaming(_xmlNaming); } } /** * This XMLNaming setter is meant to be used when working in property style * instead of setting an XMLNaming implementation. * @param xmlNamingProperty to set the XMLNaming property as read from configuration */ public void setXMLNaming(final String xmlNamingProperty) { if ((xmlNamingProperty == null) || (xmlNamingProperty.equalsIgnoreCase("lower"))) { setXMLNaming(new DefaultNaming()); } else if (xmlNamingProperty.equalsIgnoreCase("mixed")) { DefaultNaming dn = new DefaultNaming(); dn.setStyle(DefaultNaming.MIXED_CASE_STYLE); setXMLNaming(dn); } else { try { Class<XMLNaming> cls = (Class<XMLNaming>) Class.forName(xmlNamingProperty); setXMLNaming(cls.newInstance()); } catch (Exception e) { IllegalArgumentException iae = new IllegalArgumentException( "Failed to load XMLNaming: " + e); LOG.warn(iae.getMessage()); throw iae; } } if (_xmlNaming == null) { IllegalArgumentException iae = new IllegalArgumentException( "Failed to correctly set XMLNaming; property was: " + xmlNamingProperty); LOG.warn(iae.getMessage()); throw iae; } } /** * @see org.castor.xml.InternalContext#setProperty(java.lang.String, boolean) */ public void setProperty(final String propertyName, final boolean value) { _properties.put(propertyName, Boolean.valueOf(value)); } /** * @see org.castor.xml.InternalContext#getBooleanProperty(java.lang.String) */ public Boolean getBooleanProperty(final String propertyName) { return _properties.getBoolean(propertyName); } /** * @see org.castor.xml.InternalContext#getStringProperty(java.lang.String) */ public String getStringProperty(final String propertyName) { return _properties.getString(propertyName); } /** * @see org.castor.xml.InternalContext#setClassLoader(java.lang.ClassLoader) */ public void setClassLoader(final ClassLoader classLoader) { _classLoader = classLoader; if (_xmlClassDescriptorResolver != null) { _xmlClassDescriptorResolver.setClassLoader(classLoader); } } /** * @see org.castor.xml.InternalContext#setXMLClassDescriptorResolver(org.exolab.castor.xml.XMLClassDescriptorResolver) */ public void setXMLClassDescriptorResolver( final XMLClassDescriptorResolver xmlClassDescriptorResolver) { _xmlClassDescriptorResolver = xmlClassDescriptorResolver; } /** * @see org.castor.xml.InternalContext#setIntrospector(org.exolab.castor.xml.Introspector) */ public void setIntrospector(final Introspector introspector) { _introspector = introspector; } /** * @see org.castor.xml.InternalContext#getClassLoader() */ public ClassLoader getClassLoader() { return _classLoader; } /** * @see org.castor.xml.InternalContext#getLenientIdValidation() */ public boolean getLenientIdValidation() { Boolean lenientIdValidation = _properties.getBoolean(XMLProperties.LENIENT_ID_VALIDATION); if (lenientIdValidation == null) { String message = "Property lenientIdValidation must not be null"; LOG.warn(message); throw new IllegalStateException(message); } return lenientIdValidation.booleanValue(); } /** * @see org.castor.xml.InternalContext#getLenientSequenceOrder() */ public boolean getLenientSequenceOrder() { Boolean lenientSequenceOrder = _properties.getBoolean(XMLProperties.LENIENT_SEQUENCE_ORDER); if (lenientSequenceOrder == null) { String message = "Property lenientSequenceOrder must not be null"; LOG.warn(message); throw new IllegalStateException(message); } return lenientSequenceOrder.booleanValue(); } /** * @see org.castor.xml.InternalContext#getLoadPackageMapping() */ public Boolean getLoadPackageMapping() { return _properties.getBoolean(XMLProperties.LOAD_PACKAGE_MAPPING); } /** * @see org.castor.xml.InternalContext#setLoadPackageMapping(java.lang.Boolean) */ public void setLoadPackageMapping(final Boolean loadPackageMapping) { _properties.put(XMLProperties.LOAD_PACKAGE_MAPPING, loadPackageMapping); } /** * @see org.castor.xml.InternalContext#getUseIntrospector() */ public Boolean getUseIntrospector() { return _properties.getBoolean(XMLProperties.USE_INTROSPECTION); } /** * @see org.castor.xml.InternalContext#setUseIntrospector(java.lang.Boolean) */ public void setUseIntrospector(final Boolean useIntrospector) { _properties.put(XMLProperties.USE_INTROSPECTION, useIntrospector); } /** * @see org.castor.xml.InternalContext#marshallingValidation() */ public boolean marshallingValidation() { Boolean marshallingValidation = _properties.getBoolean(XMLProperties.MARSHALLING_VALIDATION); if (marshallingValidation == null) { String message = "Property marshallingValidation must not be null"; LOG.warn(message); throw new IllegalStateException(message); } return marshallingValidation.booleanValue(); } /** * @see org.castor.xml.InternalContext#strictElements() */ public boolean strictElements() { Boolean strictElements = _properties.getBoolean(XMLProperties.STRICT_ELEMENTS); if (strictElements == null) { String message = "Property strictElements must not be null"; LOG.warn(message); throw new IllegalStateException(message); } return strictElements.booleanValue(); } }