Package org.apache.cocoon.components.parser

Source Code of org.apache.cocoon.components.parser.JaxpParser

/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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.apache.cocoon.components.parser;

import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;

import org.apache.avalon.excalibur.pool.Poolable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.components.resolver.Resolver;
import org.apache.cocoon.util.ClassUtils;
import org.apache.cocoon.xml.AbstractXMLProducer;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;

/**
* An XMLParser that is only dependant on JAXP 1.1 compliant parsers.
*
* The configuration can contain the following parameters :
* <ul>
* <li>validate (boolean, default = <code>false</code>) : should the parser
*     validate parsed documents ?
* </li>
* <li>namespace-prefixes (boolean, default = <code>false</code>) : do we want
*     namespaces declarations also as 'xmlns:' attributes ?<br>
*     <i>Note</i> : setting this to <code>true</code> confuses some XSL
*     processors (e.g. Saxon).
* </li>
* <li>reuse-parsers (boolean, default = <code>true</code>) : do we want to reuse
*     parsers or create a new parser for each parse ?<br>
*     <i>Note</i> : even if this parameter is <code>true</code>, parsers are not
*     recycled in case of parsing errors : some parsers (e.g. Xerces) don't like
*     to be reused after failure.
* </li>
* <li>sax-parser-factory (string, optional) : the name of the <code>SAXParserFactory</code>
*     implementation class to be used instead of using the standard JAXP mechanism
*     (<code>SAXParserFactory.newInstance()</code>). This allows to choose
*     unambiguously the JAXP implementation to be used when several of them are
*     available in the classpath.
* </li>
* <li>document-builder-factory (string, optional) : the name of the
*     <code>DocumentBuilderFactory</code> implementation to be used (similar to
*     <code>sax-parser-factory</code> for DOM).
* </li>
* </ul>
*
* @deprecated The Avalon XML Parser is now used inside Cocoon. This role
*             will be removed in future releases.

* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
* @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
* @version CVS $Id: JaxpParser.java,v 1.4 2004/03/05 13:02:39 bdelacretaz Exp $
*/
public class JaxpParser extends AbstractXMLProducer
implements Parser, ErrorHandler, Composable, Parameterizable, Disposable, Poolable {

    /** the SAX Parser factory */
    protected SAXParserFactory factory;

    /** the Document Builder factory */
    protected DocumentBuilderFactory docFactory;

    /** The SAX reader. It is created lazily by {@link #setupXMLReader()}
        and cleared if a parsing error occurs. */
    protected XMLReader reader;

    /** The DOM builder. It is created lazily by {@link #setupDocumentBuilder()}
        and cleared if a parsing error occurs. */
    protected DocumentBuilder docBuilder;

    /** the component manager */
    protected ComponentManager manager;

    /** the Entity Resolver */
    protected Resolver resolver;

    /** do we want namespaces also as attributes ? */
    protected boolean nsPrefixes;

    /** do we want to reuse parsers ? */
    protected boolean reuseParsers;

    /**
     * Get the Entity Resolver from the component manager
     */
    public void compose(ComponentManager manager)
    throws ComponentException {
        this.manager = manager;
        if ( manager.hasComponent( Resolver.ROLE ) ) {
            if (getLogger().isDebugEnabled()) {
                getLogger().debug("Looking up " + Resolver.ROLE);
            }
            this.resolver = (Resolver)manager.lookup(Resolver.ROLE);
        }
    }

    /**
     * Dispose
     */
    public void dispose() {
        if (this.manager != null) {
            this.manager.release( this.resolver );
        }
    }

    /**
     * Configure
     */
    public void parameterize(Parameters params)
    throws ParameterException  {
        // Validation and namespace prefixes parameters
        boolean validate = params.getParameterAsBoolean("validate", false);
        this.nsPrefixes = params.getParameterAsBoolean("namespace-prefixes", false);
        this.reuseParsers = params.getParameterAsBoolean("reuse-parsers", true);

        // Get the SAXFactory
        String className = params.getParameter("sax-parser-factory", null);
        if (className == null) {
            factory = SAXParserFactory.newInstance();
        } else {
            // Will use specific class
            try {
                Class factoryClass = ClassUtils.loadClass(className);
                factory = (SAXParserFactory)factoryClass.newInstance();
            } catch(Exception e) {
                throw new ParameterException("Cannot load SAXParserFactory class " + className, e);
            }
        }
        factory.setNamespaceAware(true);
        factory.setValidating(validate);

        // Get the DocumentFactory
        className = params.getParameter("document-builder-factory", null);
        if (className == null) {
            this.docFactory = DocumentBuilderFactory.newInstance();
        } else {
            // Will use specific class
            try {
                Class factoryClass = ClassUtils.loadClass(className);
                this.docFactory = (DocumentBuilderFactory)factoryClass.newInstance();
            } catch(Exception e) {
                throw new ParameterException("Cannot load DocumentBuilderFactory class " + className, e);
            }
        }

        docFactory.setNamespaceAware(true);
        docFactory.setValidating(validate);
    }

    public void parse(InputSource in)
    throws SAXException, IOException {
        setupXMLReader();
        try {
            this.reader.setProperty("http://xml.org/sax/properties/lexical-handler", super.lexicalHandler);
        } catch (SAXException e) {
            getLogger().warn("SAX2 driver does not support property: "+
                             "'http://xml.org/sax/properties/lexical-handler'");
        }

        this.reader.setErrorHandler(this);
        this.reader.setContentHandler(super.contentHandler);
        if(this.resolver != null) {
            reader.setEntityResolver(this.resolver);
        }

        // Ensure we will use a fresh new parser at next parse in case of failure
        XMLReader tmpReader = this.reader;
        this.reader = null;

        tmpReader.parse(in);

        // Here, parsing was successful : restore this.reader
        if (this.reuseParsers)
            this.reader = tmpReader;
    }

    /**
     * Create a new Document object.
     */
    public Document newDocument() {
        setupDocumentBuilder();
        return this.docBuilder.newDocument();
    }

    /**
     * Create a new Document object with a specified DOCTYPE.
     */
    public Document newDocument(String name) {
        return this.newDocument(name, null, null);
    }

    /**
     * Create a new Document object with a specified DOCTYPE, public ID and
     * system ID.
     */
    public Document newDocument(String name, String publicId, String systemId) {
        setupDocumentBuilder();
        // Fixme: is there a better way to achieve this?
        DOMImplementation impl = this.docBuilder.newDocument().getImplementation();
        return impl.createDocument(
            null,
            name,
            impl.createDocumentType(name, publicId, systemId)
        );
    }

    /**
     * Parses a new Document object from the given InputSource.
     */
    public Document parseDocument(InputSource input) throws SAXException, IOException {
        setupDocumentBuilder();

        // Ensure we will use a fresh new parser at next parse in case of failure
        DocumentBuilder tmpBuilder = this.docBuilder;
        this.docBuilder = null;

        Document result = tmpBuilder.parse(input);

        // Here, parsing was successful : restore this.builder
        if (this.reuseParsers)
            this.docBuilder = tmpBuilder;

        return result;
    }

    /**
     * Creates a new <code>XMLReader</code> if needed.
     */
    protected void setupXMLReader() throws SAXException {
        if (this.reader == null) {
            // Create the XMLReader
            try {
                this.reader = factory.newSAXParser().getXMLReader();
                this.reader.setFeature("http://xml.org/sax/features/namespace-prefixes", nsPrefixes);
            } catch(Exception e) {
                getLogger().error("Cannot produce a valid parser", e);
                throw new SAXException("Cannot produce a valid parser", e);
            }
        }
    }

    /**
     * Creates a new <code>DocumentBuilder</code> if needed.
     */
    protected void setupDocumentBuilder() {
        if (this.docBuilder == null) {
            try {
                this.docBuilder = this.docFactory.newDocumentBuilder();
            } catch (ParserConfigurationException pce) {
                getLogger().error("Could not create DocumentBuilder", pce);
                throw new org.apache.avalon.framework.CascadingRuntimeException(
                    "Could not create DocumentBuilder", pce);
            }
        }
    }

    /**
     * Receive notification of a recoverable error.
     */
    public void error(SAXParseException e)
    throws SAXException {
        throw new SAXException("Error parsing "+e.getSystemId()+" (line "+
                               e.getLineNumber()+" col. "+e.getColumnNumber()+
                               "): "+e.getMessage(),e);
    }

    /**
     * Receive notification of a fatal error.
     */
    public void fatalError(SAXParseException e)
    throws SAXException {
        throw new SAXException("Fatal error parsing "+e.getSystemId()+" (line "+
                               e.getLineNumber()+" col. "+e.getColumnNumber()+
                               "): "+e.getMessage(),e);
    }

    /**
     * Receive notification of a warning.
     */
    public void warning(SAXParseException e)
    throws SAXException {
        throw new SAXException("Warning parsing "+e.getSystemId()+" (line "+
                               e.getLineNumber()+" col. "+e.getColumnNumber()+
                               "): "+e.getMessage(),e);
    }
}
TOP

Related Classes of org.apache.cocoon.components.parser.JaxpParser

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.