/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 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 end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``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 THE APACHE SOFTWARE FOUNDATION 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.apache.org.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

package org.apache.xerces.framework;

import java.io.InputStream;
import java.io.IOException;
import java.io.Reader;
import java.util.Locale;

import org.apache.xerces.readers.DefaultEntityHandler;
import org.apache.xerces.readers.XMLDeclRecognizer;
import org.apache.xerces.readers.XMLEntityHandler;
import org.apache.xerces.readers.XMLEntityReaderFactory;
import org.apache.xerces.utils.ChunkyCharArray;
import org.apache.xerces.utils.StringPool;
import org.apache.xerces.utils.XMLMessageProvider;
import org.apache.xerces.utils.XMLMessages;
import org.apache.xerces.utils.ImplementationMessages;
import org.apache.xerces.validators.common.GrammarResolver;
import org.apache.xerces.validators.common.GrammarResolverImpl;
import org.apache.xerces.validators.common.XMLValidator;
import org.apache.xerces.validators.datatype.DatatypeMessageProvider;
import org.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl;
import org.apache.xerces.validators.schema.SchemaMessageProvider;

import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;

/**
 * This is the base class of all standard parsers.
 *
 * @version $Id$
 */
public abstract class XMLParser 
    implements XMLErrorReporter, XMLDocumentHandler.DTDHandler {

    //
    // Constants
    //

    // protected

    /** SAX2 features prefix (http://xml.org/sax/features/). */
    protected static final String SAX2_FEATURES_PREFIX = "http://xml.org/sax/features/";

    /** SAX2 properties prefix (http://xml.org/sax/properties/). */
    protected static final String SAX2_PROPERTIES_PREFIX = "http://xml.org/sax/properties/";

    /** Xerces features prefix (http://apache.org/xml/features/). */
    protected static final String XERCES_FEATURES_PREFIX = "http://apache.org/xml/features/";

    /** Xerces properties prefix (http://apache.org/xml/properties/). */
    protected static final String XERCES_PROPERTIES_PREFIX = "http://apache.org/xml/properties/";

    // private

    /** Features recognized by this parser. */
    private static final String RECOGNIZED_FEATURES[] = {
        // SAX2 core
        "http://xml.org/sax/features/validation",
        "http://xml.org/sax/features/external-general-entities",
        "http://xml.org/sax/features/external-parameter-entities",
        "http://xml.org/sax/features/namespaces",
        // Xerces
        "http://apache.org/xml/features/validation/schema",
        "http://apache.org/xml/features/validation/dynamic",
        "http://apache.org/xml/features/validation/default-attribute-values",
        "http://apache.org/xml/features/validation/validate-content-models",
        "http://apache.org/xml/features/validation/validate-datatypes",
        "http://apache.org/xml/features/validation/warn-on-duplicate-attdef",
        "http://apache.org/xml/features/validation/warn-on-undeclared-elemdef",
        "http://apache.org/xml/features/allow-java-encodings",
        "http://apache.org/xml/features/continue-after-fatal-error",
        "http://apache.org/xml/features/nonvalidating/load-dtd-grammar"
    };

    /** Properties recognized by this parser. */
    private static final String RECOGNIZED_PROPERTIES[] = {
        // SAX2 core
        "http://xml.org/sax/properties/xml-string",
        // Xerces
    };

    // debugging

    /** Set to true and recompile to print exception stack trace. */
    private static final boolean PRINT_EXCEPTION_STACK_TRACE = false;

    //
    // Data
    //

    protected GrammarResolver fGrammarResolver = null;

    // state

    protected boolean fParseInProgress = false;
    private boolean fNeedReset = false;

    // features

    /** Continue after fatal error. */
    private boolean fContinueAfterFatalError = false;

    // properties

    /** Error handler. */
    private ErrorHandler fErrorHandler = null;

    // other

    private Locale fLocale = null;

    // error information

    private static XMLMessageProvider fgXMLMessages = new XMLMessages();
    private static XMLMessageProvider fgImplementationMessages = new ImplementationMessages();
    private static XMLMessageProvider fgSchemaMessages = new SchemaMessageProvider();
    private static XMLMessageProvider fgDatatypeMessages= new DatatypeMessageProvider();

    //
    //
    //
    protected StringPool fStringPool = null;
    protected XMLErrorReporter fErrorReporter = null;
    protected DefaultEntityHandler fEntityHandler = null;
    protected XMLDocumentScanner fScanner = null;
    protected XMLValidator fValidator = null;

    //
    // Constructors
    //

    /**
     * Constructor
     */
    protected XMLParser() {
        fStringPool = new StringPool();
        fErrorReporter = this;
        fEntityHandler = new DefaultEntityHandler(fStringPool, fErrorReporter);
        fScanner = new XMLDocumentScanner(fStringPool, fErrorReporter, fEntityHandler, new ChunkyCharArray(fStringPool));
        fValidator = new XMLValidator(fStringPool, fErrorReporter, fEntityHandler, fScanner);
        fGrammarResolver = new GrammarResolverImpl();
        fScanner.setGrammarResolver(fGrammarResolver);
        fValidator.setGrammarResolver(fGrammarResolver);
        try {
            //JR-defect 48 fix - turn on Namespaces
            setNamespaces(true);
        }
        catch (Exception e) {
            // ignore
        }
    }

    /**
     * Set char data processing preference and handlers.
     */
    protected void initHandlers(boolean sendCharDataAsCharArray,
                                XMLDocumentHandler docHandler,
                                XMLDocumentHandler.DTDHandler dtdHandler)
    {
        fValidator.initHandlers(sendCharDataAsCharArray, docHandler, dtdHandler);
        fScanner.setDTDHandler(this);
    }

    //
    // Public methods
    //

    // features and properties

    /**
     * Returns a list of features that this parser recognizes.
     * This method will never return null; if no features are
     * recognized, this method will return a zero length array.
     *
     * @see #isFeatureRecognized
     * @see #setFeature
     * @see #getFeature
     */
    public String[] getFeaturesRecognized() {
        return RECOGNIZED_FEATURES;
    }

    /**
     * Returns true if the specified feature is recognized.
     *
     * @see #getFeaturesRecognized
     * @see #setFeature
     * @see #getFeature
     */
    public boolean isFeatureRecognized(String featureId) {
        String[] recognizedFeatures = getFeaturesRecognized();
        for (int i = 0; i < recognizedFeatures.length; i++) {
            if (featureId.equals(recognizedFeatures[i]))
                return true;
        }
        return false;
    }

    /**
     * Returns a list of properties that this parser recognizes.
     * This method will never return null; if no properties are
     * recognized, this method will return a zero length array.
     *
     * @see #isPropertyRecognized
     * @see #setProperty
     * @see #getProperty
     */
    public String[] getPropertiesRecognized() {
        return RECOGNIZED_PROPERTIES;
    }

    /**
     * Returns true if the specified property is recognized.
     *
     * @see #getPropertiesRecognized
     * @see #setProperty
     * @see #getProperty
     */
    public boolean isPropertyRecognized(String propertyId) {
        String[] recognizedProperties = getPropertiesRecognized();
        for (int i = 0; i < recognizedProperties.length; i++) {
            if (propertyId.equals(recognizedProperties[i]))
                return true;
        }
        return false;
    }

    // initialization

    /**
     * Setup for application-driven parsing.
     *
     * @param source the input source to be parsed.
     * @see #parseSome
     */
    public boolean parseSomeSetup(InputSource source) throws Exception {
        if (fNeedReset)
            resetOrCopy();
        fParseInProgress = true;
        fNeedReset = true;
        return fEntityHandler.startReadingFromDocument(source);
    }

    /**
     * Application-driven parsing.
     *
     * @see #parseSomeSetup
     */
    public boolean parseSome() throws Exception {
        if (!fScanner.parseSome(false)) {
            fParseInProgress = false;
            return false;
        }
        return true;
    }

    // resetting

    /** Reset parser instance so that it can be reused. */
    public void reset() throws Exception {
        fGrammarResolver.clearGrammarResolver();
        fStringPool.reset();
        fEntityHandler.reset(fStringPool);
        fScanner.reset(fStringPool, new ChunkyCharArray(fStringPool));
        fValidator.reset(fStringPool);
        fNeedReset = false;
    }

    // properties (the normal kind)

    /**
     * return the locator being used by the parser
     *
     * @return the parser's active locator
     */
    public final Locator getLocator() {
        return fEntityHandler;
    }

    /**
     * Set the reader factory.
     */
    public void setReaderFactory(XMLEntityReaderFactory readerFactory) {
        fEntityHandler.setReaderFactory(readerFactory);
    }

    /**
     * Adds a recognizer.
     *
     * @param recognizer The XML recognizer to add.
     */
    public void addRecognizer(XMLDeclRecognizer recognizer) {
        fEntityHandler.addRecognizer(recognizer);
    }

    //
    // Protected methods
    //

    // SAX2 core features

    /**
     * Sets whether the parser validates.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://xml.org/sax/features/validation
     * </pre>
     *
     * @param validate True to validate; false to not validate.
     *
     * @see #getValidation
     * @see #setFeature
     */
    protected void setValidation(boolean validate) 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        if (fParseInProgress) {
            throw new SAXNotSupportedException("PAR004 Cannot setFeature(http://xml.org/sax/features/validation): parse is in progress.\n"+
                                               "http://xml.org/sax/features/validation");
        }
        try {
            // REVISIT: [Q] Should the scanner tell the validator that
            //              validation is on? -Ac
            fScanner.setValidationEnabled(validate);
            fValidator.setValidationEnabled(validate);
        }
        catch (Exception ex) {
            throw new SAXNotSupportedException(ex.getMessage());
        }
    }

    /**
     * Returns true if validation is turned on.
     *
     * @see #setValidation
     */
    protected boolean getValidation() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fValidator.getValidationEnabled();
    }

    /**
     * <b>Note: Currently, this parser always expands external general
     * entities.</b> Setting this feature to false will throw a
     * SAXNotSupportedException.
     * <p>
     * Sets whether external general entities are expanded.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://xml.org/sax/features/external-general-entities
     * </pre>
     *
     * @param expand True to expand external general entities; false
     *               to not expand.
     *
     * @see #getExternalGeneralEntities
     * @see #setFeature
     */
    protected void setExternalGeneralEntities(boolean expand)
        throws SAXNotRecognizedException, SAXNotSupportedException {
        if (fParseInProgress) {
            throw new SAXNotSupportedException("PAR004 Cannot setFeature(http://xml.org/sax/features/external-general-entities): parse is in progress.\n"+
                                               "http://xml.org/sax/features/external-general-entities");
        }
        if (!expand) {
            throw new SAXNotSupportedException("http://xml.org/sax/features/external-general-entities");
        }
    }

    /**
     * <b>Note: This feature is always true.</b>
     * <p>
     * Returns true if external general entities are expanded.
     *
     * @see #setExternalGeneralEntities
     */
    protected boolean getExternalGeneralEntities() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return true;
    }

    /**
     * <b>Note: Currently, this parser always expands external parameter
     * entities.</b> Setting this feature to false will throw a
     * SAXNotSupportedException.
     * <p>
     * Sets whether external parameter entities are expanded.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://xml.org/sax/features/external-parameter-entities
     * </pre>
     *
     * @param expand True to expand external parameter entities; false
     *               to not expand.
     *
     * @see #getExternalParameterEntities
     * @see #setFeature
     */
    protected void setExternalParameterEntities(boolean expand)
        throws SAXNotRecognizedException, SAXNotSupportedException {
        if (fParseInProgress) {
            throw new SAXNotSupportedException("PAR004 Cannot setFeature(http://xml.org/sax/features/external-general-entities): parse is in progress.\n"+
                                               "http://xml.org/sax/features/external-general-entities");
        }
        if (!expand) {
            throw new SAXNotSupportedException("http://xml.org/sax/features/external-parameter-entities");
        }
    }

    /**
     * <b>Note: This feature is always true.</b>
     * <p>
     * Returns true if external parameter entities are expanded.
     *
     * @see #setExternalParameterEntities
     */
    protected boolean getExternalParameterEntities() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return true;
    }

    /**
     * Sets whether the parser preprocesses namespaces.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://xml.org/sax/features/namespaces
     * <pre>
     *
     * @param process True to process namespaces; false to not process.
     *
     * @see #getNamespaces
     * @see #setFeature
     */
    protected void setNamespaces(boolean process) 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        if (fParseInProgress) {
            throw new SAXNotSupportedException("PAR004 Cannot setFeature(http://xml.org/sax/features/namespaces): parse is in progress.\n"+
                                               "http://xml.org/sax/features/namespaces");
        }
        fScanner.setNamespacesEnabled(process);
        // REVISIT: [Q] Should the scanner tell the validator that namespace
        //              processing is on? -Ac
        fValidator.setNamespacesEnabled(process);
    }

    /**
     * Returns true if the parser preprocesses namespaces.
     *
     * @see #setNamespaces
     */
    protected boolean getNamespaces() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fValidator.getNamespacesEnabled();
    }

    // Xerces features

    /**
     * Allows the user to turn Schema support on/off.
     * <p>
     * This method is equivalent to the feature:
     * <pre>
     * http://apache.org/xml/features/validation/schema
     * </pre>
     *
     * @param schema True to turn on Schema support; false to turn it off.
     *
     * @see #getValidationSchema
     * @see #setFeature
     */
    protected void setValidationSchema(boolean schema) 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        if (fParseInProgress) {
            // REVISIT: Localize message
            throw new SAXNotSupportedException("http://apache.org/xml/features/validation/schema: parse is in progress");
        }
        fValidator.setSchemaValidationEnabled(schema);
    }

    /**
     * Returns true if Schema support is turned on.
     *
     * @see #setValidationSchema
     */
    protected boolean getValidationSchema() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fValidator.getSchemaValidationEnabled();
    }

    /**
     * Allows the parser to validate a document only when it contains a
     * grammar. Validation is turned on/off based on each document
     * instance, automatically.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://apache.org/xml/features/validation/dynamic
     * </pre>
     *
     * @param dynamic True to dynamically validate documents; false to
     *                validate based on the validation feature.
     *
     * @see #getValidationDynamic
     * @see #setFeature
     */
    protected void setValidationDynamic(boolean dynamic) 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        if (fParseInProgress) {
            // REVISIT: Localize message
            throw new SAXNotSupportedException("http://apache.org/xml/features/validation/dynamic: parse is in progress");
        }
        try {
            fValidator.setDynamicValidationEnabled(dynamic);
        }
        catch (Exception ex) {
            throw new SAXNotSupportedException(ex.getMessage());
        }
    }

    /**
     * Returns true if validation is based on whether a document
     * contains a grammar.
     *
     * @see #setValidationDynamic
     */
    protected boolean getValidationDynamic() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fValidator.getDynamicValidationEnabled();
    }
    /**
     * Allows the parser to have the choice to load DTD grammar when 
     * validation is off.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://apache.org/xml/features/nonvalidating/load-dtd-grammar
     * </pre>
     *
     * @param loadDTDGrammar True to turn on the feature; false to
     *                turn off the feature.
     *
     * @see #getLoadDTDGrammar
     * @see #setFeature
     */
    protected void setLoadDTDGrammar(boolean loadDTDGrammar) 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        if (fParseInProgress) {
            // REVISIT: Localize message
            throw new SAXNotSupportedException("http://apache.org/xml/features/nonvalidating/load-dtd-grammar: parse is in progress");
        }
        try {
            fValidator.setLoadDTDGrammar(loadDTDGrammar);
        }
        catch (Exception ex) {
            throw new SAXNotSupportedException(ex.getMessage());
        }
    }

    /**
     * Returns true if load DTD grammar is turned on in the XMLValiator.
     *
     * @see #setLoadDTDGrammar
     */
    protected boolean getLoadDTDGrammar() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fValidator.getLoadDTDGrammar();
    }

    /**
     * Sets whether an error is emitted when an attribute is redefined
     * in the grammar.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://apache.org/xml/features/validation/warn-on-duplicate-attdef
     * </pre>
     *
     * @param warn True to warn; false to not warn.
     *
     * @see #getValidationWarnOnDuplicateAttdef
     * @see #setFeature
     */
    protected void setValidationWarnOnDuplicateAttdef(boolean warn)
        throws SAXNotRecognizedException, SAXNotSupportedException {
        fValidator.setWarningOnDuplicateAttDef(warn);
    }

    /**
     * Returns true if an error is emitted when an attribute is redefined
     * in the grammar.
     *
     * @see #setValidationWarnOnDuplicateAttdef
     */
    protected boolean getValidationWarnOnDuplicateAttdef()
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fValidator.getWarningOnDuplicateAttDef();
    }

    /**
     * Sets whether the parser emits an error when an element's content
     * model references an element by name that is not declared in the
     * grammar.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://apache.org/xml/features/validation/warn-on-undeclared-elemdef
     * </pre>
     *
     * @param warn True to warn; false to not warn.
     *
     * @see #getValidationWarnOnUndeclaredElemdef
     * @see #setFeature
     */
    protected void setValidationWarnOnUndeclaredElemdef(boolean warn)
        throws SAXNotRecognizedException, SAXNotSupportedException {
        fValidator.setWarningOnUndeclaredElements(warn);
    }

    /**
     * Returns true if the parser emits an error when an undeclared
     * element is referenced in the grammar.
     *
     * @see #setValidationWarnOnUndeclaredElemdef
     */
    protected boolean getValidationWarnOnUndeclaredElemdef()
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fValidator.getWarningOnUndeclaredElements();
    }

    /**
     * Allows the use of Java encoding names in the XMLDecl and TextDecl
     * lines in an XML document.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://apache.org/xml/features/allow-java-encodings
     * </pre>
     *
     * @param allow True to allow Java encoding names; false to disallow.
     *
     * @see #getAllowJavaEncodings
     * @see #setFeature
     */
    protected void setAllowJavaEncodings(boolean allow) 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        fEntityHandler.setAllowJavaEncodings(allow);
    }

    /**
     * Returns true if Java encoding names are allowed in the XML document.
     *
     * @see #setAllowJavaEncodings
     */
    protected boolean getAllowJavaEncodings() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fEntityHandler.getAllowJavaEncodings();
    }

    /**
     * Allows the parser to continue after a fatal error. Normally, a
     * fatal error would stop the parse.
     * <p>
     * This method is the equivalent to the feature:
     * <pre>
     * http://apache.org/xml/features/continue-after-fatal-error
     * </pre>
     *
     * @param continueAfterFatalError True to continue; false to stop on
     *                                fatal error.
     *
     * @see #getContinueAfterFatalError
     * @see #setFeature
     */
    protected void setContinueAfterFatalError(boolean continueAfterFatalError)
        throws SAXNotRecognizedException, SAXNotSupportedException {
        fContinueAfterFatalError = continueAfterFatalError;
    }

    /**
     * Returns true if the parser continues after a fatal error.
     *
     * @see #setContinueAfterFatalError
     */
    protected boolean getContinueAfterFatalError() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fContinueAfterFatalError;
    }

    // SAX2 core properties

    /**
     * Set the separator to be used between the URI part of a name and the
     * local part of a name when namespace processing is being performed
     * (see the http://xml.org/sax/features/namespaces feature).  By default,
     * the separator is a single space.
     * <p>
     * This property may not be set while a parse is in progress (throws a
     * SAXNotSupportedException).
     * <p>
     * This method is the equivalent to the property:
     * <pre>
     * http://xml.org/sax/properties/namespace-sep
     * </pre>
     *
     * @param separator The new namespace separator.
     *
     * @see #getNamespaceSep
     * @see #setProperty
     */
    /***
    protected void setNamespaceSep(String separator) 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        // REVISIT: Ask someone what it could possibly hurt to allow
        //          the application to change this in mid-parse.
        if (fParseInProgress) {
            throw new SAXNotSupportedException("http://xml.org/sax/properties/namespace-sep: parse is in progress");
        }
        fNamespaceSep = separator;
    }
    /***/

    /**
     * Returns the namespace separator.
     *
     * @see #setNamespaceSep
     */
    /***
    protected String getNamespaceSep() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fNamespaceSep;
    }
    /***/

    /**
     * This method is the equivalent to the property:
     * <pre>
     * http://xml.org/sax/properties/xml-string
     * </pre>
     *
     * @see #getProperty
     */
    protected String getXMLString() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        throw new SAXNotSupportedException("http://xml.org/sax/properties/xml-string");
    }

    // resetting

    /**
     * Reset or copy parser
     * Allows parser instance reuse
     */
    protected void resetOrCopy() throws Exception {
        fStringPool = new StringPool();
        fEntityHandler.reset(fStringPool);
        fScanner.reset(fStringPool, new ChunkyCharArray(fStringPool));
        fValidator.resetOrCopy(fStringPool);
        fNeedReset = false;
        fGrammarResolver = new GrammarResolverImpl();
        fScanner.setGrammarResolver(fGrammarResolver);
        fValidator.setGrammarResolver(fGrammarResolver);
        DatatypeValidatorFactoryImpl.getDatatypeRegistry().resetRegistry();
    }

    //
    // Parser/XMLReader methods
    //
    // NOTE: This class does *not* implement the org.xml.sax.Parser
    //       interface but it does share some common methods. -Ac

    // handlers

    /**
     * Sets the resolver used to resolve external entities. The EntityResolver
     * interface supports resolution of public and system identifiers.
     *
     * @param resolver The new entity resolver. Passing a null value will
     *                 uninstall the currently installed resolver.
     */
    public void setEntityResolver(EntityResolver resolver) {
        fEntityHandler.setEntityResolver(resolver);
    }

    /**
     * Return the current entity resolver.
     *
     * @return The current entity resolver, or null if none
     *         has been registered.
     * @see #setEntityResolver
     */
    public EntityResolver getEntityResolver() {
        return fEntityHandler.getEntityResolver();
    }

    /**
     * Sets the error handler.
     *
     * @param handler The new error handler.
     */
    public void setErrorHandler(ErrorHandler handler) {
        fErrorHandler = handler;
    }

    /**
     * Return the current error handler.
     *
     * @return The current error handler, or null if none
     *         has been registered.
     * @see #setErrorHandler
     */
    public ErrorHandler getErrorHandler() {
        return fErrorHandler;
    }

    // parsing

    /**
     * Parses the specified input source.
     *
     * @param source The input source.
     *
     * @exception org.xml.sax.SAXException Throws exception on SAX error.
     * @exception java.io.IOException Throws exception on i/o error.
     */
    public void parse(InputSource source)
        throws SAXException, IOException {

        if (fParseInProgress) {
            throw new org.xml.sax.SAXException("FWK005 parse may not be called while parsing."); // REVISIT - need to add new error message
        }

        try {
            if (parseSomeSetup(source)) {
                fScanner.parseSome(true);
            }
            fParseInProgress = false;
        } catch (org.xml.sax.SAXException ex) {
            fParseInProgress = false;
            if (PRINT_EXCEPTION_STACK_TRACE)
                ex.printStackTrace();
            throw ex;
        } catch (IOException ex) {
            fParseInProgress = false;
            if (PRINT_EXCEPTION_STACK_TRACE)
                ex.printStackTrace();
            throw ex;
        } catch (Exception ex) {
            fParseInProgress = false;
            if (PRINT_EXCEPTION_STACK_TRACE)
                ex.printStackTrace();
            throw new org.xml.sax.SAXException(ex);
        }

    } // parse(InputSource)

    /**
     * Parses the input source specified by the given system identifier.
     * <p>
     * This method is equivalent to the following:
     * <pre>
     *     parse(new InputSource(systemId));
     * </pre>
     *
     * @param source The input source.
     *
     * @exception org.xml.sax.SAXException Throws exception on SAX error.
     * @exception java.io.IOException Throws exception on i/o error.
     */
    public void parse(String systemId)
        throws SAXException, IOException {

        InputSource source = new InputSource(systemId);
        parse(source);
        try {
            Reader reader = source.getCharacterStream();
            if (reader != null) {
                reader.close();
            }
            else {
                InputStream is = source.getByteStream();
                if (is != null) {
                    is.close();
                }
            }
        }
        catch (IOException e) {
            // ignore
        }

    } // parse(String)

    // locale

    /**
     * Set the locale to use for messages.
     *
     * @param locale The locale object to use for localization of messages.
     *
     * @exception SAXException An exception thrown if the parser does not
     *                         support the specified locale.
     *
     * @see org.xml.sax.Parser
     */
    public void setLocale(Locale locale) throws SAXException {

        if (fParseInProgress) {
            throw new org.xml.sax.SAXException("FWK006 setLocale may not be called while parsing"); // REVISIT - need to add new error message
        }

        fLocale = locale;
        fgXMLMessages.setLocale(locale);
        fgImplementationMessages.setLocale(locale);

    } // setLocale(Locale)

    //
    // XMLErrorReporter methods
    //

    /**
     * Report an error.
     *
     * @param locator Location of error.
     * @param errorDomain The error domain.
     * @param majorCode The major code of the error.
     * @param minorCode The minor code of the error.
     * @param args Arguments for replacement text.
     * @param errorType The type of the error.
     *
     * @exception Exception Thrown on error.
     *
     * @see XMLErrorReporter#ERRORTYPE_WARNING
     * @see XMLErrorReporter#ERRORTYPE_FATAL_ERROR
     */
    public void reportError(Locator locator, String errorDomain,
                            int majorCode, int minorCode, Object args[],
                            int errorType) throws Exception {

        // create the appropriate message
        SAXParseException spe;
        if (errorDomain.equals(XMLMessages.XML_DOMAIN)) {
            spe = new SAXParseException(fgXMLMessages.createMessage(fLocale, majorCode, minorCode, args), locator);
        }
        else if (errorDomain.equals(XMLMessages.XMLNS_DOMAIN)) {
            spe = new SAXParseException(fgXMLMessages.createMessage(fLocale, majorCode, minorCode, args), locator);
        }
        else if (errorDomain.equals(ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN)) {
            spe = new SAXParseException(fgImplementationMessages.createMessage(fLocale, majorCode, minorCode, args), locator);
        } else if (errorDomain.equals(SchemaMessageProvider.SCHEMA_DOMAIN)) {
            spe = new SAXParseException(fgSchemaMessages.createMessage(fLocale, majorCode, minorCode, args), locator);
        } else if (errorDomain.equals(DatatypeMessageProvider.DATATYPE_DOMAIN)) {
            spe = new SAXParseException(fgDatatypeMessages.createMessage(fLocale, majorCode, minorCode, args), locator);
        } else {
            throw new RuntimeException("FWK007 Unknown error domain \"" + errorDomain + "\"."+"\n"+errorDomain);
        }

        // default error handling
        if (fErrorHandler == null) {
            if (errorType == XMLErrorReporter.ERRORTYPE_FATAL_ERROR &&
                !fContinueAfterFatalError) {
                throw spe;
            }
            return;
        }

        // make appropriate callback
        if (errorType == XMLErrorReporter.ERRORTYPE_WARNING) {
            fErrorHandler.warning(spe);
        }
        else if (errorType == XMLErrorReporter.ERRORTYPE_FATAL_ERROR) {
            fErrorHandler.fatalError(spe);
            if (!fContinueAfterFatalError) {
                Object[] fatalArgs = { spe.getMessage() };
                throw new SAXException(fgImplementationMessages.createMessage(fLocale, ImplementationMessages.FATAL_ERROR, 0, fatalArgs));
            }
        }
        else {
            fErrorHandler.error(spe);
        }

    } // reportError(Locator,String,int,int,Object[],int)

    //
    // XMLReader methods
    //

    /**
     * Set the state of a feature.
     *
     * Set the state of any feature in a SAX2 parser.  The parser
     * might not recognize the feature, and if it does recognize
     * it, it might not be able to fulfill the request.
     *
     * @param featureId The unique identifier (URI) of the feature.
     * @param state The requested state of the feature (true or false).
     *
     * @exception org.xml.sax.SAXNotRecognizedException If the
     *            requested feature is not known.
     * @exception org.xml.sax.SAXNotSupportedException If the
     *            requested feature is known, but the requested
     *            state is not supported.
     * @exception org.xml.sax.SAXException If there is any other
     *            problem fulfilling the request.
     */
    public void setFeature(String featureId, boolean state)
        throws SAXNotRecognizedException, SAXNotSupportedException {

        //
        // SAX2 Features
        //

        if (featureId.startsWith(SAX2_FEATURES_PREFIX)) {
            String feature = featureId.substring(SAX2_FEATURES_PREFIX.length());
            //
            // http://xml.org/sax/features/validation
            //   Validate (true) or don't validate (false).
            //
            if (feature.equals("validation")) {
                setValidation(state);
                return;
            }
            //
            // http://xml.org/sax/features/external-general-entities
            //   Expand external general entities (true) or don't expand (false).
            //
            if (feature.equals("external-general-entities")) {
                setExternalGeneralEntities(state);
                return;
            }
            //
            // http://xml.org/sax/features/external-parameter-entities
            //   Expand external parameter entities (true) or don't expand (false).
            //
            if (feature.equals("external-parameter-entities")) {
                setExternalParameterEntities(state);
                return;
            }
            //
            // http://xml.org/sax/features/namespaces
            //   Preprocess namespaces (true) or don't preprocess (false).  See also
            //   the http://xml.org/sax/properties/namespace-sep property.
            //
            if (feature.equals("namespaces")) {
                setNamespaces(state);
                return;
            }
            //
            // Not recognized
            //
        }

        //
        // Xerces Features
        //

        else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
            String feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
            //
            // http://apache.org/xml/features/validation/schema
            //   Lets the user turn Schema validation support on/off.
            //
            if (feature.equals("validation/schema")) {
                setValidationSchema(state);
                return;
            }
            //
            // http://apache.org/xml/features/validation/dynamic
            //   Allows the parser to validate a document only when it
            //   contains a grammar. Validation is turned on/off based
            //   on each document instance, automatically.
            //
            if (feature.equals("validation/dynamic")) {
                setValidationDynamic(state);
                return;
            }
            //
            // http://apache.org/xml/features/validation/default-attribute-values
            //
            if (feature.equals("validation/default-attribute-values")) {
                // REVISIT
                throw new SAXNotSupportedException(featureId);
            }
            //
            // http://apache.org/xml/features/validation/default-attribute-values
            //
            if (feature.equals("validation/validate-content-models")) {
                // REVISIT
                throw new SAXNotSupportedException(featureId);
            }
            //
            // http://apache.org/xml/features/validation/nonvalidating/load-dtd-grammar
            //
            if (feature.equals("nonvalidating/load-dtd-grammar")) {
                setLoadDTDGrammar(state);
                return;
            }

            //
            // http://apache.org/xml/features/validation/default-attribute-values
            //
            if (feature.equals("validation/validate-datatypes")) {
                // REVISIT
                throw new SAXNotSupportedException(featureId);
            }
            //
            // http://apache.org/xml/features/validation/warn-on-duplicate-attdef
            //   Emits an error when an attribute is redefined.
            //
            if (feature.equals("validation/warn-on-duplicate-attdef")) {
                setValidationWarnOnDuplicateAttdef(state);
                return;
            }
            //
            // http://apache.org/xml/features/validation/warn-on-undeclared-elemdef
            //   Emits an error when an element's content model
            //   references an element, by name, that is not declared
            //   in the grammar.
            //
            if (feature.equals("validation/warn-on-undeclared-elemdef")) {
                setValidationWarnOnUndeclaredElemdef(state);
                return;
            }
            //
            // http://apache.org/xml/features/allow-java-encodings
            //   Allows the use of Java encoding names in the XML
            //   and TextDecl lines.
            //
            if (feature.equals("allow-java-encodings")) {
                setAllowJavaEncodings(state);
                return;
            }
            //
            // http://apache.org/xml/features/continue-after-fatal-error
            //   Allows the parser to continue after a fatal error.
            //   Normally, a fatal error would stop the parse.
            //
            if (feature.equals("continue-after-fatal-error")) {
                setContinueAfterFatalError(state);
                return;
            }
            //
            // Not recognized
            //
        }

        //
        // Not recognized
        //

        throw new SAXNotRecognizedException(featureId);

    } // setFeature(String,boolean)

    /**
     * Query the state of a feature.
     *
     * Query the current state of any feature in a SAX2 parser.  The
     * parser might not recognize the feature.
     *
     * @param featureId The unique identifier (URI) of the feature
     *                  being set.
     * @return The current state of the feature.
     * @exception org.xml.sax.SAXNotRecognizedException If the
     *            requested feature is not known.
     * @exception org.xml.sax.SAXException If there is any other
     *            problem fulfilling the request.
     */
    public boolean getFeature(String featureId) 
        throws SAXNotRecognizedException, SAXNotSupportedException {

        //
        // SAX2 Features
        //

        if (featureId.startsWith(SAX2_FEATURES_PREFIX)) {
            String feature = featureId.substring(SAX2_FEATURES_PREFIX.length());
            //
            // http://xml.org/sax/features/validation
            //   Validate (true) or don't validate (false).
            //
            if (feature.equals("validation")) {
                return getValidation();
            }
            //
            // http://xml.org/sax/features/external-general-entities
            //   Expand external general entities (true) or don't expand (false).
            //
            if (feature.equals("external-general-entities")) {
                return getExternalGeneralEntities();
            }
            //
            // http://xml.org/sax/features/external-parameter-entities
            //   Expand external parameter entities (true) or don't expand (false).
            //
            if (feature.equals("external-parameter-entities")) {
                return getExternalParameterEntities();
            }
            //
            // http://xml.org/sax/features/namespaces
            //   Preprocess namespaces (true) or don't preprocess (false).  See also
            //   the http://xml.org/sax/properties/namespace-sep property.
            //
            if (feature.equals("namespaces")) {
                return getNamespaces();
            }
            //
            // Not recognized
            //
        }

        //
        // Xerces Features
        //

        else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
            String feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
            //
            // http://apache.org/xml/features/validation/schema
            //   Lets the user turn Schema validation support on/off.
            //
            if (feature.equals("validation/schema")) {
                return getValidationSchema();
            }
            //
            // http://apache.org/xml/features/validation/dynamic
            //   Allows the parser to validate a document only when it
            //   contains a grammar. Validation is turned on/off based
            //   on each document instance, automatically.
            //
            if (feature.equals("validation/dynamic")) {
                return getValidationDynamic();
            }
            //
            // http://apache.org/xml/features/validation/default-attribute-values
            //
            if (feature.equals("validation/default-attribute-values")) {
                // REVISIT
                throw new SAXNotRecognizedException(featureId);
            }
            //
            // http://apache.org/xml/features/validation/validate-content-models
            //
            if (feature.equals("validation/validate-content-models")) {
                // REVISIT
                throw new SAXNotRecognizedException(featureId);
            }
            //
            // http://apache.org/xml/features/validation/load-dtd-grammar
            //
            if (feature.equals("load-dtd-grammar")) {
                return getLoadDTDGrammar();
            }
            //
            // http://apache.org/xml/features/validation/validate-datatypes
            //
            if (feature.equals("validation/validate-datatypes")) {
                // REVISIT
                throw new SAXNotRecognizedException(featureId);
            }
            //
            // http://apache.org/xml/features/validation/warn-on-duplicate-attdef
            //   Emits an error when an attribute is redefined.
            //
            if (feature.equals("validation/warn-on-duplicate-attdef")) {
                return getValidationWarnOnDuplicateAttdef();
            }
            //
            // http://apache.org/xml/features/validation/warn-on-undeclared-elemdef
            //   Emits an error when an element's content model
            //   references an element, by name, that is not declared
            //   in the grammar.
            //
            if (feature.equals("validation/warn-on-undeclared-elemdef")) {
                return getValidationWarnOnUndeclaredElemdef();
            }
            //
            // http://apache.org/xml/features/allow-java-encodings
            //   Allows the use of Java encoding names in the XML
            //   and TextDecl lines.
            //
            if (feature.equals("allow-java-encodings")) {
                return getAllowJavaEncodings();
            }
            //
            // http://apache.org/xml/features/continue-after-fatal-error
            //   Allows the parser to continue after a fatal error.
            //   Normally, a fatal error would stop the parse.
            //
            if (feature.equals("continue-after-fatal-error")) {
                return getContinueAfterFatalError();
            }
            //
            // Not recognized
            //
        }

        //
        // Not recognized
        //

        throw new SAXNotRecognizedException(featureId);

    } // getFeature(String):boolean

    /**
     * Set the value of a property.
     *
     * Set the value of any property in a SAX2 parser.  The parser
     * might not recognize the property, and if it does recognize
     * it, it might not support the requested value.
     *
     * @param propertyId The unique identifier (URI) of the property
     *                   being set.
     * @param Object The value to which the property is being set.
     * @exception org.xml.sax.SAXNotRecognizedException If the
     *            requested property is not known.
     * @exception org.xml.sax.SAXNotSupportedException If the
     *            requested property is known, but the requested
     *            value is not supported.
     * @exception org.xml.sax.SAXException If there is any other
     *            problem fulfilling the request.
     */
    public void setProperty(String propertyId, Object value)
        throws SAXNotRecognizedException, SAXNotSupportedException {

        //
        // SAX2 Properties
        //

        if (propertyId.startsWith(SAX2_PROPERTIES_PREFIX)) {
            String property = propertyId.substring(SAX2_PROPERTIES_PREFIX.length());
            //
            // http://xml.org/sax/properties/namespace-sep
            // Value type: String
            // Access: read/write, pre-parse only
            //   Set the separator to be used between the URI part of a name and the
            //   local part of a name when namespace processing is being performed
            //   (see the http://xml.org/sax/features/namespaces feature).  By
            //   default, the separator is a single space.  This property may not be
            //   set while a parse is in progress (throws a SAXNotSupportedException).
            //
            /***
            if (property.equals("namespace-sep")) {
                try {
                    setNamespaceSep((String)value);
                }
                catch (ClassCastException e) {
                    throw new SAXNotSupportedException(propertyId);
                }
                return;
            }
            /***/
            
            //
            // http://xml.org/sax/properties/xml-string
            // Value type: String
            // Access: read-only
            //   Get the literal string of characters associated with the current
            //   event.  If the parser recognises and supports this property but is
            //   not currently parsing text, it should return null (this is a good
            //   way to check for availability before the parse begins).
            //
            if (property.equals("xml-string")) {
                // REVISIT - we should probably ask xml-dev for a precise definition
                // of what this is actually supposed to return, and in exactly which
                // circumstances.
                throw new SAXNotSupportedException(propertyId);
            }
            //
            // Not recognized
            //
        }

        //
        // Xerces Properties
        //

        /*
        else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
            //
            // No properties defined yet that are common to all parsers.
            //
        }
        */

        //
        // Not recognized
        //

        throw new SAXNotRecognizedException(propertyId);

    } // setProperty(String,Object)

    /**
     * Query the value of a property.
     *
     * Return the current value of a property in a SAX2 parser.
     * The parser might not recognize the property.
     *
     * @param propertyId The unique identifier (URI) of the property
     *                   being set.
     * @return The current value of the property.
     * @exception org.xml.sax.SAXNotRecognizedException If the
     *            requested property is not known.
     * @exception org.xml.sax.SAXException If there is any other
     *            problem fulfilling the request.
     * @see org.xml.sax.XMLReader#getProperty
     */
    public Object getProperty(String propertyId) 
        throws SAXNotRecognizedException, SAXNotSupportedException {

        //
        // SAX2 Properties
        //

        if (propertyId.startsWith(SAX2_PROPERTIES_PREFIX)) {
            String property = propertyId.substring(SAX2_PROPERTIES_PREFIX.length());
            //
            // http://xml.org/sax/properties/namespace-sep
            // Value type: String
            // Access: read/write, pre-parse only
            //   Set the separator to be used between the URI part of a name and the
            //   local part of a name when namespace processing is being performed
            //   (see the http://xml.org/sax/features/namespaces feature).  By
            //   default, the separator is a single space.  This property may not be
            //   set while a parse is in progress (throws a SAXNotSupportedException).
            //
            /***
            if (property.equals("namespace-sep")) {
                return getNamespaceSep();
            }
            /***/
            //
            // http://xml.org/sax/properties/xml-string
            // Value type: String
            // Access: read-only
            //   Get the literal string of characters associated with the current
            //   event.  If the parser recognises and supports this property but is
            //   not currently parsing text, it should return null (this is a good
            //   way to check for availability before the parse begins).
            //
            if (property.equals("xml-string")) {
                return getXMLString();
            }
            //
            // Not recognized
            //
        }

        //
        // Xerces Properties
        //

        /*
        else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
            //
            // No properties defined yet that are common to all parsers.
            //
        }
        */

        //
        // Not recognized
        //

        throw new SAXNotRecognizedException(propertyId);

    } // getProperty(String):Object

}
