Package org.exolab.castor.util

Source Code of org.exolab.castor.util.LocalConfiguration

/**
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
*    statements and notices.  Redistributions must also contain a
*    copy of this document.
*
* 2. Redistributions in binary form must reproduce the
*    above copyright notice, this list of conditions and the
*    following disclaimer in the documentation and/or other
*    materials provided with the distribution.
*
* 3. The name "Exolab" must not be used to endorse or promote
*    products derived from this Software without prior written
*    permission of Intalio, Inc.  For written permission,
*    please contact info@exolab.org.
*
* 4. Products derived from this Software may not be called "Exolab"
*    nor may "Exolab" appear in their names without prior written
*    permission of Intalio, Inc. Exolab is a registered
*    trademark of Intalio, Inc.
*
* 5. Due credit should be given to the Exolab Project
*    (http://www.exolab.org/).
*
* THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
* INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 1999-2003 (C) Intalio, Inc. All Rights Reserved.
*
* $Id: LocalConfiguration.java,v 1.8 2004/07/23 20:53:06 snyder Exp $
*/


package org.exolab.castor.util;


import java.util.Properties;
import java.io.OutputStream;
import java.io.Writer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Hashtable;
import java.net.URL;
import org.xml.sax.SAXException;
import org.xml.sax.DocumentHandler;
import org.xml.sax.Parser;
import org.xml.sax.XMLReader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xml.serialize.Serializer;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.Method;
import org.exolab.castor.util.Messages;
import org.exolab.castor.xml.NodeType;
import org.exolab.castor.xml.XMLNaming;
import org.exolab.castor.xml.util.DefaultNaming;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;


/**
* Provides default configuration for Castor components from the
* <tt>castor.properties</tt> configuration file. All Castor features
* rely on the central configuration file.
* <p>
* The configuration file is loaded from the Java <tt>lib</tt>
* directory, the classpath and the Castor JAR. Properties set in the
* classpath file takes precedence over properties set in the Java library
* configuration file and properties set in the Castor JAR, allowing for
* each customization. All three files are named <tt>castor.properties</tt>.
* <p>
* For example, to change the parser in use, specify that all
* documents should be printed with identantion or turn debugging on,
* create a new configuration file in the current directory, instead
* of modifying the global one.
*
* @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
* @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a>
* @version $Revision: 1.8 $ $Date: 2004/07/23 20:53:06 $
*/
public final class LocalConfiguration extends Configuration {

    /**
     * The <a href="http://jakarta.apache.org/commons/logging/">Jakarta
     * Commons Logging</a> instance used for all logging.
     */
    private static final Log _log = LogFactory.getFactory().getInstance(LocalConfiguration.class);

  /**
     * The properties loaded from the local configuration file.
     */
    private Properties   _props;
   
    /**
     * The local configuration values (retrieved from a local properties file)
     */
    private ConfigValues _values = new ConfigValues();

    /**
     * Cache of loaded configurations
     */
    private static Hashtable _configurations = new Hashtable();
   
    /**
     * The full url to the castor.properties file that was loaded
     */
    private String _resourceUrl = null;
   
    /**
     * Creates a new instance of LocalConfiguration
     */
    public LocalConfiguration() {
        super();
        load();
        //-- Disable for now, not needed yet until we work on
        //-- a way to differentiate different configurations
        //-- throughout the framework...
        //String key = (_resourceUrl == null) ? "" : _resourceUrl;
        //_configurations.put(key, this);
    } //-- LocalConfiguration
   
    /**
     * Returns an instance of the LocalConfiguration, if a previous
     * configuration has already been loaded for local resource,
     * it will be returned.
     *
     * @return the LocalConfiguration
     */
    public static synchronized LocalConfiguration getInstance() {
       
        LocalConfiguration config = null;
        URL url = null;
       
        //-- disable for now, it's a huge performance hit, for no gain,
        //-- at the moment anyway. We need to come up with a clean, fast
        //-- way to differentiate between different configurations
        //-- throughout the framework...
        //url = LocalConfiguration.class.getResource("/" + Property.FileName);
       
        String key = "";
        if (url != null) {
            key = url.toString();
        }
        config = (LocalConfiguration)_configurations.get(key);
        if (config == null) {
            config = new LocalConfiguration();
            _configurations.put(key, config);
        }
        return config;
       
    } //-- getInstance
   
   
    /**
     * Returns true if the current configuration has enabled debugging.
     *
     * @return true if the current configuration has enabled debugging,
     * otherwise false.
     */
    public boolean debug()
    {
        getProperties();
        return _values.debug;
       
    } //-- debug

    /**
     * Access to the property specifying whether to apply strictness to elements when
     * unmarshalling. Default is true which means that elements appearing in the
     * XML Documnt which cannot be mapped to a class cause a SAXException to be thrown.
     * If set to false, these 'unknown' elements are ignored
     *
     * @return true if element processing should be "strict".
     */
    public boolean strictElements() {
        getProperties();
        return _values.strictElements;
    } //-- strictElements
   
    /**
     * Returns true if the default configuration specified validation in
     * the marshalling framework.
     */
    public boolean marshallingValidation()
    {
        getProperties();
        return _values.marshallingValidation;
       
    } //-- marshallingValidation
   
    /**
     * Returns the current properties from the configuration file(s).
     * The Properties returned may be empty, but never null.
     *
     * @return The current set of configuration properties.
     */
    public synchronized Properties getProperties()
    {
        if ( _props == null ) {
            load();
        }
        return _props;
    }


    /**
     * Returns the naming conventions to use for the XML framework
     *
     * @return the naming conventions to use for the XML framework    
     */
    public XMLNaming getXMLNaming() {
       
        if (_values.naming != null) return _values.naming;
       
        String prop = getProperty( Property.Naming, null);
        if ((prop == null) || (prop.equalsIgnoreCase("lower"))) {
            _values.naming = new DefaultNaming();
        }
        else if (prop.equalsIgnoreCase("mixed")) {
            DefaultNaming dn = new DefaultNaming();
            dn.setStyle(DefaultNaming.MIXED_CASE_STYLE);
            _values.naming = dn;
        }
        else {
            try {
                Class cls = Class.forName(prop);
                _values.naming = (XMLNaming) cls.newInstance();
            }
            catch (Exception except) {
                throw new RuntimeException("Failed to load XMLNaming: " +
                    except);
            }
        }
        return _values.naming;
    } //-- getXMLNaming
   
    /**
     * Return an XML document parser implementing the feature list
     * specified in the configuration file.
     *
     * @return A suitable XML parser
     */
    public Parser getParser()
    {
        return getParser( null );
    }


    /**
     * Returns an XML document parser implementing the requested
     * set of features. The feature list is a comma separated list
     * of features that parser may or may not support. No errors are
     * generated for unsupported features. If the feature list is not
     * null, it overrides the default feature list specified in the
     * configuration file, including validation and Namespaces.
     *
     * @param features The requested feature list, null for the
     *   defaults
     * @return A suitable XML parser
     */
    public Parser getParser( String features )
    {
        String prop;
        Parser parser;
       
        //-- validation?
        prop = getProperties().getProperty( Property.ParserValidation, "false" );
        boolean validation = ( prop.equalsIgnoreCase( "true" ) ||
                               prop.equalsIgnoreCase( "on" ) );
                              
        //-- namespaces?
        prop = getProperties().getProperty( Property.Namespaces, "false" );
        boolean namespaces = ( prop.equalsIgnoreCase( "true" ) ||
                               prop.equalsIgnoreCase( "on" ) );
       

        //-- which parser?
        prop = getProperties().getProperty( Property.Parser );
        if (( prop == null ) || (prop.length() == 0)) {
            // If no parser class was specified, check for JAXP
            // otherwise we default to Xerces.
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setNamespaceAware(namespaces);
            factory.setValidating(validation);
            try {
                SAXParser saxParser = factory.newSAXParser();
                return saxParser.getParser();
            }
            catch(ParserConfigurationException pcx) {
                Logger.getSystemLogger().println( Messages.format( "conf.configurationError", pcx ) );
            }
            catch(org.xml.sax.SAXException sx) {
                Logger.getSystemLogger().println( Messages.format( "conf.configurationError", sx ) );
            }
           
        }
       
        if ((prop == null) ||
            (prop.length() == 0) ||
            (prop.equalsIgnoreCase("xerces")))
        {
            prop = "org.apache.xerces.parsers.SAXParser";
        }
       

        // If a parser class was specified, we try to create it and
        // complain about creation error.
        try {
            Class cls;
           
            cls = Class.forName( prop );
            parser = (Parser) cls.newInstance();
        } catch ( Exception except ) {
            throw new RuntimeException( Messages.format( "conf.failedInstantiateParser",
                                                         prop, except ) );
        }

        if ( parser instanceof XMLReader ) {
            StringTokenizer token;
            XMLReader xmlReader = (XMLReader)parser;
            try {
                xmlReader.setFeature( Features.Validation, validation );
                xmlReader.setFeature( Features.Namespaces, namespaces );
                features = getProperties().getProperty( Property.ParserFeatures, features );
                if ( features != null ) {
                    token = new StringTokenizer( features, ", " );
                    while ( token.hasMoreTokens() ) {
                        xmlReader.setFeature( token.nextToken(), true );
                    }
                }
            }
            catch ( SAXException except ) {
                Logger.getSystemLogger().println( Messages.format( "conf.configurationError", except ) );
            }
        }
        return parser;
       
    }
   
    /**
     * Returns an XML document parser implementing the requested
     * set of features. The feature list is a comma separated list
     * of features that parser may or may not support. No errors are
     * generated for unsupported features. If the feature list is not
     * null, it overrides the default feature list specified in the
     * configuration file, including validation and Namespaces.
     *
     * @return A suitable XML parser
     */
    public XMLReader getXMLReader()
    {
        return getXMLReader( null ) ;
       
    } //-- getXMLReader
   
    /**
     * Returns an XML document parser implementing the requested
     * set of features. The feature list is a comma separated list
     * of features that parser may or may not support. No errors are
     * generated for unsupported features. If the feature list is not
     * null, it overrides the default feature list specified in the
     * configuration file, including validation and Namespaces.
     *
     * @return A suitable XML parser
     */
    public XMLReader getXMLReader( String features )
    {
       
        String prop;
        XMLReader reader = null;
       
        //-- validation?
        prop = getProperties().getProperty( Property.ParserValidation, "false" );
        boolean validation = ( prop.equalsIgnoreCase( "true" ) ||
                               prop.equalsIgnoreCase( "on" ) );
                              
        //-- namespaces?
        prop = getProperties().getProperty( Property.Namespaces, "false" );
        boolean namespaces = ( prop.equalsIgnoreCase( "true" ) ||
                               prop.equalsIgnoreCase( "on" ) );
       

        //-- which parser?
        prop = getProperties().getProperty( Property.Parser );
        if (( prop == null ) || (prop.length() == 0)) {
            // If no parser class was specified, check for JAXP
            // otherwise we default to Xerces.
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setNamespaceAware(namespaces);
            factory.setValidating(validation);
            try {
                SAXParser saxParser = factory.newSAXParser();
                reader = saxParser.getXMLReader();
            }
            catch(ParserConfigurationException pcx) {
                Logger.getSystemLogger().println( Messages.format( "conf.configurationError", pcx ) );
            }
            catch(org.xml.sax.SAXException sx) {
                Logger.getSystemLogger().println( Messages.format( "conf.configurationError", sx ) );
            }
           
        }
       
        if (reader == null) {
            if ((prop == null) ||
                (prop.length() == 0) ||
                (prop.equalsIgnoreCase("xerces")))
            {
                prop = "org.apache.xerces.parsers.SAXParser";
            }
       

            // If a parser class was specified, we try to create it and
            // complain about creation error.
            try {
                Class cls;
               
                cls = Class.forName( prop );
                reader = (XMLReader) cls.newInstance();
            } catch ( Exception except ) {
                throw new RuntimeException( Messages.format( "conf.failedInstantiateParser",
                                                            prop, except ) );
            }
        }

        StringTokenizer token;
        try {
            reader.setFeature( Features.Validation, validation );
            reader.setFeature( Features.Namespaces, namespaces );
            features = getProperties().getProperty( Property.ParserFeatures, features );
            if ( features != null ) {
                token = new StringTokenizer( features, ", " );
                while ( token.hasMoreTokens() ) {
                    reader.setFeature( token.nextToken(), true );
                }
            }
        }
        catch ( SAXException except ) {
            Logger.getSystemLogger().println( Messages.format( "conf.configurationError", except ) );
        }
        return reader;
       
    } //-- getXMLReader
   

    /**
     * Returns the NodeType to use for Java primitives.
     * A null value will be returned if no NodeType was specified,
     * indicating the default NodeType should be used.
     *
     * @return the NodeType assigned to Java primitives, or null
     * if no NodeType was specified.
    **/
    public NodeType getPrimitiveNodeType() {
       
        if (_values.primitiveNodeType != null)
            return _values.primitiveNodeType;
           
        String prop = getProperty(Property.PrimitiveNodeType, null);
        if (prop == null)
            return null;
        else {
            _values.primitiveNodeType = NodeType.getNodeType(prop);
            return _values.primitiveNodeType;
        }
    } //-- getPrimitiveNodeType
   
    /**
     * Returns a new instance of the specified Regular Expression
     * Evaluator, or null if no validator was specified
     *
     * @return the regular expression evaluator,
     *
    **/
    public RegExpEvaluator getRegExpEvaluator() {

        String prop = getProperties().getProperty( Property.RegExp );

        RegExpEvaluator regex = null;

        if ( prop == null ) {
            return null;
        }
        else {
            try {
                if (_values.regExpEvalClass == null) {
                    _values.regExpEvalClass = Class.forName( prop );
                }
                regex = (RegExpEvaluator) _values.regExpEvalClass.newInstance();
            }
            catch ( Exception except ) {
                throw new RuntimeException( Messages.format( "conf.failedInstantiateRegExp",
                                                             prop, except ) );
            }
        }

        return regex;
    } //-- getRegExpEvaluator

    /**
     * Returns a default serializer for producing an XML document.
     * The caller can specify an alternative output format, may reuse
     * this serializer across several streams, and may serialize both
     * DOM and SAX events. If such control is not required, it is
     * recommended to call one of the other two methods.
     *
     * @return A suitable serializer
     */
    public Serializer getSerializer()
    {
        String     prop;
        Serializer serializer;

        prop = _props.getProperty( Property.Serializer );
        if ( prop == null || prop.equalsIgnoreCase( "xerces" ) ) {
            // If no parser class was specified, we default to Xerces.
            serializer = new org.apache.xml.serialize.XMLSerializer();
        } else {
            try {
                serializer = (Serializer) Class.forName( prop ).newInstance();
            } catch ( Exception except ) {
                throw new RuntimeException( Messages.format( "conf.failedInstantiateSerializer",
                                                             prop, except ) );
            }
        }
        serializer.setOutputFormat( getOutputFormat() );
        return serializer;
    }

    /**
     * Returns the default OutputFormat for use with a Serializer.
     *
     * @return the default OutputFormat
    **/
    public OutputFormat getOutputFormat() {

        boolean indent = false;
        String prop = _props.getProperty( Property.Indent, "" );

        //-- get default indentation
        indent = ( prop.equalsIgnoreCase( TRUE_VALUE ) ||
                   prop.equalsIgnoreCase( ON_VALUE ) );

        OutputFormat format = new OutputFormat();
        format.setMethod(Method.XML);
        format.setIndenting(indent);
       
        // There is a bad interaction between the indentation and the
        // setPreserveSpace option. The indentated output is strangely indented.
        if (!indent)
            format.setPreserveSpace(true);

        return format;
    } //-- getOutputFormat


    /**
     * Returns a default serializer for producing an XML document to
     * the designated output stream using the default serialization
     * format.
     *
     * @param output The output stream
     * @return A suitable serializer
     */
    public DocumentHandler getSerializer( 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;
    }


    /**
     * Returns a default serializer for producing an XML document to
     * the designated output stream using the default serialization
     * format.
     *
     * @param output The output stream
     * @return A suitable serializer
     */
    public DocumentHandler getSerializer( 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;
    }

    /**
     * Calls {@link #getDefault} to load the configuration the
     * first time and then looks for a local configuration to
     * merge in with the defaults. Will not complain about inability
     * to load local configuration file from one of the default
     * directories, but if it cannot find the JAR's configuration file,
     * will throw a run time exception.
     */
    protected void load()
    {
        //-- load default properties
        _props = new Properties(getDefault());
       
        try {
        loadProperties( Property.FileName );
    }
    catch(FileNotFoundException fnfe) {
        //-- Ignore, simply no user supplied castor.properties file.
        //-- If no default castor.properties is found an exception
        //-- will occur in the above call to super.load.
    }

        String     prop;
        prop = _props.getProperty( Property.Debug, "" );
        if ( prop.equalsIgnoreCase( "true" ) || prop.equalsIgnoreCase( "on" ) )
            _values.debug = true;
        prop = _props.getProperty( Property.MarshallingValidation, "" );
        if ( prop.equalsIgnoreCase( "false" ) || prop.equalsIgnoreCase( "off" ) )
            _values.marshallingValidation = false;

        prop = _props.getProperty( Property.StrictElements, "" );
        if ( prop.equalsIgnoreCase( "false" ) || prop.equalsIgnoreCase( "off" ) )
            _values.strictElements = false;
        else
            _values.strictElements = true;

        prop = null;
    }

    /**
     * Load the configuration will not complain about inability to load
     * configuration file from one of the default directories, but if
     * it cannot find the JAR's configuration file, will throw a
     * run time exception.
     */
  public void loadProperties(String fileOrResourceName)
      throws FileNotFoundException
  {
     

        boolean found = false;
       
        // Get overriding configuration from the classpath,
        // ignore if not found. If found, merge any existing
        // properties.
        try {     
            URL url = getClass().getResource("/" + fileOrResourceName);
            if (url != null) {
                _resourceUrl = url.toString();
                _log.debug ("Trying to load configuration file from " + _resourceUrl);
                _props.load( url.openStream() );
                //-- debug information
                //System.out.println("merging local configuration: " + url.toExternalForm());
                //-- end debug information
                found = true;
            }     
        } catch ( Exception except ) {
            // Do nothing
        }
       
        //-- if not found, either it doesn't exist, or "." is not part of the
        //-- class path, try looking at local working directory
        if (!found) {
            try {     
                File file = new File(fileOrResourceName);
                if (file.exists() && file.canRead()) {
                    InputStream is = new FileInputStream(file);
                    _props.load( is );
                    is.close();
                    found = true;
                }
            } catch ( Exception except ) {
                //-- do nothing
            }
        }
       


        //-- Cannot find any castor.properties file(s).
        //if (!found) {
        //    throw new FileNotFoundException(fileOrResourceName);
        //}
  }
 
 

} //-- LocalConfiguration
TOP

Related Classes of org.exolab.castor.util.LocalConfiguration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.