org.exist.util.XMLReaderObjectFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.exist.util.XMLReaderObjectFactory.java

Source

/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2009 The eXist Project
 *  http://exist-db.org
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  $Id$
 */
package org.exist.util;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.pool.BasePoolableObjectFactory;

import org.apache.log4j.Logger;

import org.exist.Namespaces;
import org.exist.storage.BrokerPool;
import org.exist.validation.GrammarPool;
import org.exist.validation.resolver.eXistXMLCatalogResolver;

import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;

/**
 * Factory to create new XMLReader objects on demand. The factory is used
 * by {@link org.exist.util.XMLReaderPool}.
 *
 * @author wolf
 */
public class XMLReaderObjectFactory extends BasePoolableObjectFactory {

    private final static Logger LOG = Logger.getLogger(XMLReaderObjectFactory.class);

    public static enum VALIDATION_SETTING {
        UNKNOWN, ENABLED, AUTO, DISABLED
    };

    public final static String CONFIGURATION_ENTITY_RESOLVER_ELEMENT_NAME = "entity-resolver";
    public final static String CONFIGURATION_CATALOG_ELEMENT_NAME = "catalog";
    public final static String CONFIGURATION_ELEMENT_NAME = "validation";

    //TOO : move elsewhere ?
    public final static String VALIDATION_MODE_ATTRIBUTE = "mode";
    public final static String PROPERTY_VALIDATION_MODE = "validation.mode";
    public final static String CATALOG_RESOLVER = "validation.resolver";
    public final static String CATALOG_URIS = "validation.catalog_uris";
    public final static String GRAMMER_POOL = "validation.grammar_pool";

    // Xerces feature and property names
    public final static String APACHE_FEATURES_VALIDATION_SCHEMA = "http://apache.org/xml/features/validation/schema";
    public final static String APACHE_PROPERTIES_INTERNAL_GRAMMARPOOL = "http://apache.org/xml/properties/internal/grammar-pool";
    public final static String APACHE_PROPERTIES_LOAD_EXT_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
    public final static String APACHE_PROPERTIES_ENTITYRESOLVER = "http://apache.org/xml/properties/internal/entity-resolver";

    public final static String APACHE_PROPERTIES_NONAMESPACESCHEMALOCATION = "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation";

    private BrokerPool pool;

    /**
     *
     */
    public XMLReaderObjectFactory(BrokerPool pool) {
        super();
        this.pool = pool;
    }

    /**
     * @see org.apache.commons.pool.BasePoolableObjectFactory#makeObject()
     */
    public Object makeObject() throws Exception {
        final Configuration config = pool.getConfiguration();

        // Get validation settings
        final String option = (String) config.getProperty(PROPERTY_VALIDATION_MODE);
        final VALIDATION_SETTING validation = convertValidationMode(option);

        final GrammarPool grammarPool = (GrammarPool) config.getProperty(XMLReaderObjectFactory.GRAMMER_POOL);

        final eXistXMLCatalogResolver resolver = (eXistXMLCatalogResolver) config.getProperty(CATALOG_RESOLVER);

        final XMLReader xmlReader = createXmlReader(validation, grammarPool, resolver);

        setReaderValidationMode(validation, xmlReader);

        return xmlReader;
    }

    /**
     * Create Xmlreader and setup validation
     */
    public static XMLReader createXmlReader(VALIDATION_SETTING validation, GrammarPool grammarPool,
            eXistXMLCatalogResolver resolver) throws ParserConfigurationException, SAXException {

        // Create a xmlreader
        final SAXParserFactory saxFactory = ExistSAXParserFactory.getSAXParserFactory();

        if (validation == VALIDATION_SETTING.AUTO || validation == VALIDATION_SETTING.ENABLED) {
            saxFactory.setValidating(true);
        } else {
            saxFactory.setValidating(false);
        }
        saxFactory.setNamespaceAware(true);

        final SAXParser saxParser = saxFactory.newSAXParser();
        final XMLReader xmlReader = saxParser.getXMLReader();

        // Setup grammar cache
        if (grammarPool != null) {
            setReaderProperty(xmlReader, APACHE_PROPERTIES_INTERNAL_GRAMMARPOOL, grammarPool);
        }

        // Setup xml catalog resolver
        if (resolver != null) {
            setReaderProperty(xmlReader, APACHE_PROPERTIES_ENTITYRESOLVER, resolver);
        }

        return xmlReader;
    }

    /**
     * Convert configuration text (yes,no,true,false,auto) into a magic number.
     */
    public static VALIDATION_SETTING convertValidationMode(String option) {
        VALIDATION_SETTING mode = VALIDATION_SETTING.AUTO;
        if (option != null) {
            if ("true".equals(option) || "yes".equals(option)) {
                mode = VALIDATION_SETTING.ENABLED;

            } else if ("auto".equals(option)) {
                mode = VALIDATION_SETTING.AUTO;

            } else {
                mode = VALIDATION_SETTING.DISABLED;
            }
        }
        return mode;
    }

    /**
     * Setup validation mode of xml reader.
     */
    public static void setReaderValidationMode(VALIDATION_SETTING validation, XMLReader xmlReader) {

        if (validation == VALIDATION_SETTING.UNKNOWN) {
            return;
        }

        // Configure xmlreader see http://xerces.apache.org/xerces2-j/features.html
        setReaderFeature(xmlReader, Namespaces.SAX_NAMESPACES_PREFIXES, true);

        setReaderFeature(xmlReader, Namespaces.SAX_VALIDATION,
                validation == VALIDATION_SETTING.AUTO || validation == VALIDATION_SETTING.ENABLED);

        setReaderFeature(xmlReader, Namespaces.SAX_VALIDATION_DYNAMIC, validation == VALIDATION_SETTING.AUTO);

        setReaderFeature(xmlReader, APACHE_FEATURES_VALIDATION_SCHEMA,
                (validation == VALIDATION_SETTING.AUTO || validation == VALIDATION_SETTING.ENABLED));

        setReaderFeature(xmlReader, APACHE_PROPERTIES_LOAD_EXT_DTD,
                (validation == VALIDATION_SETTING.AUTO || validation == VALIDATION_SETTING.ENABLED));

        // Attempt to make validation function equal to insert mode
        //saxFactory.setFeature(Namespaces.SAX_NAMESPACES_PREFIXES, true);
    }

    private static void setReaderFeature(XMLReader xmlReader, String featureName, boolean value) {
        try {
            xmlReader.setFeature(featureName, value);

        } catch (final SAXNotRecognizedException ex) {
            LOG.error("SAXNotRecognizedException: " + ex.getMessage());

        } catch (final SAXNotSupportedException ex) {
            LOG.error("SAXNotSupportedException:" + ex.getMessage());
        }
    }

    private static void setReaderProperty(XMLReader xmlReader, String propertyName, Object object) {
        try {
            xmlReader.setProperty(propertyName, object);

        } catch (final SAXNotRecognizedException ex) {
            LOG.error("SAXNotRecognizedException: " + ex.getMessage());

        } catch (final SAXNotSupportedException ex) {
            LOG.error("SAXNotSupportedException:" + ex.getMessage());
        }
    }

}