You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by el...@apache.org on 2003/07/18 19:34:39 UTC

cvs commit: xml-xerces/java/src/org/apache/xerces/xinclude XIncludeTextReader.java MultipleScopeNamespaceSupport.java XIncludeFatalError.java XIncludeHandler.java XIncludeMessageFormatter.java XIncludeNamespaceSupport.java XIncludeResourceError.java

elena       2003/07/18 10:34:39

  Modified:    java/src/org/apache/xerces/impl Constants.java
               java/src/org/apache/xerces/impl/msg
                        XIncludeMessages.properties
               java/src/org/apache/xerces/parsers AbstractSAXParser.java
                        XIncludeParserConfiguration.java
               java/src/org/apache/xerces/xinclude
                        MultipleScopeNamespaceSupport.java
                        XIncludeFatalError.java XIncludeHandler.java
                        XIncludeMessageFormatter.java
                        XIncludeNamespaceSupport.java
                        XIncludeResourceError.java
  Added:       java/src/org/apache/xerces/xinclude XIncludeTextReader.java
  Log:
  XInclude implementation update:
  * Couple of bugs fixes, copyright date updates (Peter McCracken)
  * XIncludeHandler is now using EntityResover and structure of text inclusions has changed. (Peter McCracken)
  * Implementation for determining the encoding of  included documents
  when  parse="text". Encoding is determined  as per  section 4.3 of XInclude
  spec (Arun Yadav)
  * Support for unparsed entities and notations (Peter McCracken)
  * Introduce a new features "allow-dtd-events-after-endDTD" that controls sending unparsed entity declaration and notation declaration
  events outside of start/end DTD events. (Peter McCracken)
  
  There is still no support for XPointer fragments.
  
  Revision  Changes    Path
  1.31      +5 -2      xml-xerces/java/src/org/apache/xerces/impl/Constants.java
  
  Index: Constants.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/Constants.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- Constants.java	24 Jun 2003 21:56:58 -0000	1.30
  +++ Constants.java	18 Jul 2003 17:34:37 -0000	1.31
  @@ -99,6 +99,9 @@
       /** External parameter entities feature ("external-parameter-entities "). */
       public static final String EXTERNAL_PARAMETER_ENTITIES_FEATURE = "external-parameter-entities";
   
  +    /** Allow unparsed entity and notation declaration events to be sent after the end DTD event ("allow-dtd-events-after-endDTD") */
  +    public static final String ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE = "allow-dtd-events-after-endDTD";
  +
       // sax properties
   
       /** SAX property prefix ("http://xml.org/sax/properties/"). */
  @@ -268,7 +271,7 @@
   
       /** Standard URI conformant feature ("standard-uri-conformant"). */
       public static final String STANDARD_URI_CONFORMANT_FEATURE = "standard-uri-conformant";
  -    
  +
       // xerces properties
   
       /** Xerces properties prefix ("http://apache.org/xml/properties/"). */
  
  
  
  1.2       +3 -1      xml-xerces/java/src/org/apache/xerces/impl/msg/XIncludeMessages.properties
  
  Index: XIncludeMessages.properties
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/msg/XIncludeMessages.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XIncludeMessages.properties	24 Jun 2003 21:56:58 -0000	1.1
  +++ XIncludeMessages.properties	18 Jul 2003 17:34:38 -0000	1.2
  @@ -6,13 +6,15 @@
   NoFallback = An 'include' failed, and no 'fallback' element was found.
   MultipleFallbacks = The [children] of an 'include' element cannot contain more than one 'fallback' element.
   FallbackParent = An 'include' element is not parent of 'fallback' element.
  -IncludeParent = The parent of an 'include' element cannot be another 'include' element.
  +IncludeChild = A ''{0}'' element cannot be a child of an 'include' element.
   HrefMissing = The 'href' attribute of an 'include' element is missing.
   RecursiveInclude = Recursive include detected.
   InvalidParseValue = Invalid value for ''parse'' attribute on ''include'' element: ''{0}''.
   XMLParseError = Error parsing invalid XML file.
   XMLResourceError = Resource error reading XML file. Reason: {0}
   TextResourceError = Resource error reading text file. Reason: {0}
  +NonDuplicateNotation = Multiple notations were used which had the name ''{0}'', but which were not determined to be duplicates.
  +NonDuplicateUnparsedEntity = Multiple unparsed entities were used which had the name ''{0}'', but which were not determined to be duplicates.
   
   # Messages from erroneous set-up
   IncompatibleNamespaceContext = The type of the NamespaceContext is incompatible with using XInclude; it must be an instance of XIncludeNamespaceSupport
  
  
  
  1.42      +13 -1     xml-xerces/java/src/org/apache/xerces/parsers/AbstractSAXParser.java
  
  Index: AbstractSAXParser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/parsers/AbstractSAXParser.java,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- AbstractSAXParser.java	8 May 2003 20:11:58 -0000	1.41
  +++ AbstractSAXParser.java	18 Jul 2003 17:34:38 -0000	1.42
  @@ -134,6 +134,12 @@
       protected static final String STRING_INTERNING =
           Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
       
  +    /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
  +    // this is not meant to be a recognized feature, but we need it here to use
  +    // if it is already a recognized feature for the pipeline
  +    protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
  +        Constants.SAX_FEATURE_PREFIX + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
  +
       /** Recognized features. */
       private static final String[] RECOGNIZED_FEATURES = {
           NAMESPACES,
  @@ -234,6 +240,12 @@
           config.addRecognizedFeatures(RECOGNIZED_FEATURES);
           config.addRecognizedProperties(RECOGNIZED_PROPERTIES);
   
  +        try {
  +            config.setFeature(ALLOW_UE_AND_NOTATION_EVENTS, false);
  +        }
  +        catch (XMLConfigurationException e) {
  +            // it wasn't a recognized feature, so we don't worry about it
  +        }
       } // <init>(XMLParserConfiguration)
   
       //
  
  
  
  1.2       +66 -39    xml-xerces/java/src/org/apache/xerces/parsers/XIncludeParserConfiguration.java
  
  Index: XIncludeParserConfiguration.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/parsers/XIncludeParserConfiguration.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XIncludeParserConfiguration.java	24 Jun 2003 21:56:58 -0000	1.1
  +++ XIncludeParserConfiguration.java	18 Jul 2003 17:34:38 -0000	1.2
  @@ -60,9 +60,12 @@
   import org.apache.xerces.util.SymbolTable;
   import org.apache.xerces.xinclude.XIncludeHandler;
   import org.apache.xerces.xinclude.XIncludeNamespaceSupport;
  +import org.apache.xerces.xni.XMLDTDHandler;
   import org.apache.xerces.xni.XMLDocumentHandler;
   import org.apache.xerces.xni.grammars.XMLGrammarPool;
   import org.apache.xerces.xni.parser.XMLComponentManager;
  +import org.apache.xerces.xni.parser.XMLConfigurationException;
  +import org.apache.xerces.xni.parser.XMLDTDSource;
   import org.apache.xerces.xni.parser.XMLDocumentSource;
   
   /**
  @@ -70,7 +73,11 @@
    */
   public class XIncludeParserConfiguration extends XML11Configuration {
   
  -    private XIncludeHandler fXIncludeComponent;
  +    private XIncludeHandler fXIncludeHandler;
  +
  +    /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
  +    protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
  +        Constants.SAX_FEATURE_PREFIX + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
   
       /** Property identifier: error reporter. */
       protected static final String XINCLUDE_HANDLER =
  @@ -83,7 +90,6 @@
       /** Default constructor. */
       public XIncludeParserConfiguration() {
           this(null, null, null);
  -        //this(null, new XMLGrammarPoolImpl(), null);
       } // <init>()
   
       /** 
  @@ -93,7 +99,6 @@
        */
       public XIncludeParserConfiguration(SymbolTable symbolTable) {
           this(symbolTable, null, null);
  -        //this(symbolTable, new XMLGrammarPoolImpl(), null);
       } // <init>(SymbolTable)
   
       /**
  @@ -131,8 +136,11 @@
           XMLComponentManager parentSettings) {
           super(symbolTable, grammarPool, parentSettings);
   
  +        fXIncludeHandler = new XIncludeHandler();
  +        addComponent(fXIncludeHandler);
  +            
           final String[] recognizedFeatures = {
  -            // XINCLUDE_PROCESSING TODO: should this be a feature?
  +            ALLOW_UE_AND_NOTATION_EVENTS
           };
           addRecognizedFeatures(recognizedFeatures);
   
  @@ -140,51 +148,70 @@
           final String[] recognizedProperties =
               { XINCLUDE_HANDLER, NAMESPACE_CONTEXT };
           addRecognizedProperties(recognizedProperties);
  -
  +        
  +        setFeature(ALLOW_UE_AND_NOTATION_EVENTS, true);
  +        
  +        setProperty(XINCLUDE_HANDLER, fXIncludeHandler);
           setProperty(NAMESPACE_CONTEXT, new XIncludeNamespaceSupport());
  -
  -        fXIncludeComponent = new XIncludeHandler();
  -        setProperty(XINCLUDE_HANDLER, fXIncludeComponent);
  -        addComponent(fXIncludeComponent);
       } // <init>(SymbolTable,XMLGrammarPool)}
   
       /** Configures the pipeline. */
       protected void configurePipeline() {
  +        // setup document pipeline
           super.configurePipeline();
   
  -        // setup document pipeline
  -        // TODO: actually use XINCLUDE_PROCESSING feature, if we decide to implement it
  -        if (true /*fFeatures.get(XINCLUDE_PROCESSING) == Boolean.TRUE*/
  -            ) {
  -            if (fXIncludeComponent == null) {
  -                fXIncludeComponent = new XIncludeHandler();
  -                addComponent(fXIncludeComponent);
  -            }
  +        // insert before fSchemaValidator, if one exists.
  +        XMLDocumentSource prev = null;
  +        if (fFeatures.get(XMLSCHEMA_VALIDATION) == Boolean.TRUE) {
  +            // we don't have to worry about fSchemaValidator being null, since
  +            // super.configurePipeline() instantiated it if the feature was set
  +            prev = fSchemaValidator.getDocumentSource();
  +        }
  +        // Otherwise, insert after the last component in the pipeline
  +        else {
  +            prev = fLastComponent;
  +        }
   
  -            // insert before fSchemaValidator, if one exists.
  -            XMLDocumentSource prev = null;
  -            if (fFeatures.get(XMLSCHEMA_VALIDATION) == Boolean.TRUE) {
  -                // we don't have to worry about fSchemaValidator being null, since
  -                // super.configurePipeline() instantiated it if the feature was set
  -                prev = fSchemaValidator.getDocumentSource();
  +        if (prev != null) {
  +            XMLDocumentHandler next = prev.getDocumentHandler();
  +            if (next != null) {
  +                fXIncludeHandler.setDocumentHandler(next);
  +                next.setDocumentSource(fXIncludeHandler);
               }
  -            // Otherwise, insert after the last component in the pipeline
  -            else {
  -                prev = fLastComponent;
  +            prev.setDocumentHandler(fXIncludeHandler);
  +            fXIncludeHandler.setDocumentSource(prev);
  +        }
  +        else {
  +            setDocumentHandler(fXIncludeHandler);
  +        }
  +    } // configurePipeline()
  +    
  +    protected void configureDTDPipeline() {
  +        super.configureDTDPipeline();
  +        
  +        // It doesn't really matter where we stick the XIncludeHandler in the
  +        // DTD pipeline, since it doesn't ever modify anything.
  +        // We'll put it right after the scanner
  +        if (fDTDScanner != null) {
  +            XMLDTDHandler next = fDTDScanner.getDTDHandler();
  +            if (next != null) {
  +                fXIncludeHandler.setDTDHandler(next);
  +                next.setDTDSource(fXIncludeHandler);
               }
  +            fDTDScanner.setDTDHandler(fXIncludeHandler);
  +            fXIncludeHandler.setDTDSource(fDTDScanner);            
  +        }
  +        else {
  +            setDTDHandler(fXIncludeHandler);
  +        }
  +    }
  +    
  +    public void setProperty(String propertyId, Object value)
  +        throws XMLConfigurationException {
   
  -            if (prev != null) {
  -                XMLDocumentHandler next = prev.getDocumentHandler();
  -                if (next != null) {
  -                    fXIncludeComponent.setDocumentHandler(next);
  -                    next.setDocumentSource(fXIncludeComponent);
  -                }
  -                prev.setDocumentHandler(fXIncludeComponent);
  -                fXIncludeComponent.setDocumentSource(prev);
  -            }
  -            else {
  -                setDocumentHandler(fXIncludeComponent);
  -            }
  +        if (propertyId.equals(XINCLUDE_HANDLER)) {
           }
  -    } // configurePipeline()
  +
  +        super.setProperty(propertyId, value);
  +    } // setProperty(String,Object)
   }
  
  
  
  1.2       +1 -1      xml-xerces/java/src/org/apache/xerces/xinclude/MultipleScopeNamespaceSupport.java
  
  Index: MultipleScopeNamespaceSupport.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/MultipleScopeNamespaceSupport.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MultipleScopeNamespaceSupport.java	25 Jun 2003 00:48:32 -0000	1.1
  +++ MultipleScopeNamespaceSupport.java	18 Jul 2003 17:34:38 -0000	1.2
  @@ -49,7 +49,7 @@
    *
    * 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
  + * originally based on software copyright (c) 2003, International
    * Business Machines, Inc., http://www.apache.org.  For more
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
  
  
  
  1.2       +1 -3      xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeFatalError.java
  
  Index: XIncludeFatalError.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeFatalError.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XIncludeFatalError.java	25 Jun 2003 00:48:58 -0000	1.1
  +++ XIncludeFatalError.java	18 Jul 2003 17:34:38 -0000	1.2
  @@ -49,14 +49,12 @@
    *
    * 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
  + * originally based on software copyright (c) 2003, 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.xinclude;
  -
  -import org.apache.xerces.xni.XNIException;
   
   /**
    * @author Peter McCracken, IBM
  
  
  
  1.2       +928 -328  xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeHandler.java
  
  Index: XIncludeHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeHandler.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XIncludeHandler.java	25 Jun 2003 00:49:21 -0000	1.1
  +++ XIncludeHandler.java	18 Jul 2003 17:34:38 -0000	1.2
  @@ -49,7 +49,7 @@
    *
    * 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
  + * originally based on software copyright (c) 2003, International
    * Business Machines, Inc., http://www.apache.org.  For more
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
  @@ -58,46 +58,48 @@
   
   import java.io.File;
   import java.io.IOException;
  -import java.io.InputStreamReader;
   import java.net.MalformedURLException;
   import java.net.URL;
   import java.util.Enumeration;
  +import java.util.StringTokenizer;
   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.dtd.DTDGrammar;
  -import org.apache.xerces.impl.dtd.XMLDTDDescription;
   import org.apache.xerces.util.AugmentationsImpl;
   import org.apache.xerces.util.ObjectFactory;
  +import org.apache.xerces.util.ParserConfigurationSettings;
   import org.apache.xerces.util.XMLAttributesImpl;
  -import org.apache.xerces.util.XMLStringBuffer;
  +import org.apache.xerces.util.XMLResourceIdentifierImpl;
   import org.apache.xerces.util.XMLSymbols;
   import org.apache.xerces.util.URI.MalformedURIException;
   import org.apache.xerces.xni.Augmentations;
   import org.apache.xerces.xni.NamespaceContext;
   import org.apache.xerces.xni.QName;
   import org.apache.xerces.xni.XMLAttributes;
  +import org.apache.xerces.xni.XMLDTDHandler;
   import org.apache.xerces.xni.XMLDocumentHandler;
   import org.apache.xerces.xni.XMLLocator;
   import org.apache.xerces.xni.XMLResourceIdentifier;
   import org.apache.xerces.xni.XMLString;
   import org.apache.xerces.xni.XNIException;
  -import org.apache.xerces.xni.grammars.XMLGrammarDescription;
  -import org.apache.xerces.xni.grammars.XMLGrammarPool;
   import org.apache.xerces.xni.parser.XMLComponent;
   import org.apache.xerces.xni.parser.XMLComponentManager;
   import org.apache.xerces.xni.parser.XMLConfigurationException;
  +import org.apache.xerces.xni.parser.XMLDTDFilter;
  +import org.apache.xerces.xni.parser.XMLDTDSource;
   import org.apache.xerces.xni.parser.XMLDocumentFilter;
   import org.apache.xerces.xni.parser.XMLDocumentSource;
  +import org.apache.xerces.xni.parser.XMLEntityResolver;
   import org.apache.xerces.xni.parser.XMLInputSource;
   import org.apache.xerces.xni.parser.XMLParserConfiguration;
   
   /**
    * @author Peter McCracken, IBM
    */
  -public class XIncludeHandler implements XMLComponent, XMLDocumentFilter {
  +public class XIncludeHandler
  +    implements XMLComponent, XMLDocumentFilter, XMLDTDFilter {
   
       public final static String XINCLUDE_DEFAULT_CONFIGURATION =
           "org.apache.xerces.parsers.XIncludeParserConfiguration";
  @@ -134,50 +136,63 @@
               NamespaceContext.XMLNS_URI);
   
       // Processing States
  -    private final static Integer STATE_NORMAL_PROCESSING = new Integer(1);
  -    private final static Integer STATE_IGNORE = new Integer(2);
  -    private final static Integer STATE_EXPECT_FALLBACK = new Integer(3);
  +    private final static int STATE_NORMAL_PROCESSING = 1;
  +    private final static int STATE_IGNORE = 2;
  +    private final static int STATE_EXPECT_FALLBACK = 3;
   
       // recognized features and properties
   
  +    /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
  +    protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
  +        Constants.SAX_FEATURE_PREFIX
  +            + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
  +
       /** Property identifier: error handler. */
       protected static final String ERROR_REPORTER =
           Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
   
       /** Property identifier: grammar pool . */
  -    protected static final String GRAMMAR_POOL =
  -        Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
  +    protected static final String ENTITY_RESOLVER =
  +        Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
   
       /** Recognized features. */
  -    private static final String[] RECOGNIZED_FEATURES = {
  -    };
  +    private static final String[] RECOGNIZED_FEATURES =
  +        { ALLOW_UE_AND_NOTATION_EVENTS };
   
       /** Feature defaults. */
  -    private static final Boolean[] FEATURE_DEFAULTS = {
  -    };
  +    private static final Boolean[] FEATURE_DEFAULTS = { Boolean.TRUE };
   
       /** Recognized properties. */
   
  -    // TODO: make DEFAULT_XINCLUDE_PIPELINE a property?
       private static final String[] RECOGNIZED_PROPERTIES =
  -        { ERROR_REPORTER, GRAMMAR_POOL };
  +        { ERROR_REPORTER, ENTITY_RESOLVER };
   
       /** Property defaults. */
  -    private static final Object[] PROPERTY_DEFAULTS = { null, null, null, };
  +    private static final Object[] PROPERTY_DEFAULTS = { null, null };
   
  -    // Data
  +    // instance variables
   
  +    // for XMLDocumentFilter
       protected XMLDocumentHandler fDocumentHandler;
       protected XMLDocumentSource fDocumentSource;
   
  +    // for XMLDTDFilter
  +    protected XMLDTDHandler fDTDHandler;
  +    protected XMLDTDSource fDTDSource;
  +
  +    // for XIncludeHandler
       protected XIncludeHandler fParentXIncludeHandler;
   
  +    // for caching
  +    protected XMLParserConfiguration fChildConfig;
  +
       protected XMLLocator fDocLocation;
       protected XIncludeNamespaceSupport fNamespaceContext;
       protected XMLErrorReporter fErrorReporter;
  -    protected XMLGrammarPool fGrammarPool;
  -    protected XMLGrammarDescription fGrammarDesc;
  -    protected DTDGrammar fDTDGrammar;
  +    protected XMLEntityResolver fEntityResolver;
  +
  +    // used for passing features on to child XIncludeHandler objects
  +    protected ParserConfigurationSettings fSettings;
   
       // The current element depth.
       // This is used to access the appropriate level of the following stacks.
  @@ -188,40 +203,38 @@
       // is an include, and processing goes to the fallback.
       private int fRootDepth;
   
  -    // TODO: for performance, change these to expanding arrays
  +    // this value must be at least 1
  +    private static final int INITIAL_SIZE = 8;
   
       // Used to ensure that fallbacks are always children of include elements,
       // and that include elements are never children of other include elements.
       // An index contains true if the ancestor of the current element which resides
       // at that depth was an include element.
  -    private Vector fSawInclude;
  +    private boolean[] fSawInclude = new boolean[INITIAL_SIZE];
   
       // Ensures that only one fallback element can be at a single depth.
       // An index contains true if we have seen any fallback elements at that depth,
       // and it is only reset to false when the end tag of the parent is encountered.
  -    private Vector fSawFallback;
  +    private boolean[] fSawFallback = new boolean[INITIAL_SIZE];
   
       // The state of the processor at each given depth.
  -    private Vector fState;
  +    private int[] fState = new int[INITIAL_SIZE];
   
  -    // Constructors
  +    // buffering the necessary DTD events
  +    private Vector fNotations = new Vector();
  +    private Vector fUnparsedEntities = new Vector();
   
  -    public XIncludeHandler() {
  -        this(null);
  -    }
  +    private boolean fSendUEAndNotationEvents;
   
  -    private XIncludeHandler(XIncludeHandler parent) {
  -        fParentXIncludeHandler = parent;
  +    // Constructors
   
  +    public XIncludeHandler() {
           fDepth = 0;
           fRootDepth = 0;
   
  -        fSawFallback = new Vector();
  -        fSawFallback.add(Boolean.FALSE);
  -        fSawInclude = new Vector();
  -        fSawInclude.add(Boolean.FALSE);
  -        fState = new Vector();
  -        fState.add(STATE_NORMAL_PROCESSING);
  +        fSawFallback[fDepth] = false;
  +        fSawInclude[fDepth] = false;
  +        fState[fDepth] = STATE_NORMAL_PROCESSING;
       }
   
       // XMLComponent methods
  @@ -233,19 +246,61 @@
           fRootDepth = 0;
   
           try {
  -            setErrorReporter(
  -                (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER));
  +            fSendUEAndNotationEvents =
  +                componentManager.getFeature(ALLOW_UE_AND_NOTATION_EVENTS);
  +            if (fChildConfig != null) {
  +                fChildConfig.setFeature(
  +                    ALLOW_UE_AND_NOTATION_EVENTS,
  +                    fSendUEAndNotationEvents);
  +            }
  +        }
  +        catch (XMLConfigurationException e) {
  +        }
  +
  +        try {
  +            XMLErrorReporter value =
  +                (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
  +            setErrorReporter(value);
  +            if (fChildConfig != null) {
  +                fChildConfig.setProperty(ERROR_REPORTER, value);
  +            }
           }
           catch (XMLConfigurationException e) {
               fErrorReporter = null;
           }
  +
           try {
  -            fGrammarPool =
  -                (XMLGrammarPool)componentManager.getProperty(GRAMMAR_POOL);
  +            XMLEntityResolver value =
  +                (XMLEntityResolver)componentManager.getProperty(
  +                    ENTITY_RESOLVER);
  +            fEntityResolver = value;
  +            if (fChildConfig != null) {
  +                fChildConfig.setProperty(ENTITY_RESOLVER, value);
  +            }
           }
           catch (XMLConfigurationException e) {
  -            fGrammarPool = null;
  +            fEntityResolver = null;
           }
  +
  +        fSettings = new ParserConfigurationSettings();
  +
  +        Enumeration xercesFeatures = Constants.getXercesFeatures();
  +        while (xercesFeatures.hasMoreElements()) {
  +            String featureId = (String)xercesFeatures.nextElement();
  +            fSettings.addRecognizedFeatures(
  +                new String[] { Constants.XERCES_FEATURE_PREFIX + featureId });
  +            try {
  +                fSettings.setFeature(
  +                    featureId,
  +                    componentManager.getFeature(featureId));
  +            }
  +            catch (XMLConfigurationException e) {
  +                // componentManager doesn't support this feature,
  +                // so we won't worry about it
  +            }
  +        }
  +
  +        // don't reset fChildConfig -- we don't want it to share the same components
       } // reset(XMLComponentManager)
   
       /**
  @@ -274,6 +329,12 @@
        */
       public void setFeature(String featureId, boolean state)
           throws XMLConfigurationException {
  +        if (featureId.equals(ALLOW_UE_AND_NOTATION_EVENTS)) {
  +            fSendUEAndNotationEvents = state;
  +        }
  +        if (fSettings != null) {
  +            fSettings.setFeature(featureId, state);
  +        }
       } // setFeature(String,boolean)
   
       /**
  @@ -304,9 +365,15 @@
           throws XMLConfigurationException {
           if (propertyId.equals(ERROR_REPORTER)) {
               setErrorReporter((XMLErrorReporter)value);
  +            if (fChildConfig != null) {
  +                fChildConfig.setProperty(propertyId, value);
  +            }
           }
  -        if (propertyId.equals(GRAMMAR_POOL)) {
  -            fGrammarPool = (XMLGrammarPool)value;
  +        if (propertyId.equals(ENTITY_RESOLVER)) {
  +            fEntityResolver = (XMLEntityResolver)value;
  +            if (fChildConfig != null) {
  +                fChildConfig.setProperty(propertyId, value);
  +            }
           }
       } // setProperty(String,Object)
   
  @@ -346,15 +413,6 @@
           return null;
       } // getPropertyDefault(String):Object
   
  -    private void setErrorReporter(XMLErrorReporter reporter) {
  -        fErrorReporter = reporter;
  -        if (fErrorReporter != null) {
  -            fErrorReporter.putMessageFormatter(
  -                XIncludeMessageFormatter.XINCLUDE_DOMAIN,
  -                new XIncludeMessageFormatter());
  -        }
  -    }
  -
       public void setDocumentHandler(XMLDocumentHandler handler) {
           fDocumentHandler = handler;
       }
  @@ -372,9 +430,14 @@
           Augmentations augs)
           throws XNIException {
   
  -        if (!isRootDocument()
  -            && fParentXIncludeHandler.searchForRecursiveIncludes(locator)) {
  -            throw new XIncludeFatalError("RecursiveInclude", null);
  +        try {
  +            if (!isRootDocument()
  +                && fParentXIncludeHandler.searchForRecursiveIncludes(locator)) {
  +                throw new XIncludeFatalError("RecursiveInclude", null);
  +            }
  +        }
  +        catch (XIncludeFatalError e) {
  +            reportFatalError(e.getKey(), e.getArgs());
           }
   
           if (!(namespaceContext instanceof XIncludeNamespaceSupport)) {
  @@ -409,26 +472,6 @@
           String systemId,
           Augmentations augs)
           throws XNIException {
  -
  -        String eid = null;
  -        try {
  -            eid =
  -                XMLEntityManager.expandSystemId(
  -                    systemId,
  -                    fDocLocation.getExpandedSystemId(),
  -                    false);
  -        }
  -        catch (java.io.IOException e) {
  -        }
  -
  -        fGrammarDesc =
  -            new XMLDTDDescription(
  -                publicId,
  -                systemId,
  -                fDocLocation.getExpandedSystemId(),
  -                eid,
  -                rootElement);
  -
           if (isRootDocument() && fDocumentHandler != null) {
               fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
           }
  @@ -512,6 +555,13 @@
           else if (isFallbackElement(element)) {
               this.handleFallbackElement();
           }
  +        else if (hasXIncludeNamespace(element)) {
  +            if (getSawInclude(fDepth - 1)) {
  +                reportFatalError(
  +                    "IncludeChild",
  +                    new Object[] { element.rawname });
  +            }
  +        }
           else if (
               fDocumentHandler != null
                   && getState() == STATE_NORMAL_PROCESSING) {
  @@ -528,157 +578,6 @@
           fDepth--;
       }
   
  -    protected void handleFallbackElement() {
  -        setSawInclude(fDepth, false);
  -        fNamespaceContext.setContextInvalid();
  -        if (!getSawInclude(fDepth - 1)) {
  -            reportFatalError("FallbackParent");
  -        }
  -
  -        if (getSawFallback(fDepth)) {
  -            reportFatalError("MultipleFallbacks");
  -        }
  -        else {
  -            setSawFallback(fDepth, true);
  -        }
  -
  -        // either the state is STATE_EXPECT_FALLBACK or it's STATE_IGNORE
  -        // if we're ignoring, we want to stay ignoring. But if we're expecting this fallback element,
  -        // we want to signal that we should process the children
  -        if (getState() == STATE_EXPECT_FALLBACK) {
  -            setState(STATE_NORMAL_PROCESSING);
  -        }
  -    }
  -
  -    protected void handleIncludeElement(XMLAttributes attributes)
  -        throws XNIException {
  -        setSawInclude(fDepth, true);
  -        fNamespaceContext.setContextInvalid();
  -        if (getSawInclude(fDepth - 1)) {
  -            reportFatalError("IncludeParent");
  -        }
  -        if (getState() == STATE_IGNORE)
  -            return;
  -
  -        String href = attributes.getValue(XINCLUDE_ATTR_HREF);
  -
  -        XMLInputSource includedSource = null;
  -        if (href == null) {
  -            reportFatalError("HrefMissing");
  -        }
  -
  -        includedSource =
  -            new XMLInputSource(null, href, fDocLocation.getBaseSystemId());
  -
  -        String parse = attributes.getValue(XINCLUDE_ATTR_PARSE);
  -        if (parse == null) {
  -            parse = XINCLUDE_PARSE_XML;
  -        }
  -
  -        if (parse.equals(XINCLUDE_PARSE_XML)) {
  -            // create pipeline with no schema validator
  -            // TODO: implement DEFAULT_XINCLUDE_PROPERTY?
  -            String parserName = XINCLUDE_DEFAULT_CONFIGURATION;
  -            XMLParserConfiguration parserConfig =
  -                (XMLParserConfiguration)ObjectFactory.newInstance(
  -                    parserName,
  -                    ObjectFactory.findClassLoader(),
  -                    true);
  -
  -            // TODO: set all features on parserConfig to match this parser configuration
  -
  -            // we don't want a schema validator on the new pipeline
  -            parserConfig.setFeature(
  -                Constants.XERCES_FEATURE_PREFIX
  -                    + Constants.SCHEMA_VALIDATION_FEATURE,
  -                false);
  -
  -            // use the same error reporter
  -            parserConfig.setProperty(ERROR_REPORTER, fErrorReporter);
  -            // use the same namespace context
  -            parserConfig.setProperty(
  -                Constants.XERCES_PROPERTY_PREFIX
  -                    + Constants.NAMESPACE_CONTEXT_PROPERTY,
  -                fNamespaceContext);
  -
  -            XIncludeHandler newHandler =
  -                (XIncludeHandler)parserConfig.getProperty(
  -                    Constants.XERCES_PROPERTY_PREFIX
  -                        + Constants.XINCLUDE_HANDLER_PROPERTY);
  -            newHandler.setParent(this);
  -            newHandler.setDocumentHandler(this.getDocumentHandler());
  -
  -            try {
  -                fNamespaceContext.pushScope();
  -
  -                parserConfig.parse(includedSource);
  -            }
  -            catch (XIncludeFatalError e) {
  -                reportFatalError(e.getKey(), e.getArgs());
  -            }
  -            catch (XNIException e) {
  -                reportFatalError("XMLParseError");
  -            }
  -            catch (IOException e) {
  -                throw new XIncludeResourceError(
  -                    "XMLResourceError",
  -                    new Object[] { e.getMessage()});
  -            }
  -            finally {
  -                fNamespaceContext.popScope();
  -            }
  -        }
  -        // TODO: fix parsing as text.
  -        // Suggest writing a ParserConfiguration with an appropriate Scanner,
  -        // so that it will be parallel to how we treat parsing as XML
  -        else if (parse.equals(XINCLUDE_PARSE_TEXT)) {
  -            // TODO: This is what the spec says on encoding. Make sure it is being done.
  -            //     The encoding of such a resource is determined by:
  -            //         * external encoding information, if available, otherwise
  -            //         * if the media type of the resource is text/xml, application/xml, or matches the conventions text/*+xml or application/*+xml as described in XML Media Types [IETF RFC 3023], the encoding is recognized as specified in XML 1.0, otherwise
  -            //         * the value of the encoding attribute if one exists, otherwise
  -            //         * UTF-8.
  -            //     Byte sequences outside the range allowed by the encoding are a fatal error. Characters that are not permitted in XML documents also are a fatal error.
  -
  -            // encoding only matters when parse="text"
  -            String encoding = attributes.getValue(XINCLUDE_ATTR_ENCODING);
  -            if (encoding != null) {
  -                includedSource.setEncoding(encoding);
  -            }
  -
  -            String systemId = includedSource.getSystemId();
  -            InputStreamReader reader = null;
  -            try {
  -                URL url = this.createURL(includedSource);
  -                if (encoding != null) {
  -                    reader = new InputStreamReader(url.openStream(), encoding);
  -                }
  -                else {
  -                    reader = new InputStreamReader(url.openStream(), "UTF-8");
  -                }
  -
  -                XMLStringBuffer buffer = new XMLStringBuffer();
  -                while (reader.ready()) {
  -                    buffer.append((char)reader.read());
  -                }
  -                if (fDocumentHandler != null) {
  -                    fDocumentHandler.characters(
  -                        buffer,
  -                        modifyAugmentations(null, true));
  -                }
  -                reader.close();
  -            }
  -            catch (IOException e) {
  -                throw new XIncludeResourceError(
  -                    "TextResourceError",
  -                    new Object[] { e.getMessage()});
  -            }
  -        }
  -        else {
  -            reportFatalError("InvalidParseValue", new Object[] { parse });
  -        }
  -    }
  -
       public void endElement(QName element, Augmentations augs)
           throws XNIException {
   
  @@ -789,14 +688,446 @@
           return fDocumentSource;
       }
   
  +    // DTDHandler methods
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void attributeDecl(
  +        String elementName,
  +        String attributeName,
  +        String type,
  +        String[] enumeration,
  +        String defaultType,
  +        XMLString defaultValue,
  +        XMLString nonNormalizedDefaultValue,
  +        Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.attributeDecl(
  +                elementName,
  +                attributeName,
  +                type,
  +                enumeration,
  +                defaultType,
  +                defaultValue,
  +                nonNormalizedDefaultValue,
  +                augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#elementDecl(java.lang.String, java.lang.String, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void elementDecl(
  +        String name,
  +        String contentModel,
  +        Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.elementDecl(name, contentModel, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#endAttlist(org.apache.xerces.xni.Augmentations)
  +     */
  +    public void endAttlist(Augmentations augmentations) throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.endAttlist(augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#endConditional(org.apache.xerces.xni.Augmentations)
  +     */
  +    public void endConditional(Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.endConditional(augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#endDTD(org.apache.xerces.xni.Augmentations)
  +     */
  +    public void endDTD(Augmentations augmentations) throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.endDTD(augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#endExternalSubset(org.apache.xerces.xni.Augmentations)
  +     */
  +    public void endExternalSubset(Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.endExternalSubset(augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#endParameterEntity(java.lang.String, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void endParameterEntity(String name, Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.endParameterEntity(name, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#externalEntityDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void externalEntityDecl(
  +        String name,
  +        XMLResourceIdentifier identifier,
  +        Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.externalEntityDecl(name, identifier, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#getDTDSource()
  +     */
  +    public XMLDTDSource getDTDSource() {
  +        return fDTDSource;
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#ignoredCharacters(org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void ignoredCharacters(XMLString text, Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.ignoredCharacters(text, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#internalEntityDecl(java.lang.String, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void internalEntityDecl(
  +        String name,
  +        XMLString text,
  +        XMLString nonNormalizedText,
  +        Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.internalEntityDecl(
  +                name,
  +                text,
  +                nonNormalizedText,
  +                augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#notationDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void notationDecl(
  +        String name,
  +        XMLResourceIdentifier identifier,
  +        Augmentations augmentations)
  +        throws XNIException {
  +        this.addNotation(name, identifier, augmentations);
  +        if (fDTDHandler != null) {
  +            fDTDHandler.notationDecl(name, identifier, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#setDTDSource(org.apache.xerces.xni.parser.XMLDTDSource)
  +     */
  +    public void setDTDSource(XMLDTDSource source) {
  +        fDTDSource = source;
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#startAttlist(java.lang.String, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void startAttlist(String elementName, Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.startAttlist(elementName, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#startConditional(short, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void startConditional(short type, Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.startConditional(type, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#startDTD(org.apache.xerces.xni.XMLLocator, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void startDTD(XMLLocator locator, Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.startDTD(locator, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#startExternalSubset(org.apache.xerces.xni.XMLResourceIdentifier, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void startExternalSubset(
  +        XMLResourceIdentifier identifier,
  +        Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.startExternalSubset(identifier, augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#startParameterEntity(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, java.lang.String, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void startParameterEntity(
  +        String name,
  +        XMLResourceIdentifier identifier,
  +        String encoding,
  +        Augmentations augmentations)
  +        throws XNIException {
  +        if (fDTDHandler != null) {
  +            fDTDHandler.startParameterEntity(
  +                name,
  +                identifier,
  +                encoding,
  +                augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.XMLDTDHandler#unparsedEntityDecl(java.lang.String, org.apache.xerces.xni.XMLResourceIdentifier, java.lang.String, org.apache.xerces.xni.Augmentations)
  +     */
  +    public void unparsedEntityDecl(
  +        String name,
  +        XMLResourceIdentifier identifier,
  +        String notation,
  +        Augmentations augmentations)
  +        throws XNIException {
  +        this.addUnparsedEntity(name, identifier, notation, augmentations);
  +        if (fDTDHandler != null) {
  +            fDTDHandler.unparsedEntityDecl(
  +                name,
  +                identifier,
  +                notation,
  +                augmentations);
  +        }
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.parser.XMLDTDSource#getDTDHandler()
  +     */
  +    public XMLDTDHandler getDTDHandler() {
  +        return fDTDHandler;
  +    }
  +
  +    /* (non-Javadoc)
  +     * @see org.apache.xerces.xni.parser.XMLDTDSource#setDTDHandler(org.apache.xerces.xni.XMLDTDHandler)
  +     */
  +    public void setDTDHandler(XMLDTDHandler handler) {
  +        fDTDHandler = handler;
  +    }
  +
  +    // XIncludeHandler methods
  +
  +    private void setErrorReporter(XMLErrorReporter reporter) {
  +        fErrorReporter = reporter;
  +        if (fErrorReporter != null) {
  +            fErrorReporter.putMessageFormatter(
  +                XIncludeMessageFormatter.XINCLUDE_DOMAIN,
  +                new XIncludeMessageFormatter());
  +        }
  +    }
  +
  +    protected void handleFallbackElement() {
  +        setSawInclude(fDepth, false);
  +        fNamespaceContext.setContextInvalid();
  +        if (!getSawInclude(fDepth - 1)) {
  +            reportFatalError("FallbackParent");
  +        }
  +
  +        if (getSawFallback(fDepth)) {
  +            reportFatalError("MultipleFallbacks");
  +        }
  +        else {
  +            setSawFallback(fDepth, true);
  +        }
  +
  +        // either the state is STATE_EXPECT_FALLBACK or it's STATE_IGNORE
  +        // if we're ignoring, we want to stay ignoring. But if we're expecting this fallback element,
  +        // we want to signal that we should process the children
  +        if (getState() == STATE_EXPECT_FALLBACK) {
  +            setState(STATE_NORMAL_PROCESSING);
  +        }
  +    }
  +
  +    protected void handleIncludeElement(XMLAttributes attributes)
  +        throws XNIException {
  +        setSawInclude(fDepth, true);
  +        fNamespaceContext.setContextInvalid();
  +        if (getSawInclude(fDepth - 1)) {
  +            reportFatalError("IncludeChild", new Object[] { XINCLUDE_INCLUDE });
  +        }
  +        if (getState() == STATE_IGNORE)
  +            return;
  +
  +        String href = attributes.getValue(XINCLUDE_ATTR_HREF);
  +        String parse = attributes.getValue(XINCLUDE_ATTR_PARSE);
  +
  +        if (href == null) {
  +            reportFatalError("HrefMissing");
  +        }
  +        if (parse == null) {
  +            parse = XINCLUDE_PARSE_XML;
  +        }
  +
  +        XMLResourceIdentifier resourceIdentifier =
  +            new XMLResourceIdentifierImpl(
  +                null,
  +                href,
  +                fDocLocation.getBaseSystemId(),
  +                null);
  +
  +        XMLInputSource includedSource = null;
  +        if (fEntityResolver != null) {
  +            try {
  +                includedSource =
  +                    fEntityResolver.resolveEntity(resourceIdentifier);
  +            }
  +            catch (IOException e) {
  +                throw new XIncludeResourceError(
  +                    "XMLResourceError",
  +                    new Object[] { e.getMessage()});
  +            }
  +        }
  +
  +        if (includedSource == null) {
  +            includedSource =
  +                new XMLInputSource(null, href, fDocLocation.getBaseSystemId());
  +        }
  +
  +        if (parse.equals(XINCLUDE_PARSE_XML)) {
  +            // Instead of always creating a new configuration, the first one can be reused
  +            if (fChildConfig == null) {
  +                String parserName = XINCLUDE_DEFAULT_CONFIGURATION;
  +
  +                fChildConfig =
  +                    (XMLParserConfiguration)ObjectFactory.newInstance(
  +                        parserName,
  +                        ObjectFactory.findClassLoader(),
  +                        true);
  +
  +                // use the same error reporter
  +                fChildConfig.setProperty(ERROR_REPORTER, fErrorReporter);
  +                // use the same namespace context
  +                fChildConfig.setProperty(
  +                    Constants.XERCES_PROPERTY_PREFIX
  +                        + Constants.NAMESPACE_CONTEXT_PROPERTY,
  +                    fNamespaceContext);
  +
  +                XIncludeHandler newHandler = (XIncludeHandler)fChildConfig.getProperty(
  +                    Constants.XERCES_PROPERTY_PREFIX
  +                        + Constants.XINCLUDE_HANDLER_PROPERTY);
  +                newHandler.setParent(this);
  +                newHandler.setDocumentHandler(this.getDocumentHandler());
  +            }
  +
  +            // set all features on parserConfig to match this parser configuration
  +            Enumeration xercesFeatures = Constants.getXercesFeatures();
  +            while (xercesFeatures.hasMoreElements()) {
  +                String featureId = (String)xercesFeatures.nextElement();
  +                try {
  +                    fChildConfig.setFeature(
  +                        featureId,
  +                        fSettings.getFeature(featureId));
  +                }
  +                catch (XMLConfigurationException e) {
  +                    // parserConfig doesn't support this feature,
  +                    // so we won't worry about it
  +                }
  +            }
  +
  +            // we don't want a schema validator on the new pipeline
  +            fChildConfig.setFeature(
  +                Constants.XERCES_FEATURE_PREFIX
  +                    + Constants.SCHEMA_VALIDATION_FEATURE,
  +                false);
  +
  +            try {
  +                fNamespaceContext.pushScope();
  +                fChildConfig.parse(includedSource);
  +            }
  +            catch (XIncludeFatalError e) {
  +                reportFatalError(e.getKey(), e.getArgs());
  +            }
  +            catch (XNIException e) {
  +                reportFatalError("XMLParseError");
  +            }
  +            catch (IOException e) {
  +                throw new XIncludeResourceError(
  +                    "XMLResourceError",
  +                    new Object[] { e.getMessage()});
  +            }
  +            finally {
  +                fNamespaceContext.popScope();
  +            }
  +        }
  +        else if (parse.equals(XINCLUDE_PARSE_TEXT)) {
  +            String encoding = attributes.getValue(XINCLUDE_ATTR_ENCODING);
  +            includedSource.setEncoding(encoding);
  +
  +            XIncludeTextReader reader = null;
  +            try {
  +                reader = new XIncludeTextReader(includedSource, this);
  +                reader.parse();
  +            }
  +            catch (IOException e) {
  +                throw new XIncludeResourceError(
  +                    "TextResourceError",
  +                    new Object[] { e.getMessage()});
  +            }
  +            finally {
  +                if (reader != null) {
  +                    try {
  +                        reader.close();
  +                    }
  +                    catch (IOException e) {
  +                        throw new XIncludeResourceError(
  +                            "TextResourceError",
  +                            new Object[] { e.getMessage()});
  +                    }
  +                }
  +            }
  +        }
  +        else {
  +            reportFatalError("InvalidParseValue", new Object[] { parse });
  +        }
  +    }
  +
  +    protected boolean hasXIncludeNamespace(QName element) {
  +        return element.uri == XINCLUDE_NS_URI
  +            || fNamespaceContext.getURI(element.prefix) == XINCLUDE_NS_URI;
  +    }
  +
       protected boolean isIncludeElement(QName element) {
           return element.localpart.equals(XINCLUDE_INCLUDE)
  -            && fNamespaceContext.getURI(element.prefix).equals(XINCLUDE_NS_URI);
  +            && hasXIncludeNamespace(element);
       }
   
       protected boolean isFallbackElement(QName element) {
           return element.localpart.equals(XINCLUDE_FALLBACK)
  -            && fNamespaceContext.getURI(element.prefix).equals(XINCLUDE_NS_URI);
  +            && hasXIncludeNamespace(element);
       }
   
       protected boolean sameBaseURISourceAsParent() {
  @@ -805,8 +1136,17 @@
                   // We test if the included file is in the same directory as it's parent
                   // by creating a new URL, with the filename of the included file and the
                   // base of the parent, and checking if it is the same file as the included file
  -                URL input = createURL(fDocLocation);
  -                URL parent = createURL(fParentXIncludeHandler.fDocLocation);
  +                // TODO: does Java use IURIs by default?
  +                //       [Definition: An internationalized URI reference, or IURI, is a URI reference that directly uses [Unicode] characters.]
  +                // TODO: figure out what section 4.1.1 of the XInclude spec is talking about
  +                //       has to do with disallowed ASCII character escaping
  +                //       this ties in with the above IURI section, but I suspect Java already does it
  +                URL input = new URL(fDocLocation.getExpandedSystemId());
  +                URL parent =
  +                    new URL(
  +                        fParentXIncludeHandler
  +                            .fDocLocation
  +                            .getExpandedSystemId());
                   URL test = new URL(parent, new File(input.getFile()).getName());
                   return input.sameFile(test);
               }
  @@ -829,14 +1169,7 @@
                           false);
               }
               catch (MalformedURIException e) {
  -                reportFatalError("ExpandedSystemId");
  -                // returning false opens the possibility of attempting an infinite
  -                // recursive parse, in the case when:
  -                //   we can't resolve the system id
  -                //   AND continue-after-fatal-error is set
  -                //   AND there is actually a recursive parse.
  -                // But that's probably a pretty slim chance.
  -                return false;
  +                throw new XIncludeFatalError("ExpandedSystemId", null);
               }
           }
   
  @@ -864,6 +1197,20 @@
           return getSawFallback(fDepth - 1);
       }
   
  +    /**
  +     * Processes the XMLAttributes object of startElement() calls.  Performs the following tasks:
  +     * <ul>
  +     * <li> If the element is a top level included item whose [base URI] is different from the
  +     * [base URI] of the include parent, then an xml:base attribute is added to specify the
  +     * true [base URI]
  +     * <li> For all namespace prefixes which are in-scope in an included item, but not in scope
  +     * in the include parent, a xmlns:prefix attribute is added
  +     * <li> For all attributes with a type of ENTITY, ENTITIES or NOTATIONS, the notations and
  +     * unparsed entities are processed as described in the spec, sections 4.5.1 and 4.5.2
  +     * </ul>
  +     * @param attributes
  +     * @return
  +     */
       protected XMLAttributes processAttributes(XMLAttributes attributes) {
           if (isTopLevelIncludedItem()) {
               // Modify attributes to fix the base URI (spec 4.5.5).
  @@ -876,24 +1223,36 @@
   
                   // this causes errors with schema validation, since the schema doesn't specify that these elements can have an xml:base attribute
                   // TODO: add a user option to turn this off?
  +                // TODO: make this a relative URL, when possible
  +                // TODO: [base URI] is still an open issue with the working group.
  +                //       They're deciding if xml:base should be added if the [base URI] is different in terms
  +                //       of resolving relative references, or if it should be added if they are different at all.
  +                //       Revisit this after a final decision has been made.
  +                // TODO: Output a relative URI instead of an absolute one.
                   int index =
                       attributes.addAttribute(
                           XML_BASE_QNAME,
                           XMLSymbols.fCDATASymbol,
  -                        this.fDocLocation.getBaseSystemId());
  +                        fDocLocation.getBaseSystemId());
                   attributes.setSpecified(index, true);
               }
   
               // Modify attributes of included items to do namespace-fixup. (spec 4.5.4)
  +            // TODO: worry about null namespace?
               Enumeration inscopeNS = fNamespaceContext.getAllPrefixes();
               while (inscopeNS.hasMoreElements()) {
                   String prefix = (String)inscopeNS.nextElement();
                   String parentURI =
                       fNamespaceContext.getURIFromIncludeParent(prefix);
                   String uri = fNamespaceContext.getURI(prefix);
  -                if (attributes.getValue(NamespaceContext.XMLNS_URI, prefix)
  -                    == null
  -                    && parentURI != uri) {
  +                if (parentURI != uri
  +                    && (attributes != null
  +                        && attributes.getValue(NamespaceContext.XMLNS_URI, prefix)
  +                            == null)) {
  +                    if (attributes == null) {
  +                        attributes = new XMLAttributesImpl();
  +                    }
  +
                       QName ns = (QName)NEW_NS_ATTR_QNAME.clone();
                       ns.localpart = prefix;
                       ns.rawname += prefix;
  @@ -907,30 +1266,26 @@
               for (int i = 0; i < length; i++) {
                   String type = attributes.getType(i);
                   String value = attributes.getValue(i);
  -                if (checkGrammar()) {
  -                    // TODO: 4.5.1
  -                    if (type == XMLSymbols.fENTITYSymbol) {
  -
  -                    }
  -                    if (type == XMLSymbols.fENTITIESSymbol) {
  -
  -                    }
  -                    else if (type == XMLSymbols.fNOTATIONSymbol) {
  -                        // TODO: 4.5.2
  -                        //       Obtain [notations] property from DTD grammar
  -                        // TODO: 4.5.2 -- don't forget about searching unparsed entities for notations, too
  +                if (type == XMLSymbols.fENTITYSymbol) {
  +                    this.checkUnparsedEntity(value);
  +                }
  +                if (type == XMLSymbols.fENTITIESSymbol) {
  +                    // 4.5.1 - Unparsed Entities
  +                    StringTokenizer st = new StringTokenizer(value);
  +                    while (st.hasMoreTokens()) {
  +                        String entName = st.nextToken();
  +                        this.checkUnparsedEntity(entName);
                       }
                   }
  +                else if (type == XMLSymbols.fNOTATIONSymbol) {
  +                    // 4.5.2 - Notations
  +                    this.checkNotation(value);
  +                }
                   /* We actually don't need to do anything for 4.5.3, because at this stage the
                    * value of the attribute is just a string. It will be taken care of later
  -                 * in the pipeline, when the IDREFs are actually resolved against elements.
  -                 *
  -                 * TODO: what about when XInclude processing comes after schema validation? 
  +                 * in the pipeline, when the IDREFs are actually resolved against IDs.
                    * 
  -                 * if (type == XMLSymbols.fIDREFSymbol
  -                 *    || type == XMLSymbols.fIDREFSSymbol) {
  -                 *    // look at ValidationState for IDREFs (it should be a property)
  -                 * }
  +                 * if (type == XMLSymbols.fIDREFSymbol || type == XMLSymbols.fIDREFSSymbol) { }
                    */
               }
           }
  @@ -954,72 +1309,67 @@
           return augs;
       }
   
  -    protected Integer getState(int val) {
  -        return (Integer)this.fState.elementAt(val);
  +    protected int getState(int depth) {
  +        return fState[depth];
       }
   
  -    protected Integer getState() {
  -        return this.getState(fDepth);
  +    protected int getState() {
  +        return fState[fDepth];
       }
   
  -    protected void setState(Integer state) {
  -        while (fDepth >= fState.size()) {
  -            this.fState.add(STATE_NORMAL_PROCESSING);
  +    protected void setState(int state) {
  +        if (fDepth >= fState.length) {
  +            int[] newarray = new int[fDepth * 2];
  +            System.arraycopy(fState, 0, newarray, 0, fState.length);
  +            fState = newarray;
           }
  -        this.fState.set(fDepth, state);
  +        fState[fDepth] = state;
       }
   
       protected void setSawFallback(int depth, boolean val) {
  -        this.setSawFallback(depth, val ? Boolean.TRUE : Boolean.FALSE);
  -    }
  -
  -    protected void setSawFallback(int depth, Boolean val) {
  -        while (depth >= fSawFallback.size()) {
  -            this.fSawFallback.add(Boolean.FALSE);
  +        if (depth >= fSawFallback.length) {
  +            boolean[] newarray = new boolean[depth * 2];
  +            System.arraycopy(fSawFallback, 0, newarray, 0, fSawFallback.length);
  +            fSawFallback = newarray;
           }
  -        this.fSawFallback.set(depth, val);
  +        fSawFallback[depth] = val;
       }
   
       protected boolean getSawFallback(int depth) {
  -        if (depth >= this.fSawFallback.size()) {
  +        if (depth >= fSawFallback.length) {
               return false;
           }
  -        return ((Boolean)this.fSawFallback.elementAt(depth)).booleanValue();
  +        return fSawFallback[depth];
       }
   
  +    /**
  +     * Records that an &lt;include&gt; was encountered at the specified depth,
  +     * as an ancestor of the current item.
  +     * 
  +     * @param depth
  +     * @param val
  +     */
       protected void setSawInclude(int depth, boolean val) {
  -        this.setSawInclude(depth, val ? Boolean.TRUE : Boolean.FALSE);
  -    }
  -
  -    protected void setSawInclude(int depth, Boolean val) {
  -        while (depth >= fSawInclude.size()) {
  -            this.fSawInclude.add(Boolean.FALSE);
  +        if (depth >= fSawInclude.length) {
  +            boolean[] newarray = new boolean[depth * 2];
  +            System.arraycopy(fSawInclude, 0, newarray, 0, fSawInclude.length);
  +            fSawInclude = newarray;
           }
  -        this.fSawInclude.set(depth, val);
  +        fSawInclude[depth] = val;
       }
   
  +    /**
  +     * Return whether an &lt;include&gt; was encountered at the specified depth,
  +     * as an ancestor of the current item.
  +     * 
  +     * @param depth
  +     * @return
  +     */
       protected boolean getSawInclude(int depth) {
  -        if (depth >= this.fSawInclude.size()) {
  +        if (depth >= fSawInclude.length) {
               return false;
           }
  -        return ((Boolean)this.fSawInclude.elementAt(depth)).booleanValue();
  -    }
  -
  -    // TODO: this method really doesn't belong here; it's only temporary to make text include work
  -    //       see comment about XINCLUDE_PARSE_TEXT
  -    // TODO: does Java use IURIs by default?
  -    //       [Definition: An internationalized URI reference, or IURI, is a URI reference that directly uses [Unicode] characters.]
  -    // TODO: figure out what section 4.1.1 of the XInclude spec is talking about
  -    //       has to do with disallowed ASCII character escaping
  -    //       this ties in with the above IURI section, but I suspect Java already does it
  -    private URL createURL(XMLLocator source) throws MalformedURLException {
  -        return new URL(
  -            new URL(source.getBaseSystemId()),
  -            source.getExpandedSystemId());
  -    }
  -
  -    private URL createURL(XMLInputSource source) throws MalformedURLException {
  -        return new URL(new URL(source.getBaseSystemId()), source.getSystemId());
  +        return fSawInclude[depth];
       }
   
       protected void reportFatalError(String key) {
  @@ -1039,33 +1389,283 @@
           // at least the default error reporter
       }
   
  +    /**
  +     * Set the parent of this XIncludeHandler in the tree
  +     * @param parent
  +     */
       protected void setParent(XIncludeHandler parent) {
  -        this.fParentXIncludeHandler = parent;
  +        fParentXIncludeHandler = parent;
       }
   
       // used to know whether to pass declarations to the document handler
       protected boolean isRootDocument() {
  -        return this.fParentXIncludeHandler == null;
  +        return fParentXIncludeHandler == null;
       }
   
  -    private boolean checkGrammar() {
  -        /*        System.err.println("checking grammar");
  -                if (fDTDGrammar == null) {
  -                    System.err.println("grammar is null");
  -                    if (fGrammarDesc == null || fGrammarPool == null) {
  -                        System.err.println("bailed out");
  -                        return false;
  -                    }
  -                    fDTDGrammar =
  -                        (DTDGrammar)fGrammarPool.retrieveGrammar(fGrammarDesc);
  -                    System.err.println(fDTDGrammar);
  -                    return fDTDGrammar != null;
  -                }
  -                else {
  -                    System.err.println("have grammar!");
  -                    return true;
  +    /**
  +     * Caches an unparsed entity.
  +     * @param name the name of the unparsed entity
  +     * @param identifier the location of the unparsed entity
  +     * @param augmentations any Augmentations that were on the original unparsed entity declaration
  +     */
  +    protected void addUnparsedEntity(
  +        String name,
  +        XMLResourceIdentifier identifier,
  +        String notation,
  +        Augmentations augmentations) {
  +        UnparsedEntity ent = new UnparsedEntity();
  +        ent.name = name;
  +        ent.systemId = identifier.getLiteralSystemId();
  +        ent.publicId = identifier.getPublicId();
  +        ent.baseURI = identifier.getBaseSystemId();
  +        ent.notation = notation;
  +        ent.augmentations = augmentations;
  +        fUnparsedEntities.add(ent);
  +    }
  +
  +    /**
  +     * Caches a notation.
  +     * @param name the name of the notation
  +     * @param identifier the location of the notation
  +     * @param augmentations any Augmentations that were on the original notation declaration
  +     */
  +    protected void addNotation(
  +        String name,
  +        XMLResourceIdentifier identifier,
  +        Augmentations augmentations) {
  +        Notation not = new Notation();
  +        not.name = name;
  +        not.systemId = identifier.getLiteralSystemId();
  +        not.publicId = identifier.getPublicId();
  +        not.baseURI = identifier.getBaseSystemId();
  +        not.augmentations = augmentations;
  +        fNotations.add(not);
  +    }
  +
  +    /**
  +     * Checks if an UnparsedEntity with the given name was declared in the DTD of the document
  +     * for the current pipeline.  If so, then the notation for the UnparsedEntity is checked.
  +     * If that turns out okay, then the UnparsedEntity is passed to the root pipeline to
  +     * be checked for conflicts, and sent to the root DTDHandler.
  +     * 
  +     * @param entName the name of the UnparsedEntity to check
  +     */
  +    protected void checkUnparsedEntity(String entName) {
  +        UnparsedEntity ent = new UnparsedEntity();
  +        ent.name = entName;
  +        int index = fUnparsedEntities.indexOf(ent);
  +        if (index != -1) {
  +            ent = (UnparsedEntity)fUnparsedEntities.get(index);
  +            // first check the notation of the unparsed entity
  +            try {
  +                checkNotation(ent.notation);
  +            }
  +            catch (XIncludeFatalError e) {
  +                reportFatalError(e.getKey(), e.getArgs());
  +            }
  +
  +            try {
  +                checkAndSendUnparsedEntity(ent);
  +            }
  +            catch (XIncludeFatalError e) {
  +                reportFatalError(e.getKey(), e.getArgs());
  +            }
  +        }
  +    }
  +
  +    /**
  +     * Checks if a Notation with the given name was declared in the DTD of the document
  +     * for the current pipeline.  If so, that Notation is passed to the root pipeline to
  +     * be checked for conflicts, and sent to the root DTDHandler
  +     * 
  +     * @param notName the name of the Notation to check
  +     */
  +    protected void checkNotation(String notName) {
  +        Notation not = new Notation();
  +        not.name = notName;
  +        int index = fNotations.indexOf(not);
  +        if (index != -1) {
  +            not = (Notation)fNotations.get(index);
  +            try {
  +                checkAndSendNotation(not);
  +            }
  +            catch (XIncludeFatalError e) {
  +                reportFatalError(e.getKey(), e.getArgs());
  +            }
  +        }
  +    }
  +
  +    /**
  +     * The purpose of this method is to check if an UnparsedEntity conflicts with a previously
  +     * declared entity in the current pipeline stack.  If there is no conflict, the
  +     * UnparsedEntity is sent by the root pipeline.
  +     * 
  +     * @param ent the UnparsedEntity to check for conflicts
  +     * @throws XIncludeFatalError if there is an UnparsedEntity conflict as described in 4.5.1
  +     */
  +    protected void checkAndSendUnparsedEntity(UnparsedEntity ent)
  +        throws XIncludeFatalError {
  +        if (isRootDocument()) {
  +            int index = fUnparsedEntities.indexOf(ent);
  +            if (index == -1) {
  +                // There is no unparsed entity with the same name that we have sent.
  +                // Calling unparsedEntityDecl() will add the entity to our local store,
  +                // and also send the unparsed entity to the DTDHandler
  +                XMLResourceIdentifier id =
  +                    new XMLResourceIdentifierImpl(
  +                        ent.publicId,
  +                        ent.systemId,
  +                        ent.baseURI,
  +                        null);
  +                this.addUnparsedEntity(
  +                    ent.name,
  +                    id,
  +                    ent.notation,
  +                    ent.augmentations);
  +                if (fSendUEAndNotationEvents && fDTDHandler != null) {
  +                    fDTDHandler.unparsedEntityDecl(
  +                        ent.name,
  +                        id,
  +                        ent.notation,
  +                        ent.augmentations);
  +                }
  +            }
  +            else {
  +                UnparsedEntity localEntity =
  +                    (UnparsedEntity)fUnparsedEntities.get(index);
  +                if (!ent.isDuplicate(localEntity)) {
  +                    throw new XIncludeFatalError(
  +                        "NonDuplicateUnparsedEntity",
  +                        new Object[] { ent.name });
                   }
  -        */
  -        return false;
  +            }
  +        }
  +        else {
  +            fParentXIncludeHandler.checkAndSendUnparsedEntity(ent);
  +        }
  +    }
  +
  +    /**
  +     * The purpose of this method is to check if a Notation conflicts with a previously
  +     * declared notation in the current pipeline stack.  If there is no conflict, the
  +     * Notation is sent by the root pipeline.
  +     * 
  +     * @param not the Notation to check for conflicts
  +     * @throws XIncludeFatalError if there is a Notation conflict as described in 4.5.2
  +     */
  +    protected void checkAndSendNotation(Notation not)
  +        throws XIncludeFatalError {
  +        if (isRootDocument()) {
  +            int index = fNotations.indexOf(not);
  +            if (index == -1) {
  +                // There is no notation with the same name that we have sent.
  +                XMLResourceIdentifier id =
  +                    new XMLResourceIdentifierImpl(
  +                        not.publicId,
  +                        not.systemId,
  +                        not.baseURI,
  +                        null);
  +                this.addNotation(not.name, id, not.augmentations);
  +                if (fSendUEAndNotationEvents && fDTDHandler != null) {
  +                    fDTDHandler.notationDecl(not.name, id, not.augmentations);
  +                }
  +            }
  +            else {
  +                Notation localNotation = (Notation)fNotations.get(index);
  +                if (!not.isDuplicate(localNotation)) {
  +                    throw new XIncludeFatalError(
  +                        "NonDuplicateNotation",
  +                        new Object[] { not.name });
  +                }
  +            }
  +        }
  +        else {
  +            fParentXIncludeHandler.checkAndSendNotation(not);
  +        }
  +    }
  +
  +    // This is a storage class to hold information about the notations.
  +    // We're not using XMLNotationDecl because we don't want to lose the augmentations.
  +    protected class Notation {
  +        public String name;
  +        public String systemId;
  +        public String baseURI;
  +        public String publicId;
  +        public Augmentations augmentations;
  +
  +        // equals() returns true if two Notations have the same name.
  +        // Useful for searching Vectors for notations with the same name
  +        public boolean equals(Object obj) {
  +            if (obj == null) {
  +                return false;
  +            }
  +            if (obj instanceof Notation) {
  +                Notation other = (Notation)obj;
  +                return name.equals(other.name);
  +            }
  +            return false;
  +        }
  +
  +        // from 4.5.2
  +        // Notation items with the same [name], [system identifier],
  +        // [public identifier], and [declaration base URI] are considered
  +        // to be duplicate
  +        public boolean isDuplicate(Object obj) {
  +            if (obj != null && obj instanceof Notation) {
  +                Notation other = (Notation)obj;
  +                return name.equals(other.name)
  +                    && (systemId == other.systemId
  +                        || (systemId != null && systemId.equals(other.systemId)))
  +                    && (publicId == other.publicId
  +                        || (publicId != null && publicId.equals(other.publicId)))
  +                    && (baseURI == other.baseURI
  +                        || (baseURI != null && baseURI.equals(other.baseURI)));
  +            }
  +            return false;
  +        }
  +    }
  +
  +    // This is a storage class to hold information about the unparsed entities.
  +    // We're not using XMLEntityDecl because we don't want to lose the augmentations.
  +    protected class UnparsedEntity {
  +        public String name;
  +        public String systemId;
  +        public String baseURI;
  +        public String publicId;
  +        public String notation;
  +        public Augmentations augmentations;
  +
  +        // equals() returns true if two UnparsedEntities have the same name.
  +        // Useful for searching Vectors for entities with the same name
  +        public boolean equals(Object obj) {
  +            if (obj == null) {
  +                return false;
  +            }
  +            if (obj instanceof UnparsedEntity) {
  +                UnparsedEntity other = (UnparsedEntity)obj;
  +                return name.equals(other.name);
  +            }
  +            return false;
  +        }
  +
  +        // from 4.5.1:
  +        // Unparsed entity items with the same [name], [system identifier],
  +        // [public identifier], [declaration base URI], [notation name], and
  +        // [notation] are considered to be duplicate
  +        public boolean isDuplicate(Object obj) {
  +            if (obj != null && obj instanceof UnparsedEntity) {
  +                UnparsedEntity other = (UnparsedEntity)obj;
  +                return name.equals(other.name)
  +                    && (systemId == other.systemId
  +                        || (systemId != null && systemId.equals(other.systemId)))
  +                    && (publicId == other.publicId
  +                        || (publicId != null && publicId.equals(other.publicId)))
  +                    && (baseURI == other.baseURI
  +                        || (baseURI != null && baseURI.equals(other.baseURI)))
  +                    && (notation == other.notation
  +                        || (notation != null && notation.equals(other.notation)));
  +            }
  +            return false;
  +        }
       }
   } // class XIncludeHandler
  
  
  
  1.2       +1 -1      xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeMessageFormatter.java
  
  Index: XIncludeMessageFormatter.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeMessageFormatter.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XIncludeMessageFormatter.java	25 Jun 2003 00:50:29 -0000	1.1
  +++ XIncludeMessageFormatter.java	18 Jul 2003 17:34:38 -0000	1.2
  @@ -49,7 +49,7 @@
    *
    * 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) 2001, International
  + * originally based on software copyright (c) 2003, International
    * Business Machines, Inc., http://www.apache.org.  For more
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
  
  
  
  1.2       +1 -1      xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeNamespaceSupport.java
  
  Index: XIncludeNamespaceSupport.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeNamespaceSupport.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XIncludeNamespaceSupport.java	25 Jun 2003 00:50:59 -0000	1.1
  +++ XIncludeNamespaceSupport.java	18 Jul 2003 17:34:38 -0000	1.2
  @@ -49,7 +49,7 @@
    *
    * 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
  + * originally based on software copyright (c) 2003, International
    * Business Machines, Inc., http://www.apache.org.  For more
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
  
  
  
  1.2       +1 -3      xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeResourceError.java
  
  Index: XIncludeResourceError.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeResourceError.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XIncludeResourceError.java	25 Jun 2003 00:52:44 -0000	1.1
  +++ XIncludeResourceError.java	18 Jul 2003 17:34:38 -0000	1.2
  @@ -49,14 +49,12 @@
    *
    * 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
  + * originally based on software copyright (c) 2003, 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.xinclude;
  -
  -import org.apache.xerces.xni.XNIException;
   
   /**
    * @author Peter McCracken, IBM
  
  
  
  1.1                  xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeTextReader.java
  
  Index: XIncludeTextReader.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001-2003 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) 2003, 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.xinclude;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.Reader;
  import java.net.URL;
  import java.net.URLConnection;
  
  import org.apache.xerces.util.XMLStringBuffer;
  import org.apache.xerces.xni.parser.XMLInputSource;
  
  /**
   * @author Peter McCracken, IBM
   * @author Arun Yadav, Sun Microsystem
   */
  public class XIncludeTextReader {
  
      private Reader fReader;
      private XIncludeHandler fHandler;
      private XMLInputSource fSource;
      private boolean fCheckBOM = false;
  
      /**
       * Construct the XIncludeReader using the XMLInputSource and XIncludeHandler.
       *
       * @param source The XMLInputSource to use.
       * @param handler The XIncludeHandler to use.
       */
      public XIncludeTextReader(XMLInputSource source, XIncludeHandler handler)
          throws IOException {
          fHandler = handler;
          fSource = source;
      }
  
      /**
       * Return the Reader for given XMLInputSource.
       *
       * @param source The XMLInputSource to use.
       */
      protected Reader getReader(XMLInputSource source) throws IOException {
          if (source.getCharacterStream() != null) {
              return fReader = source.getCharacterStream();
          }
          else {
              InputStream stream = null;
  
              String encoding = source.getEncoding();
              if (encoding == null) {
                  encoding = "UTF-8";
              }
              if (source.getByteStream() != null) {
                  stream = source.getByteStream();
              }
              else {
                  URL url =
                      new URL(
                          new URL(source.getBaseSystemId()),
                          source.getSystemId());
                  stream = url.openStream();
                  URLConnection urlCon = url.openConnection();
  
                  String charset = urlCon.getContentEncoding();
                  String contentType = urlCon.getContentType();
  
                  /**  The encoding of such a resource is determined by:
                      1 external encoding information, if available, otherwise
                           -- the most common type of external information is the "charset" parameter of a MIME package
                      2 if the media type of the resource is text/xml, application/xml, or matches the conventions text/*+xml or application/*+xml as described in XML Media Types [IETF RFC 3023], the encoding is recognized as specified in XML 1.0, otherwise
                      3 the value of the encoding attribute if one exists, otherwise
                      4 UTF-8.
                   **/
                  if (charset != null) {
                      encoding = charset;
                  }
                  /* RFC2376 section 3.1: If  text/xml entity is received with
                  charset parameter omitted, then MIME processors and XML processors
                  MUST use the default charset value of "us-ascii". */
                  else if (contentType.equals("text/xml")) {
                      encoding = "US-ASCII";
                  }
                  /* RFC2376 section 3.1: If  text/xml entity is received with
                  charset parameter omitted, no information is provided about the
                  charset by the MIME Content-type header. Conforming  XML processors
                  MUST follow the requirements in section 4.3.3 of [REC-XML].
                  */
                  else if (contentType.equals("application/xml")) {
                      encoding = getEncodingName(stream);
  
                  }
                  else if (contentType.endsWith("+xml")) {
                      System.out.println("Not suppported");
                      // TODO: Error messages need to be defined.
                  }
                  //else 3  or 4.
              }
              return fReader = new InputStreamReader(stream, encoding);
          }
      }
  
      protected String getEncodingName(InputStream stream) throws IOException {
          final byte[] b4 = new byte[4];
          int count = 0;
          for (; count < 4; count++) {
              b4[count] = (byte)stream.read();
          }
          Object[] encodinginfo = getEncodingName(b4, count);
  
          // REVISIT: what to do if encodinginfo[1] == null
          //          Currently, this isn't a problem, since getEncodingName() will never
          //          return a null value, but the javadocs say it's possible.
          if (encodinginfo[1] != null
              && !((Boolean)encodinginfo[1]).booleanValue()) {
              stream.reset();
              fCheckBOM = false;
          }
          else {
              fCheckBOM = true;
          }
          return (String)encodinginfo[0];
      }
  
      /**
       * REVISIT: This code is take from org.apache.xerces.impl.XMLEntityManager.
       *          Is there any way we can share the code, without having it implemented twice?
       * 
       * Returns the IANA encoding name that is auto-detected from
       * the bytes specified, with the endian-ness of that encoding where appropriate.
       *
       * @param b4    The first four bytes of the input.
       * @param count The number of bytes actually read.
       * @return a 2-element array:  the first element, an IANA-encoding string,
       *  the second element a Boolean which is true iff the document is big endian, false
       *  if it's little-endian, and null if the distinction isn't relevant.
       */
      protected Object[] getEncodingName(byte[] b4, int count) {
  
          if (count < 2) {
              return new Object[] { "UTF-8", new Boolean(false)};
          }
  
          // UTF-16, with BOM
          int b0 = b4[0] & 0xFF;
          int b1 = b4[1] & 0xFF;
          if (b0 == 0xFE && b1 == 0xFF) {
              // UTF-16, big-endian
              return new Object[] { "UTF-16BE", new Boolean(true)};
          }
          if (b0 == 0xFF && b1 == 0xFE) {
              // UTF-16, little-endian
              return new Object[] { "UTF-16LE", new Boolean(true)};
          }
  
          // default to UTF-8 if we don't have enough bytes to make a
          // good determination of the encoding
          if (count < 3) {
              return new Object[] { "UTF-8", new Boolean(false)};
          }
  
          // UTF-8 with a BOM
          int b2 = b4[2] & 0xFF;
          if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
              return new Object[] { "UTF-8", new Boolean(true)};
          }
  
          // default to UTF-8 if we don't have enough bytes to make a
          // good determination of the encoding
          if (count < 4) {
              return new Object[] { "UTF-8", new Boolean(false)};
          }
  
          // other encodings
          int b3 = b4[3] & 0xFF;
          if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
              // UCS-4, big endian (1234), with BOM
              return new Object[] { "ISO-10646-UCS-4", new Boolean(true)};
          }
          if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
              // UCS-4, little endian (4321), with BOM
              return new Object[] { "ISO-10646-UCS-4", new Boolean(true)};
          }
          if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
              // UCS-4, unusual octet order (2143), with BOM
              // REVISIT: What should this be?
              return new Object[] { "ISO-10646-UCS-4", new Boolean(true)};
          }
          if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
              // UCS-4, unusual octect order (3412), with BOM
              // REVISIT: What should this be?
              return new Object[] { "ISO-10646-UCS-4", new Boolean(true)};
          }
          if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
              // UTF-16, big-endian, no BOM
              // (or could turn out to be UCS-2...
              // REVISIT: What should this be?
              return new Object[] { "UTF-16BE", new Boolean(false)};
          }
          if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
              // UTF-16, little-endian, no BOM
              // (or could turn out to be UCS-2...
              return new Object[] { "UTF-16LE", new Boolean(false)};
          }
          if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
              // EBCDIC, no BOM
              // a la xerces1, return CP037 instead of EBCDIC here
              return new Object[] { "CP037", new Boolean(false)};
          }
          if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
              // UCS-4, no BOM
              //
              return new Object[] { "UCS-4", new Boolean(false)};
          }
  
          // default encoding
          return new Object[] { "UTF-8", new Boolean(false)};
  
      } // getEncodingName(byte[],int):Object[]
  
      public void parse() throws IOException {
          XMLStringBuffer buffer = new XMLStringBuffer();
          fReader = getReader(fSource);
          if (fReader.ready()) {
              // deal with byte order mark, see spec 4.3
              if (!fCheckBOM) {
                  int bom = fReader.read();
                  // only include the character if it isn't the byte-order mark
                  if (bom != '\uFEFF') {
                      buffer.append((char)bom);
                  }
              }
  
              // REVISIT: We might want to consider sending the character events in chunks
              //          instead of reading them all.  This would be a space hog for large
              //          text includes.
              while (fReader.ready()) {
                  buffer.append((char)fReader.read());
              }
              if (fHandler != null) {
                  fHandler.characters(
                      buffer,
                      fHandler.modifyAugmentations(null, true));
              }
          }
      }
  
      public void close() throws IOException {
          if (fReader != null) {
              fReader.close();
          }
      }
  }
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org