You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2001/11/07 17:17:50 UTC
cvs commit: xml-cocoon2/src/org/apache/cocoon/components/parser PooledJaxpParser.java
sylvain 01/11/07 08:17:50
Added: src/org/apache/cocoon/components/parser
PooledJaxpParser.java
Log:
Fully pooled parser, with more configuration options. Parsers are reused unless a parsing error has occured.
Revision Changes Path
1.1 xml-cocoon2/src/org/apache/cocoon/components/parser/PooledJaxpParser.java
Index: PooledJaxpParser.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.cocoon.components.parser;
import org.apache.avalon.excalibur.pool.Poolable;
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.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
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.*;
import javax.xml.parsers.*;
import java.io.IOException;
/**
* 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>true</code>) : do we want
* namespaces declarations also as 'xmlns:' attributes ? The Cocoon default
* up to now was <code>true</code>, but this 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 ? Note : even if this parameter
* code 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>
*
* @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 $Revision: 1.1 $ $Date: 2001/11/07 16:17:50 $
*/
public class PooledJaxpParser extends AbstractXMLProducer
implements Parser, ErrorHandler, Composable, Configurable, 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 {
try {
this.manager = manager;
getLogger().debug("Looking up " + Resolver.ROLE);
this.resolver = (Resolver)manager.lookup(Resolver.ROLE);
} catch(ComponentException e) {
// This exception is ok during initialization/startup.
getLogger().debug("JaxpParser: Could not yet find " + Resolver.ROLE);
}
}
/**
* Configure
*/
public void configure(Configuration config)
throws ConfigurationException {
Parameters params = Parameters.fromConfiguration(config);
// Validation and namespace prefixes parameters
boolean validate = params.getParameterAsBoolean("validate", false);
this.nsPrefixes = params.getParameterAsBoolean("namespace-prefixes", true);
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 ConfigurationException("Cannot load SAXParserFactory class " + className, e);
}
}
getLogger().debug("SAXParserFactory: " + ClassUtils.which(factory.getClass()));
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 ConfigurationException("Cannot load DocumentBuilderFactory class " + className, e);
}
}
getLogger().debug("DocumentBuilderFactory: " + ClassUtils.which(docFactory.getClass()));
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);
}
}
----------------------------------------------------------------------
In case of troubles, e-mail: webmaster@xml.apache.org
To unsubscribe, e-mail: cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org