Massive update for changes made to XNI parser pipeline
interfaces. All of the parser configurations and parsers
(currently on the parserConfig branch) as well as all
parser components implementing the XMLComponent interface
needed to be updated to follow the new model.

Seems to work but more testing needs to be done.


git-svn-id: https://svn.apache.org/repos/asf/xerces/java/branches/parserConfig@317030 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/org/apache/xerces/parsers/AbstractDOMParser.java b/src/org/apache/xerces/parsers/AbstractDOMParser.java
index 068b74c..9a70b9f 100644
--- a/src/org/apache/xerces/parsers/AbstractDOMParser.java
+++ b/src/org/apache/xerces/parsers/AbstractDOMParser.java
@@ -2,8 +2,8 @@
  * The Apache Software License, Version 1.1
  *
  *
- * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
- * reserved.
+ * Copyright (c) 2001 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
@@ -64,6 +64,7 @@
 import org.apache.xerces.xni.QName;
 import org.apache.xerces.xni.XMLAttributes;
 import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
 
 import org.w3c.dom.Attr;
 import org.w3c.dom.CDATASection;
@@ -80,16 +81,18 @@
 import org.xml.sax.SAXException;
 
 /**
- * This is the base class of all DOM parsers. It implements the XNI callback
- * methods to create the DOM tree. After a successful parse of an XML document,
- * the DOM Document object can be queried using the getDocument method.
- * The actual pipeline is defined in subclasses.
+ * This is the base class of all DOM parsers. It implements the XNI 
+ * callback methods to create the DOM tree. After a successful parse of
+ * an XML document, the DOM Document object can be queried using the 
+ * <code>getDocument</code> method. The actual pipeline is defined in
+ * parser configuration.
  * 
  * @author Stubs generated by DesignDoc on Mon Sep 11 11:10:57 PDT 2000
+ * @author Arnaud Le Hors, IBM
  * @author Andy Clark, IBM
- *
  * 
- * @version $Id$ */
+ * @version $Id$ 
+ */
 public abstract class AbstractDOMParser
     extends AbstractXMLDocumentParser {
 
@@ -126,9 +129,9 @@
     //
 
     /** Default constructor. */
-    protected AbstractDOMParser(ParserConfiguration config) {
+    protected AbstractDOMParser(XMLParserConfiguration config) {
         super(config);
-    } // <init>(ParserConfiguration)
+    } // <init>(XMLParserConfiguration)
 
     //
     // Public methods
diff --git a/src/org/apache/xerces/parsers/AbstractSAXParser.java b/src/org/apache/xerces/parsers/AbstractSAXParser.java
index da6c096..027ddac 100644
--- a/src/org/apache/xerces/parsers/AbstractSAXParser.java
+++ b/src/org/apache/xerces/parsers/AbstractSAXParser.java
@@ -2,8 +2,8 @@
  * The Apache Software License, Version 1.1
  *
  *
- * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
- * reserved.
+ * Copyright (c) 2001 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
@@ -65,12 +65,14 @@
 import org.apache.xerces.xni.QName;
 import org.apache.xerces.xni.XMLAttributes;
 import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
 
 import org.xml.sax.ContentHandler;
 import org.xml.sax.DTDHandler;
 import org.xml.sax.DocumentHandler;
 import org.xml.sax.EntityResolver;
 import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
 import org.xml.sax.Parser;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXNotRecognizedException;
@@ -80,20 +82,37 @@
 import org.xml.sax.ext.LexicalHandler;
 
 /**
- * This is the base class of all SAX parsers. It implements both the SAX1 and
- * SAX2 parser functionality, while the actual pipeline is defined in
- * subclasses.
+ * This is the base class of all SAX parsers. It implements both the 
+ * SAX1 and SAX2 parser functionality, while the actual pipeline is
+ * defined in the parser configuration.
  *
  * @author Stubs generated by DesignDoc on Mon Sep 11 11:10:57 PDT 2000
+ * @author Arnaud Le Hors, IBM
  * @author Andy Clark, IBM
  *
- * @version $Id$ */
+ * @version $Id$ 
+ */
 public abstract class AbstractSAXParser
     extends AbstractXMLDocumentParser
     implements Parser, XMLReader // SAX1, SAX2
     {
 
     //
+    // Constants
+    //
+
+    // NOTE: The locator and symbol table properties are for internal
+    //       use. -Ac
+
+    /** Property identifier: locator. */
+    protected static final String LOCATOR =
+        Constants.XERCES_PROPERTY_PREFIX + Constants.LOCATOR_PROPERTY;
+
+    /** Property identifier: symbol table. */
+    protected static final String SYMBOL_TABLE =
+        Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+    //
     // Data
     //
 
@@ -133,9 +152,10 @@
     //
 
     /** Default constructor. */
-    protected AbstractSAXParser(ParserConfiguration config) {
+    protected AbstractSAXParser(XMLParserConfiguration config) {
         super(config);
-    } // <init>(ParserConfiguration)
+
+    } // <init>(XMLParserConfiguration)
 
     //
     // XMLDocumentHandler methods
@@ -698,7 +718,15 @@
      */
     public void setDocumentHandler(DocumentHandler documentHandler) {
         fDocumentHandler = documentHandler;
-        fDocumentHandler.setDocumentLocator(fConfiguration.getLocator());
+        try {
+            Locator locator = (Locator)fConfiguration.getProperty(LOCATOR);
+            if (locator != null) {
+                fDocumentHandler.setDocumentLocator(locator);
+            }
+        }
+        catch (SAXException e) {
+            // do nothing
+        }
     } // setDocumentHandler(DocumentHandler)
 
     //
@@ -774,7 +802,6 @@
         // SAX2 Features
         //
 
-        Hashtable features = fConfiguration.getFeatureTable();
         if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
             String feature = featureId.substring(Constants.SAX_FEATURE_PREFIX.length());
 
@@ -785,7 +812,7 @@
             //   and xmlns* attributes must not be reported.
             //
             if (feature.equals(Constants.NAMESPACE_PREFIXES_FEATURE)) {
-                features.put(featureId, state ? Boolean.TRUE : Boolean.FALSE);
+                fConfiguration.setFeature(featureId, state);
                 return;
             }
             // http://xml.org/sax/features/string-interning
@@ -849,7 +876,6 @@
         // SAX2 Features
         //
 
-        Hashtable features = fConfiguration.getFeatureTable();
         if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
             String feature =
                 featureId.substring(Constants.SAX_FEATURE_PREFIX.length());
@@ -861,8 +887,8 @@
             //   and xmlns* attributes must not be reported.
             //
             if (feature.equals(Constants.NAMESPACE_PREFIXES_FEATURE)) {
-                Boolean state = (Boolean) features.get(featureId);
-                return state.booleanValue();
+                boolean state = fConfiguration.getFeature(featureId);
+                return state;
             }
             // http://xml.org/sax/features/string-interning
             //   controls the use of java.lang.String#intern() for strings
@@ -1185,7 +1211,8 @@
         fInDTD = false;
 
         // save needed symbols
-        fEmptySymbol = fConfiguration.getSymbolTable().addSymbol("");
+        SymbolTable symbolTable = (SymbolTable)fConfiguration.getProperty(SYMBOL_TABLE);
+        fEmptySymbol = symbolTable.addSymbol("");
 
     } // reset()
 
diff --git a/src/org/apache/xerces/parsers/AbstractXMLDocumentParser.java b/src/org/apache/xerces/parsers/AbstractXMLDocumentParser.java
index e6b43c4..e6567d2 100644
--- a/src/org/apache/xerces/parsers/AbstractXMLDocumentParser.java
+++ b/src/org/apache/xerces/parsers/AbstractXMLDocumentParser.java
@@ -1,10 +1,9 @@
-
 /*
  * The Apache Software License, Version 1.1
  *
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights 
- * reserved.
+ * Copyright (c) 2001 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
@@ -64,6 +63,7 @@
 import org.apache.xerces.xni.XMLDTDHandler;
 import org.apache.xerces.xni.XMLDTDContentModelHandler;
 import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
 
 import org.xml.sax.SAXException;
 
@@ -101,12 +101,12 @@
      * Constructs a document parser using the default symbol table
      * and grammar pool.
      */
-    protected AbstractXMLDocumentParser(ParserConfiguration config) {
+    protected AbstractXMLDocumentParser(XMLParserConfiguration config) {
         super(config);
         config.setDocumentHandler(this);
         config.setDTDHandler(this);
         config.setDTDContentModelHandler(this);
-    } // <init>(ParserConfiguration)
+    } // <init>(XMLParserConfiguration)
 
     //
     // XMLDocumentHandler methods
@@ -687,10 +687,7 @@
      * reset all components before parsing
      */
     protected void reset() throws SAXException {
-        super.reset();
-
         fInDTD = false;
-
     } // reset()
 
 } // class AbstractXMLDocumentParser
diff --git a/src/org/apache/xerces/parsers/BasicParserConfiguration.java b/src/org/apache/xerces/parsers/BasicParserConfiguration.java
index fdaea8b..4196c53 100644
--- a/src/org/apache/xerces/parsers/BasicParserConfiguration.java
+++ b/src/org/apache/xerces/parsers/BasicParserConfiguration.java
@@ -2,8 +2,8 @@
  * The Apache Software License, Version 1.1
  *
  *
- * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
- * reserved.
+ * Copyright (c) 2001 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
@@ -61,19 +61,17 @@
 import java.io.IOException;
 import java.io.Reader;
 import java.util.Hashtable;
-import java.util.Locale;
 import java.util.Vector;
 
 import org.apache.xerces.impl.Constants;
-import org.apache.xerces.impl.XMLEntityManager;
-import org.apache.xerces.impl.XMLErrorReporter;
 import org.apache.xerces.impl.msg.XMLMessageFormatter;
 import org.apache.xerces.util.SymbolTable;
-import org.apache.xerces.xni.XMLComponent;
-import org.apache.xerces.xni.XMLComponentManager;
 import org.apache.xerces.xni.XMLDocumentHandler;
 import org.apache.xerces.xni.XMLDTDHandler;
 import org.apache.xerces.xni.XMLDTDContentModelHandler;
+import org.apache.xerces.xni.parser.XMLComponent;
+import org.apache.xerces.xni.parser.XMLComponentManager;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
 
 import org.xml.sax.EntityResolver;
 import org.xml.sax.ErrorHandler;
@@ -84,24 +82,50 @@
 import org.xml.sax.SAXNotSupportedException;
 
 /**
- * This class sets the defaults for the following features and properties:
+ * A very basic parser configuration. This configuration class can
+ * be used as a base class for custom parser configurations. The
+ * basic parser configuration creates the symbol table (if not
+ * specified at construction time) and manages all of the recognized
+ * features and properties.
+ * <p>
+ * The basic parser configuration does <strong>not</strong> mandate
+ * any particular pipeline configuration or the use of specific 
+ * components except for the symbol table. If even this is too much
+ * for a basic parser configuration, the programmer can create a new
+ * configuration class that implements the 
+ * <code>XMLParserConfiguration</code> interface.
+ * <p>
+ * Subclasses of the basic parser configuration can add their own
+ * recognized features and properties by calling the
+ * <code>addRecognizedFeature</code> and 
+ * <code>addRecognizedProperty</code> methods, respectively.
+ * <p>
+ * The basic parser configuration assumes that the configuration
+ * will be made up of various parser components that implement the
+ * <code>XMLComponent</code> interface. If subclasses of this
+ * configuration create their own components for use in the 
+ * parser configuration, then each component should be added to
+ * the list of components by calling the <code>addComponent</code>
+ * method. The basic parser configuration will make sure to call
+ * the <code>reset</code> method of each registered component
+ * before parsing an instance document.
+ * <p>
+ * This class recognizes the following features and properties:
  * <ul>
- * <li>http://xml.org/sax/features/validation</li>
- * <li>http://xml.org/sax/features/namespaces</li>
- * <li>http://xml.org/sax/features/external-general-entities</li>
- * <li>http://xml.org/sax/features/external-parameter-entities</li>
- * <li>http://apache.org/xml/features/validation/warn-on-duplicate-attdef</li>
- * <li>http://apache.org/xml/features/validation/warn-on-undeclared-elemdef</li>
- * <li>http://apache.org/xml/features/allow-java-encodings</li>
- * <li>http://apache.org/xml/features/continue-after-fatal-error</li>
- * <li>http://xml.org/sax/properties/xml-string</li>
- * <li>http://apache.org/xml/properties/internal/symbol-table</li>
- * <li>http://apache.org/xml/properties/internal/error-reporter</li>
- * <li>http://apache.org/xml/properties/internal/error-handler</li>
- * <li>http://apache.org/xml/properties/internal/entity-manager</li>
- * <li>http://apache.org/xml/properties/internal/entity-resolver</li>
- * <li>http://apache.org/xml/properties/internal/grammar-pool</li>
- * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
+ * <li>Features
+ *  <ul>
+ *   <li>http://xml.org/sax/features/validation</li>
+ *   <li>http://xml.org/sax/features/namespaces</li>
+ *   <li>http://xml.org/sax/features/external-general-entities</li>
+ *   <li>http://xml.org/sax/features/external-parameter-entities</li>
+ *  </ul>
+ * <li>Properties
+ *  <ul>
+ *   <li>http://xml.org/sax/properties/xml-string</li>
+ *   <li>http://apache.org/xml/properties/internal/symbol-table</li>
+ *   <li>http://apache.org/xml/properties/internal/error-handler</li>
+ *   <li>http://apache.org/xml/properties/internal/entity-resolver</li>
+ *  </ul>
  * </ul>
  *
  * @author Arnaud  Le Hors, IBM
@@ -110,7 +134,47 @@
  * @version $Id$
  */
 public abstract class BasicParserConfiguration
-    extends ParserConfiguration {
+    implements XMLParserConfiguration {
+
+    //
+    // Constants
+    //
+
+    // feature identifiers
+
+    /** Feature identifier: validation. */
+    protected static final String VALIDATION =
+        Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+    
+    /** Feature identifier: namespaces. */
+    protected static final String NAMESPACES =
+        Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
+    
+    /** Feature identifier: external general entities. */
+    protected static final String EXTERNAL_GENERAL_ENTITIES =
+        Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
+    
+    /** Feature identifier: external parameter entities. */
+    protected static final String EXTERNAL_PARAMETER_ENTITIES =
+        Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
+    
+    // property identifiers
+
+    /** Property identifier: xml string. */
+    protected static final String XML_STRING = 
+        Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
+
+    /** Property identifier: symbol table. */
+    protected static final String SYMBOL_TABLE = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+
+    /** Property identifier: error handler. */
+    protected static final String ERROR_HANDLER = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
+
+    /** Property identifier: entity resolver. */
+    protected static final String ENTITY_RESOLVER = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
 
     //
     // Data
@@ -121,75 +185,81 @@
     /** Symbol table. */
     protected SymbolTable fSymbolTable;
 
-    /** Locator */
-    protected Locator fLocator;
-
-    // components (configurable)
-
-    /** Entity manager. */
-    protected XMLEntityManager fEntityManager;
-
-    /** Error reporter. */
-    protected XMLErrorReporter fErrorReporter;
-
     // data
 
+    /** Recognized properties. */
+    protected Vector fRecognizedProperties;
+
     /** Properties. */
     protected Hashtable fProperties;
 
+    /** Recognized features. */
+    protected Vector fRecognizedFeatures;
+
     /** Features. */
     protected Hashtable fFeatures;
 
     /** Components. */
     protected Vector fComponents;
 
+    // state
+
+    /** Set to true if initialization is needed. */
     protected boolean fNeedInitialize;
 
+    // handlers
+
+    /** The document handler. */
     protected XMLDocumentHandler fDocumentHandler;
 
+    /** The DTD handler. */
     protected XMLDTDHandler fDTDHandler;
 
+    /** The DTD content model handler. */
     protected XMLDTDContentModelHandler fDTDContentModelHandler;
 
     //
     // Constructors
     //
 
-    /**
-     * Default Constructor.
-     */
+    /** Default Constructor. */
     protected BasicParserConfiguration() {
 
         // create a vector to hold all the components in use
         fComponents = new Vector();
 
+        // create storage for recognized features and properties
+        fRecognizedFeatures = new Vector();
+        fRecognizedProperties = new Vector();
+
         // create table for features and properties
         fFeatures = new Hashtable();
         fProperties = new Hashtable();
 
-        // set default values for features
-        final String VALIDATION = Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
-        fFeatures.put(VALIDATION, Boolean.FALSE);
-        final String NAMESPACES = Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
-        fFeatures.put(NAMESPACES, Boolean.TRUE);
-        final String EXTERNAL_GENERAL_ENTITIES = Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
-        fFeatures.put(EXTERNAL_GENERAL_ENTITIES, Boolean.TRUE);
-        final String EXTERNAL_PARAMETER_ENTITIES = Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
-        fFeatures.put(EXTERNAL_PARAMETER_ENTITIES, Boolean.TRUE);
-        final String WARN_ON_DUPLICATE_ATTDEF = Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
-        fFeatures.put(WARN_ON_DUPLICATE_ATTDEF, Boolean.FALSE);
-        final String WARN_ON_UNDECLARED_ELEMDEF = Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE;
-        fFeatures.put(WARN_ON_UNDECLARED_ELEMDEF, Boolean.FALSE);
-        final String ALLOW_JAVA_ENCODINGS = Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
-        fFeatures.put(ALLOW_JAVA_ENCODINGS, Boolean.FALSE);
-        final String CONTINUE_AFTER_FATAL_ERROR = Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
-        fFeatures.put(CONTINUE_AFTER_FATAL_ERROR, Boolean.FALSE);
-        final String LOAD_EXTERNAL_DTD = Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
-        fFeatures.put(LOAD_EXTERNAL_DTD, Boolean.TRUE);
+        // add default recognized features
+        final String[] recognizedFeatures = {
+            VALIDATION,                 NAMESPACES, 
+            EXTERNAL_GENERAL_ENTITIES,  EXTERNAL_PARAMETER_ENTITIES,
+        };
+        addRecognizedFeatures(recognizedFeatures);
 
+        // set state for default features
+        fFeatures.put(VALIDATION, Boolean.FALSE);
+        fFeatures.put(NAMESPACES, Boolean.TRUE);
+        fFeatures.put(EXTERNAL_GENERAL_ENTITIES, Boolean.TRUE);
+        fFeatures.put(EXTERNAL_PARAMETER_ENTITIES, Boolean.TRUE);
+
+        // add default recognized properties
+        final String[] recognizedProperties = {
+            XML_STRING,     SYMBOL_TABLE,
+            ERROR_HANDLER,  ENTITY_RESOLVER,
+        };
+        addRecognizedProperties(recognizedProperties);
+
+        // set state
         fNeedInitialize = true;
 
-    } // <init>
+    } // <init>()
 
     /**
      * Constructs a document parser using the specified symbol table
@@ -198,9 +268,10 @@
      */
     protected BasicParserConfiguration(SymbolTable symbolTable) {
         this();
-        final String SYMBOL_TABLE = Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
-        fSymbolTable = new SymbolTable();
-        fProperties.put(SYMBOL_TABLE, fSymbolTable);
+        fSymbolTable = symbolTable;
+        if (fSymbolTable != null) {
+            fProperties.put(SYMBOL_TABLE, fSymbolTable);
+        }
     } // <init>(SymbolTable)
 
     /**
@@ -213,47 +284,41 @@
     protected void initialize() {
 
         // create and register missing components
-        final String SYMBOL_TABLE = Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
-        fSymbolTable = (SymbolTable) fProperties.get(SYMBOL_TABLE);
         if (fSymbolTable == null) {
             fSymbolTable = new SymbolTable();
             fProperties.put(SYMBOL_TABLE, fSymbolTable);
         }
 
-        final String ENTITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
-        fEntityManager = (XMLEntityManager) fProperties.get(ENTITY_MANAGER);
-        if (fEntityManager == null) {
-            fEntityManager = createEntityManager();
-            fProperties.put(ENTITY_MANAGER, fEntityManager);
-        }
-        fComponents.addElement(fEntityManager);
-
-        final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
-        fErrorReporter = (XMLErrorReporter) fProperties.get(ERROR_REPORTER);
-        if (fErrorReporter == null) {
-            fErrorReporter =
-                createErrorReporter(fEntityManager.getEntityScanner());
-            fProperties.put(ERROR_REPORTER, fErrorReporter);
-        }
-        fComponents.addElement(fErrorReporter);
-
-        fLocator = (Locator) fEntityManager.getEntityScanner();
-
-        XMLMessageFormatter xmft = new XMLMessageFormatter();
-        fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
-        fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
-
-        // set locale
-        try {
-            setLocale(Locale.getDefault());
-        }
-        catch (SAXException e) {
-            // ignore
-        }
+        // initialization finished
         fNeedInitialize = false;
 
     } // initialize()
 
+    /** 
+     * Adds a component to the parser configuration. This method will
+     * also add all of the component's recognized features and properties
+     * to the list of default recognized features and properties.
+     *
+     * @param component The component to add.
+     */
+    protected void addComponent(XMLComponent component) {
+
+        // don't add a component more than once
+        if (fComponents.contains(component)) {
+            return;
+        }
+        fComponents.addElement(component);
+
+        // register component's recognized features
+        String[] recognizedFeatures = component.getRecognizedFeatures();
+        addRecognizedFeatures(recognizedFeatures);
+
+        // register component's recognized properties
+        String[] recognizedProperties = component.getRecognizedProperties();
+        addRecognizedProperties(recognizedProperties);
+
+    } // addComponent(XMLComponent)
+
     //
     // Public methods
     //
@@ -326,10 +391,7 @@
      *                 uninstall the currently installed resolver.
      */
     public void setEntityResolver(EntityResolver resolver) {
-
-        final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
         fProperties.put(ENTITY_RESOLVER, resolver);
-
     } // setEntityResolver(EntityResolver)
 
     /**
@@ -340,10 +402,7 @@
      * @see #setEntityResolver
      */
     public EntityResolver getEntityResolver() {
-
-        final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
         return (EntityResolver)fProperties.get(ENTITY_RESOLVER);
-
     } // getEntityResolver():EntityResolver
 
     /**
@@ -365,10 +424,7 @@
      * @see #getErrorHandler
      */
     public void setErrorHandler(ErrorHandler errorHandler) {
-
-        final String ERROR_HANDLER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
         fProperties.put(ERROR_HANDLER, errorHandler);
-
     } // setErrorHandler(ErrorHandler)
 
     /**
@@ -379,13 +435,30 @@
      * @see #setErrorHandler
      */
     public ErrorHandler getErrorHandler() {
-
-        final String ERROR_HANDLER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
         return (ErrorHandler)fProperties.get(ERROR_HANDLER);
-
     } // getErrorHandler():ErrorHandler
 
     /**
+     * Allows a parser to add parser specific features to be recognized
+     * and managed by the parser configuration.
+     *
+     * @param featureIds An array of the additional feature identifiers 
+     *                   to be recognized.
+     */
+    public void addRecognizedFeatures(String[] featureIds) {
+
+        // add recognized features
+        int featureIdsCount = featureIds != null ? featureIds.length : 0;
+        for (int i = 0; i < featureIdsCount; i++) {
+            String featureId = featureIds[i];
+            if (!fRecognizedFeatures.contains(featureId)) {
+                fRecognizedFeatures.addElement(featureId);
+            }
+        }
+
+    } // addRecognizedFeatures(String[])
+
+    /**
      * Set the state of a feature.
      *
      * Set the state of any feature in a SAX2 parser.  The parser
@@ -420,6 +493,26 @@
     } // setFeature(String,boolean)
 
     /**
+     * Allows a parser to add parser specific properties to be recognized
+     * and managed by the parser configuration.
+     *
+     * @param propertyIds An array of the additional property identifiers 
+     *                    to be recognized.
+     */
+    public void addRecognizedProperties(String[] propertyIds) {
+
+        // add recognizedProperties
+        int propertyIdsCount = propertyIds != null ? propertyIds.length : 0;
+        for (int i = 0; i < propertyIdsCount; i++) {
+            String propertyId = propertyIds[i];
+            if (!fRecognizedProperties.contains(propertyId)) {
+                fRecognizedProperties.addElement(propertyId);
+            }
+        }
+
+    } // addRecognizedProperties(String[])
+
+    /**
      * setProperty
      * 
      * @param propertyId 
@@ -441,22 +534,6 @@
 
     } // setProperty(String,Object)
 
-    /**
-     * 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 {
-
-        fErrorReporter.setLocale(locale);
-
-    } // setLocale(Locale)
-
     //
     // XMLComponentManager methods
     //
@@ -477,7 +554,7 @@
         checkFeature(featureId);
 
         Boolean state = (Boolean) fFeatures.get(featureId);
-        return state.booleanValue();
+        return state != null ? state.booleanValue() : false;
 
     } // getFeature(String):boolean
 
@@ -500,6 +577,7 @@
 
     } // getProperty(String):Object
 
+    /*** These should be queried through the property mechanism. -Ac ***
     public Locator getLocator() {
         return fLocator;
     } // getLocator():Locator
@@ -515,6 +593,7 @@
     public Hashtable getPropertyTable() {
         return fProperties;
     }
+    /***/
 
     //
     // Protected methods
@@ -551,97 +630,11 @@
     protected void checkFeature(String featureId)
         throws SAXNotRecognizedException, SAXNotSupportedException {
 
-        //
-        // SAX2 Features
-        //
-
-        if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
-            String feature =
-                featureId.substring(Constants.SAX_FEATURE_PREFIX.length());
-            //
-            // http://xml.org/sax/features/validation
-            //   Validate (true) or don't validate (false).
-            //
-            if (feature.equals(Constants.VALIDATION_FEATURE)) {
-                return;
-            }
-            //
-            // http://xml.org/sax/features/namespaces
-            //   Preprocess namespaces (true) or not (false).  See also
-            //   the http://xml.org/sax/properties/namespace-sep property.
-            //
-            if (feature.equals(Constants.NAMESPACES_FEATURE)) {
-                return;
-            }
-            //
-            // http://xml.org/sax/features/external-general-entities
-            //   Expand external general entities (true) or not (false).
-            //
-            if (feature.equals(Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE)) {
-                return;
-            }
-            //
-            // http://xml.org/sax/features/external-parameter-entities
-            //   Expand external parameter entities (true) or not (false).
-            //
-            if (feature.equals(Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE)) {
-                return;
-            }
-            //
-            // Not recognized
-            //
+        // check feature
+        if (!fRecognizedFeatures.contains(featureId)) {
+            throw new SAXNotRecognizedException(featureId);
         }
 
-        //
-        // Xerces Features
-        //
-
-        else if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
-            String feature =
-                featureId.substring(Constants.XERCES_FEATURE_PREFIX.length());
-            //
-            // http://apache.org/xml/features/validation/warn-on-duplicate-attdef
-            //   Emits an error when an attribute is redefined.
-            //
-            if (feature.equals(Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE)) {
-                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(Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE)) {
-                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(Constants.ALLOW_JAVA_ENCODINGS_FEATURE)) {
-                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(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
-                return;
-            }
-            //
-            // Not recognized
-            //
-        }
-
-        //
-        // Not recognized
-        //
-
-        throw new SAXNotRecognizedException(featureId);
-
     } // checkFeature(String)
 
     /**
@@ -661,10 +654,7 @@
     protected void checkProperty(String propertyId)
         throws SAXNotRecognizedException, SAXNotSupportedException {
 
-        //
-        // SAX2 Properties
-        //
-
+        // special cases
         if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
             String property =
                 propertyId.substring(Constants.SAX_PROPERTY_PREFIX.length());
@@ -686,74 +676,11 @@
             }
         }
 
-        //
-        // Xerces Properties
-        //
-
-        else if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
-            String property = propertyId.substring(Constants.XERCES_PROPERTY_PREFIX.length());
-            //
-            // http://apache.org/xml/properties/internal/symbol-table
-            //
-            if (property.equals(Constants.SYMBOL_TABLE_PROPERTY)) {
-                return;
-            }
-            //
-            // http://apache.org/xml/properties/internal/error-reporter
-            //
-            if (property.equals(Constants.ERROR_REPORTER_PROPERTY)) {
-                return;
-            }
-            //
-            // http://apache.org/xml/properties/internal/error-handler
-            //
-            if (property.equals(Constants.ERROR_HANDLER_PROPERTY)) {
-                return;
-            }
-            //
-            // http://apache.org/xml/properties/internal/entity-manager
-            //
-            if (property.equals(Constants.ENTITY_MANAGER_PROPERTY)) {
-                return;
-            }
-            //
-            // http://apache.org/xml/properties/internal/entity-resolver
-            //
-            if (property.equals(Constants.ENTITY_RESOLVER_PROPERTY)) {
-                return;
-            }
-            //
-            // http://apache.org/xml/properties/internal/grammar-pool
-            //
-            if (property.equals(Constants.GRAMMAR_POOL_PROPERTY)) {
-                return;
-            }
-            //
-            // http://apache.org/xml/properties/internal/datatype-validator-factory
-            //
-            if (property.equals(Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY)) {
-                return;
-            }
+        // check property
+        if (!fRecognizedProperties.contains(propertyId)) {
+            throw new SAXNotRecognizedException(propertyId);
         }
 
-        //
-        // Not recognized
-        //
-
-        throw new SAXNotRecognizedException(propertyId);
-
     } // checkProperty(String)
 
-    // factory methods
-
-    /** Creates an entity manager. */
-    protected XMLEntityManager createEntityManager() {
-        return new XMLEntityManager();
-    } // createEntityManager():XMLEntityManager
-
-    /** Creates an error reporter. */
-    protected XMLErrorReporter createErrorReporter(Locator locator) {
-        return new XMLErrorReporter(locator);
-    } // createErrorReporter(Locator):XMLErrorReporter
-
 } // class XMLParser
diff --git a/src/org/apache/xerces/parsers/DOMParser.java b/src/org/apache/xerces/parsers/DOMParser.java
index ed2645c..fe33226 100644
--- a/src/org/apache/xerces/parsers/DOMParser.java
+++ b/src/org/apache/xerces/parsers/DOMParser.java
@@ -59,17 +59,19 @@
 
 import org.apache.xerces.impl.validation.GrammarPool;
 import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
 
 /**
- * This is the main Xerces DOM parser class. It uses the abstract DOM parser
- * with a document scanner, a dtd scanner, and a validator, as well as a
- * grammar pool.
+ * This is the main Xerces DOM parser class. It uses the abstract DOM
+ * parser with a document scanner, a dtd scanner, and a validator, as 
+ * well as a grammar pool.
  *
  * @author Stubs generated by DesignDoc on Mon Sep 11 11:10:57 PDT 2000
  * @author Arnaud  Le Hors, IBM
  * @author Andy Clark, IBM
  *
- * @version $Id$ */
+ * @version $Id$ 
+ */
 public class DOMParser
     extends AbstractDOMParser {
 
@@ -87,9 +89,9 @@
     /**
      * Constructs a DOM parser using the specified parser configuration.
      */
-    public DOMParser(ParserConfiguration config) {
+    public DOMParser(XMLParserConfiguration config) {
         super(config);
-    } // <init>(ParserConfiguration)
+    } // <init>(XMLParserConfiguration)
 
     /**
      * Constructs a DOM parser using the specified symbol table.
diff --git a/src/org/apache/xerces/parsers/SAXParser.java b/src/org/apache/xerces/parsers/SAXParser.java
index ae2a99f..738a546 100644
--- a/src/org/apache/xerces/parsers/SAXParser.java
+++ b/src/org/apache/xerces/parsers/SAXParser.java
@@ -59,17 +59,19 @@
 
 import org.apache.xerces.impl.validation.GrammarPool;
 import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
 
 /**
- * This is the main Xerces SAX parser class. It uses the abstract SAX parser
- * with either a BasicConfiguration object or the one specified by the
- * application.
+ * This is the main Xerces SAX parser class. It uses the abstract SAX
+ * parser with a document scanner, a dtd scanner, and a validator, as 
+ * well as a grammar pool.
  *
  * @author Stubs generated by DesignDoc on Mon Sep 11 11:10:57 PDT 2000
  * @author Arnaud  Le Hors, IBM
  * @author Andy Clark, IBM
  *
- * @version $Id$ */
+ * @version $Id$ 
+ */
 public class SAXParser
     extends AbstractSAXParser {
 
@@ -85,13 +87,6 @@
     } // <init>
 
     /**
-     * Constructs a SAX parser using the specified parser configuration.
-     */
-    public SAXParser(ParserConfiguration config) {
-        super(config);
-    } // <init>(ParserConfiguration)
-
-    /**
      * Constructs a SAX parser using the specified symbol table.
      */
     public SAXParser(SymbolTable symbolTable) {
diff --git a/src/org/apache/xerces/parsers/StandardParserConfiguration.java b/src/org/apache/xerces/parsers/StandardParserConfiguration.java
index bd7ea9a..8d7eabd 100644
--- a/src/org/apache/xerces/parsers/StandardParserConfiguration.java
+++ b/src/org/apache/xerces/parsers/StandardParserConfiguration.java
@@ -2,8 +2,8 @@
  * The Apache Software License, Version 1.1
  *
  *
- * Copyright (c) 2001 The Apache Software Foundation.  All rights 
- * reserved.
+ * Copyright (c) 2001 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
@@ -58,13 +58,16 @@
 package org.apache.xerces.parsers;
 
 import java.io.IOException;
+import java.util.Locale;
 
 import org.apache.xerces.impl.Constants;
 import org.apache.xerces.impl.XMLDocumentScanner;
+import org.apache.xerces.impl.XMLErrorReporter;
 import org.apache.xerces.impl.XMLDTDScanner;
 import org.apache.xerces.impl.XMLEntityManager;
 import org.apache.xerces.impl.XMLInputSource;
 import org.apache.xerces.impl.XMLValidator;
+import org.apache.xerces.impl.msg.XMLMessageFormatter;
 import org.apache.xerces.impl.validation.DatatypeValidatorFactory;
 import org.apache.xerces.impl.validation.GrammarPool;
 import org.apache.xerces.impl.validation.datatypes.DatatypeValidatorFactoryImpl;
@@ -72,19 +75,44 @@
 import org.apache.xerces.util.SymbolTable;
 
 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;
 
 /**
  * This is the "standard" parser configuration. It extends the basic
- * configuration with a document scanner, a dtd scanner, and a validator, as
- * well as a grammar pool.
+ * configuration with the standard set of parser components.
+ * <p>
+ * In addition to the features and properties recognized by the base
+ * parser configuration, this class recognizes these additional 
+ * features and properties:
+ * <ul>
+ * <li>Features
+ *  <ul>
+ *   <li>http://apache.org/xml/features/validation/warn-on-duplicate-attdef</li>
+ *   <li>http://apache.org/xml/features/validation/warn-on-undeclared-elemdef</li>
+ *   <li>http://apache.org/xml/features/allow-java-encodings</li>
+ *   <li>http://apache.org/xml/features/continue-after-fatal-error</li>
+ *   <li>http://apache.org/xml/features/load-external-dtd</li>
+ *  </ul>
+ * <li>Properties
+ *  <ul>
+ *   <li>http://apache.org/xml/properties/internal/error-reporter</li>
+ *   <li>http://apache.org/xml/properties/internal/entity-manager</li>
+ *   <li>http://apache.org/xml/properties/internal/document-scanner</li>
+ *   <li>http://apache.org/xml/properties/internal/dtd-scanner</li>
+ *   <li>http://apache.org/xml/properties/internal/grammar-pool</li>
+ *   <li>http://apache.org/xml/properties/internal/validator</li>
+ *   <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
+ *  </ul>
+ * </ul>
  *
  * @author Arnaud  Le Hors, IBM
  * @author Andy Clark, IBM
  *
- * @version $Id$ */
+ * @version $Id$
+ */
 public class StandardParserConfiguration
     extends BasicParserConfiguration {
 
@@ -92,6 +120,58 @@
     // Constants
     //
 
+    // feature identifiers
+
+    /** Feature identifier: warn on duplicate attribute definition. */
+    protected static final String WARN_ON_DUPLICATE_ATTDEF =
+        Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
+    
+    /** Feature identifier: warn on undeclared element definition. */
+    protected static final String WARN_ON_UNDECLARED_ELEMDEF =
+        Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE;
+    
+    /** Feature identifier: allow Java encodings. */
+    protected static final String ALLOW_JAVA_ENCODINGS = 
+        Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
+    
+    /** Feature identifier: continue after fatal error. */
+    protected static final String CONTINUE_AFTER_FATAL_ERROR = 
+        Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
+
+    /** Feature identifier: load external DTD. */
+    protected static final String LOAD_EXTERNAL_DTD =
+        Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
+
+    // property identifiers
+
+    /** Property identifier: error reporter. */
+    protected static final String ERROR_REPORTER = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+
+    /** Property identifier: entity manager. */
+    protected static final String ENTITY_MANAGER = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
+    
+    /** Property identifier document scanner: */
+    protected static final String DOCUMENT_SCANNER = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
+
+    /** Property identifier: DTD scanner. */
+    protected static final String DTD_SCANNER = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
+
+    /** Property identifier: grammar pool. */
+    protected static final String GRAMMAR_POOL = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.GRAMMAR_POOL_PROPERTY;
+    
+    /** Property identifier: validator. */
+    protected static final String VALIDATOR = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATOR_PROPERTY;
+
+    /** Property identifier: datatype validator factory. */
+    protected static final String DATATYPE_VALIDATOR_FACTORY = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
+
     // debugging
 
     /** Set to true and recompile to print exception stack trace. */
@@ -111,6 +191,12 @@
 
     // components (configurable)
 
+    /** Error reporter. */
+    protected XMLErrorReporter fErrorReporter;
+
+    /** Entity manager. */
+    protected XMLEntityManager fEntityManager;
+
     /** Document scanner. */
     protected XMLDocumentScanner fScanner;
 
@@ -122,6 +208,9 @@
 
     // state
 
+    /** Locator */
+    protected Locator fLocator;
+
     /** 
      * True if a parse is in progress. This state is needed because
      * some features/properties cannot be set while parsing (e.g.
@@ -138,13 +227,14 @@
      * pool or the ones specified by the application (through the properties).
      */
     public StandardParserConfiguration() {
-    } // <init>
+        this(null, null);
+    } // <init>()
 
     /**
      * Constructs a document parser using the specified symbol table.
      */
     public StandardParserConfiguration(SymbolTable symbolTable) {
-        super(symbolTable);
+        this(symbolTable, null);
     } // <init>(SymbolTable)
 
     /**
@@ -152,107 +242,80 @@
      * grammar pool.
      */
     public StandardParserConfiguration(SymbolTable symbolTable,
-                              GrammarPool grammarPool) {
+                                       GrammarPool grammarPool) {
         super(symbolTable);
 
-        final String GRAMMAR_POOL = Constants.XERCES_PROPERTY_PREFIX + Constants.GRAMMAR_POOL_PROPERTY;
-        fGrammarPool = new GrammarPool();
-        fProperties.put(GRAMMAR_POOL, fGrammarPool);
-    }
+        // add default recognized features
+        final String[] recognizedFeatures = {
+            WARN_ON_DUPLICATE_ATTDEF,   WARN_ON_UNDECLARED_ELEMDEF,
+            ALLOW_JAVA_ENCODINGS,       CONTINUE_AFTER_FATAL_ERROR,
+            LOAD_EXTERNAL_DTD,
+        };
+        addRecognizedFeatures(recognizedFeatures);
 
-    /**
-     * Initialize the parser with all the components specified via the
-     * properties plus any missing ones. This method MUST be called before
-     * parsing. It is not called from the constructor though, so that the
-     * application can pass in any components it wants by presetting the
-     * relevant property.
-     */
-    public void initialize() {
-        super.initialize();
+        // set state for default features
+        fFeatures.put(WARN_ON_DUPLICATE_ATTDEF, Boolean.FALSE);
+        fFeatures.put(WARN_ON_UNDECLARED_ELEMDEF, Boolean.FALSE);
+        fFeatures.put(ALLOW_JAVA_ENCODINGS, Boolean.FALSE);
+        fFeatures.put(CONTINUE_AFTER_FATAL_ERROR, Boolean.FALSE);
+        fFeatures.put(LOAD_EXTERNAL_DTD, Boolean.TRUE);
 
-        // set default features
-        final String NAMESPACES = Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
-        fFeatures.put(NAMESPACES, Boolean.TRUE);
-        final String VALIDATION = Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
-        fFeatures.put(VALIDATION, Boolean.FALSE);
-        final String EXTERNAL_GENERAL_ENTITIES = Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
-        fFeatures.put(EXTERNAL_GENERAL_ENTITIES, Boolean.TRUE);
-        final String EXTERNAL_PARAMETER_ENTITIES = Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
-        fFeatures.put(EXTERNAL_PARAMETER_ENTITIES, Boolean.TRUE);
+        // add default recognized properties
+        final String[] recognizedProperties = {
+            ERROR_REPORTER, ENTITY_MANAGER, 
+            GRAMMAR_POOL,   DATATYPE_VALIDATOR_FACTORY
+        };
+        addRecognizedProperties(recognizedProperties);
 
-        // create and register missing components
-        final String GRAMMAR_POOL = Constants.XERCES_PROPERTY_PREFIX + Constants.GRAMMAR_POOL_PROPERTY;
-        fGrammarPool = (GrammarPool) fProperties.get(GRAMMAR_POOL);
-        if (fGrammarPool == null) {
-            fGrammarPool = new GrammarPool();
+        // create missing components
+        fGrammarPool = grammarPool;
+        if (fGrammarPool != null) {
             fProperties.put(GRAMMAR_POOL, fGrammarPool);
         }
 
-        final String DOCUMENT_SCANNER = Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
-        fScanner = (XMLDocumentScanner) fProperties.get(DOCUMENT_SCANNER);
-        if (fScanner == null) {
-            fScanner = createDocumentScanner();
-            fProperties.put(DOCUMENT_SCANNER, fScanner);
+        // set locale
+        try {
+            setLocale(Locale.getDefault());
         }
-        fComponents.addElement(fScanner);
-
-        final String DTD_SCANNER = Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
-        fDTDScanner = (XMLDTDScanner) fProperties.get(DTD_SCANNER);
-        if (fDTDScanner == null) {
-            fDTDScanner = createDTDScanner();
-            fProperties.put(DTD_SCANNER, fDTDScanner);
-        }
-        fComponents.addElement(fDTDScanner);
-
-        final String VALIDATOR = Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATOR_PROPERTY;
-        fValidator = (XMLValidator) fProperties.get(VALIDATOR);
-        if (fValidator == null) {
-            fValidator = createValidator();
-            fProperties.put(VALIDATOR, fValidator);
-        }
-        fComponents.addElement(fValidator);
-        
-        final String DATATYPE_VALIDATOR_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
-        fDatatypeValidatorFactory = (DatatypeValidatorFactory)
-            fProperties.get(DATATYPE_VALIDATOR_FACTORY);
-        if (fDatatypeValidatorFactory == null) {
-            fDatatypeValidatorFactory = createDatatypeValidatorFactory();
-            fProperties.put(DATATYPE_VALIDATOR_FACTORY,
-                            fDatatypeValidatorFactory);
+        catch (SAXException e) {
+            // do nothing
+            // REVISIT: What is the right thing to do? -Ac
         }
 
-    } // initialize()
+    } // <init>(SymbolTable,GrammarPool)
 
     //
-    // XMLParser methods
+    // Public methods
     //
 
-    /** 
-     * Reset all components before parsing. 
+    /**
+     * Set the locale to use for messages.
      *
-     * @throws SAXException Thrown if an error occurs during initialization.
+     * @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
      */
-    protected void reset() throws SAXException {
-
-        // setup document pipeline
-        fScanner.setDocumentHandler(fValidator);
-        fValidator.setDocumentHandler(fDocumentHandler);
-
-        // setup dtd pipeline
-        fDTDScanner.setDTDHandler(fValidator);
-        fValidator.setDTDHandler(fDTDHandler);
-
-        // setup dtd content model pipeline
-        fDTDScanner.setDTDContentModelHandler(fValidator);
-        fValidator.setDTDContentModelHandler(fDTDContentModelHandler);
-
-        // the following will reset every component
-        super.reset();
-
-    } // reset(XMLParser)
+    public void setLocale(Locale locale) throws SAXException {
+        if (fErrorReporter == null) {
+            if (fEntityManager == null) {
+                fEntityManager = createEntityManager();
+                fProperties.put(ENTITY_MANAGER, fEntityManager);
+                addComponent(fEntityManager);
+                fLocator = (Locator)fEntityManager.getEntityScanner();
+            }
+            fErrorReporter =
+                createErrorReporter(fEntityManager.getEntityScanner());
+            fProperties.put(ERROR_REPORTER, fErrorReporter);
+            addComponent(fErrorReporter);
+        }
+        fErrorReporter.setLocale(locale);
+    } // setLocale(Locale)
 
     //
-    // XMLReader methods
+    // XMLParserConfiguration methods
     //
 
     /**
@@ -263,8 +326,7 @@
      * @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 {
+    public void parse(InputSource source) throws SAXException, IOException {
 
         if (fParseInProgress) {
             // REVISIT - need to add new error message
@@ -303,8 +365,99 @@
     } // parse(InputSource)
 
     //
-    // XMLParser methods
+    // Protected methods
     //
+    
+    // initialization
+
+    /**
+     * Initialize the parser with all the components specified via the
+     * properties plus any missing ones. This method MUST be called before
+     * parsing. It is not called from the constructor though, so that the
+     * application can pass in any components it wants by presetting the
+     * relevant property.
+     */
+    protected void initialize() {
+        super.initialize();
+
+        // create and register missing components
+        if (fErrorReporter == null) {
+            fErrorReporter =
+                createErrorReporter(fEntityManager.getEntityScanner());
+            fProperties.put(ERROR_REPORTER, fErrorReporter);
+            addComponent(fErrorReporter);
+        }
+
+        if (fEntityManager == null) {
+            fEntityManager = createEntityManager();
+            fProperties.put(ENTITY_MANAGER, fEntityManager);
+            addComponent(fEntityManager);
+            fLocator = (Locator)fEntityManager.getEntityScanner();
+        }
+
+        if (fGrammarPool == null) {
+            fGrammarPool = new GrammarPool();
+            fProperties.put(GRAMMAR_POOL, fGrammarPool);
+        }
+
+        if (fScanner == null) {
+            fScanner = createDocumentScanner();
+            fProperties.put(DOCUMENT_SCANNER, fScanner);
+            addComponent(fScanner);
+        }
+
+        if (fDTDScanner == null) {
+            fDTDScanner = createDTDScanner();
+            fProperties.put(DTD_SCANNER, fDTDScanner);
+            addComponent(fDTDScanner);
+        }
+
+        if (fValidator == null) {
+            fValidator = createValidator();
+            fProperties.put(VALIDATOR, fValidator);
+            addComponent(fValidator);
+        }
+        
+        if (fDatatypeValidatorFactory == null) {
+            fDatatypeValidatorFactory = createDatatypeValidatorFactory();
+            fProperties.put(DATATYPE_VALIDATOR_FACTORY,
+                            fDatatypeValidatorFactory);
+        }
+
+        // add message formatters
+        if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
+            XMLMessageFormatter xmft = new XMLMessageFormatter();
+            fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
+            fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
+        }
+
+    } // initialize()
+
+    /** 
+     * Reset all components before parsing. 
+     *
+     * @throws SAXException Thrown if an error occurs during initialization.
+     */
+    protected void reset() throws SAXException {
+
+        // setup document pipeline
+        fScanner.setDocumentHandler(fValidator);
+        fValidator.setDocumentHandler(fDocumentHandler);
+
+        // setup dtd pipeline
+        fDTDScanner.setDTDHandler(fValidator);
+        fValidator.setDTDHandler(fDTDHandler);
+
+        // setup dtd content model pipeline
+        fDTDScanner.setDTDContentModelHandler(fValidator);
+        fValidator.setDTDContentModelHandler(fDTDContentModelHandler);
+
+        // the following will reset every component
+        super.reset();
+
+    } // reset()
+
+    // features and properties
 
     /**
      * Check a feature. If feature is know and supported, this method simply
@@ -424,12 +577,18 @@
 
     } // checkProperty(String)
 
-    //
-    // Protected methods
-    //
-
     // factory methods
 
+    /** Creates an entity manager. */
+    protected XMLEntityManager createEntityManager() {
+        return new XMLEntityManager();
+    } // createEntityManager():XMLEntityManager
+
+    /** Creates an error reporter. */
+    protected XMLErrorReporter createErrorReporter(Locator locator) {
+        return new XMLErrorReporter(locator);
+    } // createErrorReporter(Locator):XMLErrorReporter
+
     /** Create a document scanner. */
     protected XMLDocumentScanner createDocumentScanner() {
         return new XMLDocumentScanner();
diff --git a/src/org/apache/xerces/parsers/XMLParser.java b/src/org/apache/xerces/parsers/XMLParser.java
index 9ea2257..efaa294 100644
--- a/src/org/apache/xerces/parsers/XMLParser.java
+++ b/src/org/apache/xerces/parsers/XMLParser.java
@@ -60,6 +60,9 @@
 import java.io.IOException;
 import java.util.Locale;
 
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
+
 import org.xml.sax.EntityResolver;
 import org.xml.sax.ErrorHandler;
 import org.xml.sax.InputSource;
@@ -69,6 +72,17 @@
 
 /**
  * Base class of all XML-related parsers.
+ * <p>
+ * In addition to the features and properties recognized by the parser
+ * configuration, this parser recognizes these additional features and
+ * properties:
+ * <ul>
+ * <li>Properties
+ *  <ul>
+ *   <li>http://apache.org/xml/properties/internal/error-handler</li>
+ *   <li>http://apache.org/xml/properties/internal/entity-resolver</li>
+ *  </ul>
+ * </ul>
  *
  * @author Stubs generated by DesignDoc on Mon Sep 11 11:10:57 PDT 2000
  * @author Arnaud  Le Hors, IBM
@@ -79,10 +93,23 @@
 public abstract class XMLParser {
 
     //
+    // Constants
+    //
+
+    /** Property identifier: entity resolver. */
+    protected static final String ENTITY_RESOLVER = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+
+    /** Property identifier: error handler. */
+    protected static final String ERROR_HANDLER = 
+        Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
+
+    //
     // Data
     //
 
-    ParserConfiguration fConfiguration;
+    /** The parser configuration. */
+    protected XMLParserConfiguration fConfiguration;
 
     //
     // Constructors
@@ -91,11 +118,18 @@
     /**
      * Default Constructor.
      */
-    protected XMLParser(ParserConfiguration config) {
+    protected XMLParser(XMLParserConfiguration config) {
 
+        // save configuration
         fConfiguration = config;
 
-    } // <init>(ParserConfiguration)
+        // add default recognized properties
+        final String[] recognizedProperties = {
+            ENTITY_RESOLVER, ERROR_HANDLER,
+        };
+        fConfiguration.addRecognizedProperties(recognizedProperties);
+
+    } // <init>(XMLParserConfiguration)
 
     //
     // Public methods
@@ -114,11 +148,8 @@
      * @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 {
-
-        fConfiguration.parse(systemId);
-
+    public void parse(String systemId) throws SAXException, IOException {
+        parse(new InputSource(systemId));
     } // parse(String)
 
     /**
@@ -145,7 +176,12 @@
      */
     public void setEntityResolver(EntityResolver resolver) {
 
-        fConfiguration.setEntityResolver(resolver);
+        try {
+            setProperty(ENTITY_RESOLVER, resolver);
+        }
+        catch (SAXException e) {
+            // do nothing
+        }
 
     } // setEntityResolver(EntityResolver)
 
@@ -158,7 +194,14 @@
      */
     public EntityResolver getEntityResolver() {
 
-        return fConfiguration.getEntityResolver();
+        EntityResolver entityResolver = null;
+        try {
+            entityResolver = (EntityResolver)getProperty(ENTITY_RESOLVER);
+        }
+        catch (SAXException e) {
+            // do nothing
+        }
+        return entityResolver;
 
     } // getEntityResolver():EntityResolver
 
@@ -182,7 +225,12 @@
      */
     public void setErrorHandler(ErrorHandler errorHandler) {
 
-        fConfiguration.setErrorHandler(errorHandler);
+        try {
+            setProperty(ERROR_HANDLER, errorHandler);
+        }
+        catch (SAXException e) {
+            // do nothing
+        }
 
     } // setErrorHandler(ErrorHandler)
 
@@ -195,7 +243,14 @@
      */
     public ErrorHandler getErrorHandler() {
 
-        return fConfiguration.getErrorHandler();
+        ErrorHandler errorHandler = null;
+        try {
+            errorHandler = (ErrorHandler)getProperty(ERROR_HANDLER);
+        }
+        catch (SAXException e) {
+            // do nothing
+        }
+        return errorHandler;
 
     } // getErrorHandler():ErrorHandler
 
@@ -291,17 +346,4 @@
 
     } // getProperty(String):Object
 
-    //
-    // Protected methods
-    //
-
-    /**
-     * reset all components before parsing
-     */
-    protected void reset() throws SAXException {
-
-        fConfiguration.reset();
-
-    } // reset()
-
 } // class XMLParser