All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.castor.xml.AbstractInternalContext Maven / Gradle / Ivy

Go to download

The core XML data binding framework with support for marshalling Java objects to and unmarshalling from XML documents.

There is a newer version: 1.4.1
Show newest version
/*
 * 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.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

import javax.inject.Inject;
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 Joachim Grueneis
 * @since 1.1.2
 */
public abstract class AbstractInternalContext implements InternalContext {

   private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

   /** 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.
    */
   @Inject
   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();
      // TODO[WG]: remove once injection works
      _javaNaming = new JavaNamingImpl(this);
   }

   /**
    * @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
      this.setPropertyInternal(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(this);
      } else {
         try {
            Class cls = (Class) 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 cls = (Class) 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) {
      this.setPropertyInternal(propertyName, Boolean.valueOf(value));
   }

   private void setPropertyInternal(final String propertyName, final Object value) {
      Object oldValue = this._properties.getObject(propertyName);

      if (oldValue == null) {
         if (value != null) {
            this._properties.put(propertyName, value);
            this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, value);
         }
      } else {
         if (!oldValue.equals(value)) {
            this._properties.put(propertyName, value);
            this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, 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();
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      this.propertyChangeSupport.addPropertyChangeListener(listener);
   }

   public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
      this.propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      this.propertyChangeSupport.removePropertyChangeListener(listener);
   }

   public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
      this.propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy