gt:             String newHref = escapeHref(href);
context: /*
   * Copyright 2003-2005 The Apache Software Foundation.
   * 
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
   * 
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.xerces.xinclude;
  
  import java.io.CharConversionException;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Enumeration;
  import java.util.Locale;
  import java.util.Stack;
  import java.util.StringTokenizer;
  
  import org.apache.xerces.impl.Constants;
  import org.apache.xerces.impl.XMLEntityManager;
  import org.apache.xerces.impl.XMLErrorReporter;
  import org.apache.xerces.impl.io.MalformedByteSequenceException;
  import org.apache.xerces.impl.msg.XMLMessageFormatter;
  import org.apache.xerces.util.AugmentationsImpl;
  import org.apache.xerces.util.HTTPInputSource;
  import org.apache.xerces.util.IntStack;
  import org.apache.xerces.util.ParserConfigurationSettings;
  import org.apache.xerces.util.SecurityManager;
  import org.apache.xerces.util.SymbolTable;
  import org.apache.xerces.util.URI;
  import org.apache.xerces.util.XMLAttributesImpl;
  import org.apache.xerces.util.XMLResourceIdentifierImpl;
  import org.apache.xerces.util.XMLChar;
  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.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;
  import org.apache.xerces.xpointer.XPointerHandler;
  import org.apache.xerces.xpointer.XPointerProcessor;
  
  /**
   * <p>
   * This is a pipeline component which performs XInclude handling, according to the
   * W3C specification for XML Inclusions.
   * </p>
   * <p>
   * This component analyzes each event in the pipeline, looking for &lt;include&gt;
   * elements. An &lt;include&gt; element is one which has a namespace of
   * <code>http://www.w3.org/2001/XInclude</code> and a localname of <code>include</code>.
   * When it finds an &lt;include&gt; element, it attempts to include the file specified
   * in the <code>href</code> attribute of the element.  If inclusion succeeds, all
   * children of the &lt;include&gt; element are ignored (with the exception of
   * checking for invalid children as outlined in the specification).  If the inclusion
   * fails, the &lt;fallback&gt; child of the &lt;include&gt; element is processed.
   * </p>
   * <p>
   * See the <a href="http://www.w3.org/TR/xinclude/">XInclude specification</a> for
   * more information on how XInclude is to be used.
   * </p>
   * <p>
   * This component requires the following features and properties from the
   * component manager that uses it:
   * <ul>
   *  <li>http://xml.org/sax/features/allow-dtd-events-after-endDTD</li>
   *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
   *  <li>http://apache.org/xml/properties/internal/entity-resolver</li>
   * </ul>
   * Optional property:
   * <ul>
   *  <li>http://apache.org/xml/properties/input-buffer-size</li>
   * </ul>
   * 
   * Furthermore, the <code>NamespaceContext</code> used in the pipeline is required
   * to be an instance of <code>XIncludeNamespaceSupport</code>.
   * </p>
   * <p>
   * Currently, this implementation has only partial support for the XInclude specification.
   * Specifically, it is missing support for XPointer document fragments.  Thus, only whole
   * documents can be included using this component in the pipeline.
   * </p>
   *
   * @author Peter McCracken, IBM
   * @author Michael Glavassevich, IBM
   *
   * @version $Id: XIncludeHandler.java,v 1.54 2005/06/24 01:06:07 mrglavas Exp $
   *
   * @see XIncludeNamespaceSupport
   */
  public class XIncludeHandler
      implements XMLComponent, XMLDocumentFilter, XMLDTDFilter {
  
      public final static String XINCLUDE_DEFAULT_CONFIGURATION =
          "org.apache.xerces.parsers.XIncludeParserConfiguration";
      public final static String HTTP_ACCEPT = "Accept";
      public final static String HTTP_ACCEPT_LANGUAGE = "Accept-Language";
      public final static String XPOINTER = "xpointer";
  
      public final static String XINCLUDE_NS_URI =
          "http://www.w3.org/2001/XInclude".intern();
      public final static String XINCLUDE_INCLUDE = "include".intern();
      public final static String XINCLUDE_FALLBACK = "fallback".intern();
  
      public final static String XINCLUDE_PARSE_XML = "xml".intern();
      public final static String XINCLUDE_PARSE_TEXT = "text".intern();
  
      public final static String XINCLUDE_ATTR_HREF = "href".intern();
      public final static String XINCLUDE_ATTR_PARSE = "parse".intern();
      public final static String XINCLUDE_ATTR_ENCODING = "encoding".intern();
      public final static String XINCLUDE_ATTR_ACCEPT = "accept".intern();
      public final static String XINCLUDE_ATTR_ACCEPT_LANGUAGE = "accept-language".intern();
  
      // Top Level Information Items have [included] property in infoset
      public final static String XINCLUDE_INCLUDED = "[included]".intern();
  
      /** The identifier for the Augmentation that contains the current base URI */
      public final static String CURRENT_BASE_URI = "currentBaseURI";
  
      // used for adding [base URI] attributes
      public final static String XINCLUDE_BASE = "base".intern();
      public final static QName XML_BASE_QNAME =
          new QName(
              XMLSymbols.PREFIX_XML,
              XINCLUDE_BASE,
              (XMLSymbols.PREFIX_XML + ":" + XINCLUDE_BASE).intern(),
              NamespaceContext.XML_URI);
      
      // used for adding [language] attributes
      public final static String XINCLUDE_LANG = "lang".intern();
      public final static QName XML_LANG_QNAME = 
          new QName(
              XMLSymbols.PREFIX_XML,
              XINCLUDE_LANG,
              (XMLSymbols.PREFIX_XML + ":" + XINCLUDE_LANG).intern(),
              NamespaceContext.XML_URI);
  
      public final static QName NEW_NS_ATTR_QNAME =
          new QName(
              XMLSymbols.PREFIX_XMLNS,
              "",
              XMLSymbols.PREFIX_XMLNS + ":",
              NamespaceContext.XMLNS_URI);
  
      // Processing States
      private final static int STATE_NORMAL_PROCESSING = 1;
      // we go into this state after a successful include (thus we ignore the children
      // of the include) or after a fallback
      private final static int STATE_IGNORE = 2;
      // we go into this state after a failed include.  If we don't encounter a fallback
      // before we reach the end include tag, it's a fatal error
      private final static int STATE_EXPECT_FALLBACK = 3;
  
      // recognized features and properties
      
      /** Feature identifier: validation. */
      protected static final String VALIDATION =
          Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
      
      /** Feature identifier: schema validation. */
      protected static final String SCHEMA_VALIDATION =
          Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
      
      /** Feature identifier: dynamic validation. */
      protected static final String DYNAMIC_VALIDATION = 
          Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
  
      /** 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;
      
      /** Feature identifier: fixup base URIs. */
      protected static final String XINCLUDE_FIXUP_BASE_URIS =
          Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FIXUP_BASE_URIS_FEATURE;
      
      /** Feature identifier: fixup language. */
      protected static final String XINCLUDE_FIXUP_LANGUAGE =
          Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FIXUP_LANGUAGE_FEATURE;
      
      /** Property identifier: symbol table. */
      protected static final String SYMBOL_TABLE = 
          Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
  
      /** Property identifier: error reporter. */
      protected static final String ERROR_REPORTER =
          Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
  
      /** Property identifier: entity resolver. */
      protected static final String ENTITY_RESOLVER =
          Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
  
      /** property identifier: security manager. */
      protected static final String SECURITY_MANAGER =
          Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
      
      /** property identifier: buffer size. */
      public static final String BUFFER_SIZE =
          Constants.XERCES_PROPERTY_PREFIX + Constants.BUFFER_SIZE_PROPERTY;
      
      protected static final String PARSER_SETTINGS = 
          Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
  
      /** Recognized features. */
      private static final String[] RECOGNIZED_FEATURES =
          { ALLOW_UE_AND_NOTATION_EVENTS, XINCLUDE_FIXUP_BASE_URIS, XINCLUDE_FIXUP_LANGUAGE };
  
      /** Feature defaults. */
      private static final Boolean[] FEATURE_DEFAULTS = { Boolean.TRUE, Boolean.TRUE, Boolean.TRUE };
  
      /** Recognized properties. */
      private static final String[] RECOGNIZED_PROPERTIES =
          { ERROR_REPORTER, ENTITY_RESOLVER, SECURITY_MANAGER, BUFFER_SIZE };
  
      /** Property defaults. */
      private static final Object[] PROPERTY_DEFAULTS = { null, null, null, new Integer(XMLEntityManager.DEFAULT_BUFFER_SIZE) };
  
      // instance variables
  
      // for XMLDocumentFilter
      protected XMLDocumentHandler fDocumentHandler;
      protected XMLDocumentSource fDocumentSource;
  
      // for XMLDTDFilter
      protected XMLDTDHandler fDTDHandler;
      protected XMLDTDSource fDTDSource;
  
      // for XIncludeHandler
      protected XIncludeHandler fParentXIncludeHandler;
      
      // for buffer size in XIncludeTextReader
      protected int fBufferSize = XMLEntityManager.DEFAULT_BUFFER_SIZE;
  
      // It "feels wrong" to store this value here.  However,
      // calculating it can be time consuming, so we cache it.
      // It's never going to change in the lifetime of this XIncludeHandler
      protected String fParentRelativeURI;
  
      // we cache the child parser configuration, so we don't have to re-create
      // the objects when the parser is re-used
      protected XMLParserConfiguration fChildConfig;
  
      // The cached child parser configuration, may contain a
      // XInclude or XPointer Handler.  Cache both these
      protected XMLParserConfiguration fXIncludeChildConfig;
      protected XMLParserConfiguration fXPointerChildConfig;
      
      // The XPointerProcessor
      protected XPointerProcessor fXPtrProcessor = null;
  
      protected XMLLocator fDocLocation;
      protected XIncludeMessageFormatter fXIncludeMessageFormatter = new XIncludeMessageFormatter();
      protected XIncludeNamespaceSupport fNamespaceContext;
      protected SymbolTable fSymbolTable;
      protected XMLErrorReporter fErrorReporter;
      protected XMLEntityResolver fEntityResolver;
      protected SecurityManager fSecurityManager;
      
      // these are needed for text include processing
      protected XIncludeTextReader fXInclude10TextReader;
      protected XIncludeTextReader fXInclude11TextReader;
  
      // these are needed for XML Base processing
      protected XMLResourceIdentifier fCurrentBaseURI;
      protected IntStack fBaseURIScope;
      protected Stack fBaseURI;
      protected Stack fLiteralSystemID;
      protected Stack fExpandedSystemID;
      
      // these are needed for Language Fixup
      protected IntStack fLanguageScope;
      protected Stack fLanguageStack;
      protected String fCurrentLanguage;
  
      // used for passing features on to child XIncludeHandler objects
      protected ParserConfigurationSettings fSettings;
  
      // The current element depth.  We start at depth 0 (before we've reached any elements).
      // The first element is at depth 1.
      private int fDepth;
      
      // The current element depth of the result infoset.
      private int fResultDepth;
  
      // 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 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 boolean[] fSawFallback = new boolean[INITIAL_SIZE];
  
      // The state of the processor at each given depth.
      private int[] fState = new int[INITIAL_SIZE];
  
      // buffering the necessary DTD events
      private ArrayList fNotations;
      private ArrayList fUnparsedEntities;
      
      // flags which control whether base URI or language fixup is performed.
      private boolean fFixupBaseURIs = true;
      private boolean fFixupLanguage = true;
  
      // for SAX compatibility.
      // Has the value of the ALLOW_UE_AND_NOTATION_EVENTS feature
      private boolean fSendUEAndNotationEvents;
  
      // track the version of the document being parsed
      private boolean fIsXML11;
  
      // track whether a DTD is being parsed
      private boolean fInDTD;
      
      // track whether the root element of the result infoset has been processed
      private boolean fSeenRootElement;
      
      // track whether the child config needs its features refreshed
      private boolean fNeedCopyFeatures = true;
  
      // Constructors
  
      public XIncludeHandler() {
          fDepth = 0;
  
          fSawFallback[fDepth] = false;
          fSawInclude[fDepth] = false;
          fState[fDepth] = STATE_NORMAL_PROCESSING;
          fNotations = new ArrayList();
          fUnparsedEntities = new ArrayList();
  
          fBaseURIScope = new IntStack();
          fBaseURI = new Stack();
          fLiteralSystemID = new Stack();
          fExpandedSystemID = new Stack();
          fCurrentBaseURI = new XMLResourceIdentifierImpl();
          
          fLanguageScope = new IntStack();
          fLanguageStack = new Stack();
          fCurrentLanguage = null;
      }
  
      // XMLComponent methods
  
      public void reset(XMLComponentManager componentManager)
          throws XNIException {
          fNamespaceContext = null;
          fDepth = 0;
          fResultDepth = isRootDocument() ? 0 : fParentXIncludeHandler.getResultDepth();
          fNotations.clear();
          fUnparsedEntities.clear();
          fParentRelativeURI = null;
          fIsXML11 = false;
          fInDTD = false;
          fSeenRootElement = false;
  
          fBaseURIScope.clear();
          fBaseURI.clear();
          fLiteralSystemID.clear();
          fExpandedSystemID.clear();
          fLanguageScope.clear();
          fLanguageStack.clear();
  
          // REVISIT: Find a better method for maintaining
          // the state of the XInclude processor. These arrays
          // can potentially grow quite large. Cleaning them
          // out on reset may be very time consuming. -- mrglavas
          //
          // clear the previous settings from the arrays
          for (int i = 0; i < fState.length; ++i) {
              fState[i] = STATE_NORMAL_PROCESSING;
          }
          for (int i = 0; i < fSawFallback.length; ++i) {
              fSawFallback[i] = false;
          }
          for (int i = 0; i < fSawInclude.length; ++i) {
              fSawInclude[i] = false;
          }
          
          try {
              if (!componentManager.getFeature(PARSER_SETTINGS)) {
                  // if parser settings have not changed return.
                  return;
              }
          } 
          catch (XMLConfigurationException e) {}
          
          // parser settings changed. Need to refresh features on child config.
          fNeedCopyFeatures = true;
  
          try {
              fSendUEAndNotationEvents =
                  componentManager.getFeature(ALLOW_UE_AND_NOTATION_EVENTS);
              if (fChildConfig != null) {
                  fChildConfig.setFeature(
                      ALLOW_UE_AND_NOTATION_EVENTS,
                      fSendUEAndNotationEvents);
              }
          }
          catch (XMLConfigurationException e) {
          }
          
          try {
              fFixupBaseURIs =
                  componentManager.getFeature(XINCLUDE_FIXUP_BASE_URIS);
              if (fChildConfig != null) {
                  fChildConfig.setFeature(
                      XINCLUDE_FIXUP_BASE_URIS,
                      fFixupBaseURIs);
              }
          }
          catch (XMLConfigurationException e) {
              fFixupBaseURIs = true;
          }
          
          try {
              fFixupLanguage =
                  componentManager.getFeature(XINCLUDE_FIXUP_LANGUAGE);
              if (fChildConfig != null) {
                  fChildConfig.setFeature(
                      XINCLUDE_FIXUP_LANGUAGE,
                      fFixupLanguage);
              }
          }
          catch (XMLConfigurationException e) {
              fFixupLanguage = true;
          }
          
          // Get symbol table.
          try {
              SymbolTable value =
                  (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
              if (value != null) {
                  fSymbolTable = value;
                  if (fChildConfig != null) {
                      fChildConfig.setProperty(SYMBOL_TABLE, value);
                  }
              }
          }
          catch (XMLConfigurationException e) {
              fSymbolTable = null;
          }
  
          // Get error reporter.
          try {
              XMLErrorReporter value =
                  (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER);
              if (value != null) {
                  setErrorReporter(value);
                  if (fChildConfig != null) {
                      fChildConfig.setProperty(ERROR_REPORTER, value);
                  }
              }
          }
          catch (XMLConfigurationException e) {
              fErrorReporter = null;
          }
  
          // Get entity resolver.
          try {
              XMLEntityResolver value =
                  (XMLEntityResolver)componentManager.getProperty(
                      ENTITY_RESOLVER);
  
              if (value != null) {
                  fEntityResolver = value;
                  if (fChildConfig != null) {
                      fChildConfig.setProperty(ENTITY_RESOLVER, value);
                  }
              }
          }
          catch (XMLConfigurationException e) {
              fEntityResolver = null;
          }
  
          // Get security manager.
          try {
              SecurityManager value =
                  (SecurityManager)componentManager.getProperty(
                      SECURITY_MANAGER);
  
              if (value != null) {
                  fSecurityManager = value;
                  if (fChildConfig != null) {
                      fChildConfig.setProperty(SECURITY_MANAGER, value);
                  }
              }
          }
          catch (XMLConfigurationException e) {
              fSecurityManager = null;
          }
          
          // Get buffer size.
          try {
              Integer value =
                  (Integer)componentManager.getProperty(
                      BUFFER_SIZE);
  
              if (value != null && value.intValue() > 0) {
                  fBufferSize = value.intValue();
                  if (fChildConfig != null) {
                      fChildConfig.setProperty(BUFFER_SIZE, value);
                  }
              }
              else {
              	fBufferSize = ((Integer)getPropertyDefault(BUFFER_SIZE)).intValue();
              }
          }
          catch (XMLConfigurationException e) {
          	fBufferSize = ((Integer)getPropertyDefault(BUFFER_SIZE)).intValue();
          }
          
          // Reset XML 1.0 text reader.
          if (fXInclude10TextReader != null) {
          	fXInclude10TextReader.setBufferSize(fBufferSize);
          }
          // Reset XML 1.1 text reader.
          if (fXInclude11TextReader != null) {
              fXInclude11TextReader.setBufferSize(fBufferSize);   
          }
  
          fSettings = new ParserConfigurationSettings();
          copyFeatures(componentManager, fSettings);
          
          // we don't want a schema validator on the new pipeline,
          // so if it was enabled, we set the feature to false as 
          // well as other validation features.
          try {
              if (componentManager.getFeature(SCHEMA_VALIDATION)) {
                  fSettings.setFeature(SCHEMA_VALIDATION, false);
                  fSettings.setFeature(DYNAMIC_VALIDATION, false);
                  fSettings.setFeature(VALIDATION, false);
              }
          }
          catch (XMLConfigurationException e) {}
          
          // Don't reset fChildConfig -- we don't want it to share the same components.
          // It will be reset when it is actually used to parse something.
      } // reset(XMLComponentManager)
  
      /**
       * Returns a list of feature identifiers that are recognized by
       * this component. This method may return null if no features
       * are recognized by this component.
       */
      public String[] getRecognizedFeatures() {
          return RECOGNIZED_FEATURES;
      } // getRecognizedFeatures():String[]
  
      /**
       * Sets the state of a feature. This method is called by the component
       * manager any time after reset when a feature changes state.
       * <p>
       * <strong>Note:</strong> Components should silently ignore features
       * that do not affect the operation of the component.
       *
       * @param featureId The feature identifier.
       * @param state     The state of the feature.
       *
       * @throws SAXNotRecognizedException The component should not throw
       *                                   this exception.
       * @throws SAXNotSupportedException The component should not throw
       *                                  this exception.
       */
      public void setFeature(String featureId, boolean state)
          throws XMLConfigurationException {
          if (featureId.equals(ALLOW_UE_AND_NOTATION_EVENTS)) {
              fSendUEAndNotationEvents = state;
          }
          if (fSettings != null) {
              fNeedCopyFeatures = true;
              fSettings.setFeature(featureId, state);
          }
      } // setFeature(String,boolean)
  
      /**
       * Returns a list of property identifiers that are recognized by
       * this component. This method may return null if no properties
       * are recognized by this component.
       */
      public String[] getRecognizedProperties() {
          return RECOGNIZED_PROPERTIES;
      } // getRecognizedProperties():String[]
  
      /**
       * Sets the value of a property. This method is called by the component
       * manager any time after reset when a property changes value.
       * <p>
       * <strong>Note:</strong> Components should silently ignore properties
       * that do not affect the operation of the component.
       *
       * @param propertyId The property identifier.
       * @param value      The value of the property.
       *
       * @throws SAXNotRecognizedException The component should not throw
       *                                   this exception.
       * @throws SAXNotSupportedException The component should not throw
       *                                  this exception.
       */
      public void setProperty(String propertyId, Object value)
          throws XMLConfigurationException {
          if (propertyId.equals(SYMBOL_TABLE)) {
              fSymbolTable = (SymbolTable)value;
              if (fChildConfig != null) {
                  fChildConfig.setProperty(propertyId, value);
              }
              return;
          }
          if (propertyId.equals(ERROR_REPORTER)) {
              setErrorReporter((XMLErrorReporter)value);
              if (fChildConfig != null) {
                  fChildConfig.setProperty(propertyId, value);
              }
              return;
          }
          if (propertyId.equals(ENTITY_RESOLVER)) {
              fEntityResolver = (XMLEntityResolver)value;
              if (fChildConfig != null) {
                  fChildConfig.setProperty(propertyId, value);
              }
              return;
          }
          if (propertyId.equals(SECURITY_MANAGER)) {
              fSecurityManager = (SecurityManager)value;
              if (fChildConfig != null) {
                  fChildConfig.setProperty(propertyId, value);
              }
              return;
          }
          if (propertyId.equals(BUFFER_SIZE)) {
              Integer bufferSize = (Integer) value;
              if (fChildConfig != null) {
                  fChildConfig.setProperty(propertyId, value);
              }
              if (bufferSize != null && bufferSize.intValue() > 0) {
                  fBufferSize = bufferSize.intValue();
                  // Reset XML 1.0 text reader.
                  if (fXInclude10TextReader != null) {
                      fXInclude10TextReader.setBufferSize(fBufferSize);
                  }
                  // Reset XML 1.1 text reader.
                  if (fXInclude11TextReader != null) {
                      fXInclude11TextReader.setBufferSize(fBufferSize);
                  }
              }
              return;
          }
  
      } // setProperty(String,Object)
  
      /**
       * Returns the default state for a feature, or null if this
       * component does not want to report a default value for this
       * feature.
       *
       * @param featureId The feature identifier.
       *
       * @since Xerces 2.2.0
       */
      public Boolean getFeatureDefault(String featureId) {
          for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
              if (RECOGNIZED_FEATURES[i].equals(featureId)) {
                  return FEATURE_DEFAULTS[i];
              }
          }
          return null;
      } // getFeatureDefault(String):Boolean
  
      /**
       * Returns the default state for a property, or null if this
       * component does not want to report a default value for this
       * property.
       *
       * @param propertyId The property identifier.
       *
       * @since Xerces 2.2.0
       */
      public Object getPropertyDefault(String propertyId) {
          for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
              if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
                  return PROPERTY_DEFAULTS[i];
              }
          }
          return null;
      } // getPropertyDefault(String):Object
  
      public void setDocumentHandler(XMLDocumentHandler handler) {
          fDocumentHandler = handler;
      }
  
      public XMLDocumentHandler getDocumentHandler() {
          return fDocumentHandler;
      }
  
      // XMLDocumentHandler methods
  
      /**
       * Event sent at the start of the document.
       *
       * A fatal error will occur here, if it is detected that this document has been processed
       * before.
       *
       * This event is only passed on to the document handler if this is the root document.
       */
      public void startDocument(
          XMLLocator locator,
          String encoding,
          NamespaceContext namespaceContext,
          Augmentations augs)
          throws XNIException {
  
          // we do this to ensure that the proper location is reported in errors
          // otherwise, the locator from the root document would always be used
          fErrorReporter.setDocumentLocator(locator);
  
          if (!isRootDocument()
              && fParentXIncludeHandler.searchForRecursiveIncludes(locator)) {
              reportFatalError(
                  "RecursiveInclude",
                  new Object[] { locator.getExpandedSystemId()});
          }
  
          if (!(namespaceContext instanceof XIncludeNamespaceSupport)) {
              reportFatalError("IncompatibleNamespaceContext");
          }
          fNamespaceContext = (XIncludeNamespaceSupport)namespaceContext;
          fDocLocation = locator;
  
          // initialize the current base URI
          fCurrentBaseURI.setBaseSystemId(locator.getBaseSystemId());
          fCurrentBaseURI.setExpandedSystemId(locator.getExpandedSystemId());
          fCurrentBaseURI.setLiteralSystemId(locator.getLiteralSystemId());
          saveBaseURI();
          if (augs == null) {
              augs = new AugmentationsImpl();
          }
          augs.putItem(CURRENT_BASE_URI, fCurrentBaseURI);
          
          // initialize the current language
          fCurrentLanguage = XMLSymbols.EMPTY_STRING;
          saveLanguage(fCurrentLanguage);
  
          if (isRootDocument() && fDocumentHandler != null) {
              fDocumentHandler.startDocument(
                  locator,
                  encoding,
                  namespaceContext,
                  augs);
          }
      }
  
      public void xmlDecl(
          String version,
          String encoding,
          String standalone,
          Augmentations augs)
          throws XNIException {
          fIsXML11 = "1.1".equals(version);
          if (isRootDocument() && fDocumentHandler != null) {
              fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
          }
      }
  
      public void doctypeDecl(
          String rootElement,
          String publicId,
          String systemId,
          Augmentations augs)
          throws XNIException {
          if (isRootDocument() && fDocumentHandler != null) {
              fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
          }
      }
  
      public void comment(XMLString text, Augmentations augs)
          throws XNIException {
          if (!fInDTD) {
              if (fDocumentHandler != null
                  && getState() == STATE_NORMAL_PROCESSING) {
                  fDepth++;
                  augs = modifyAugmentations(augs);
                  fDocumentHandler.comment(text, augs);
                  fDepth--;
              }
          }
          else if (fDTDHandler != null) {
              fDTDHandler.comment(text, augs);
          }
      }
  
      public void processingInstruction(
          String target,
          XMLString data,
          Augmentations augs)
          throws XNIException {
          if (!fInDTD) {
              if (fDocumentHandler != null
                  && getState() == STATE_NORMAL_PROCESSING) {
                  // we need to change the depth like this so that modifyAugmentations() works
                  fDepth++;
                  augs = modifyAugmentations(augs);
                  fDocumentHandler.processingInstruction(target, data, augs);
                  fDepth--;
              }
          }
          else if (fDTDHandler != null) {
              fDTDHandler.processingInstruction(target, data, augs);
          }
      }
  
      public void startElement(
          QName element,
          XMLAttributes attributes,
          Augmentations augs)
          throws XNIException {
          fDepth++;
          int lastState = getState(fDepth - 1);
          // If the last two states were fallback then this must be a descendant of an include
          // child which isn't a fallback. The specification says we should ignore such elements
          // and their children.
          if (lastState == STATE_EXPECT_FALLBACK && getState(fDepth - 2) == STATE_EXPECT_FALLBACK) {
              setState(STATE_IGNORE);
          }
          else {
              setState(lastState);
          }
  
          // we process the xml:base and xml:lang attributes regardless
          // of what type of element it is.
          processXMLBaseAttributes(attributes);
          if (fFixupLanguage) {
              processXMLLangAttributes(attributes);
          }
  
          if (isIncludeElement(element)) {
              boolean success = this.handleIncludeElement(attributes);
              if (success) {
                  setState(STATE_IGNORE);
              }
              else {
                  setState(STATE_EXPECT_FALLBACK);
              }
          }
          else if (isFallbackElement(element)) {
              this.handleFallbackElement();
          }
          else if (hasXIncludeNamespace(element)) {
              if (getSawInclude(fDepth - 1)) {
                  reportFatalError(
                      "IncludeChild",
                      new Object[] { element.rawname });
              }
              if (getSawFallback(fDepth - 1)) {
                  reportFatalError(
                      "FallbackChild",
                      new Object[] { element.rawname });
              }
              if (getState() == STATE_NORMAL_PROCESSING) {
                  if (fResultDepth++ == 0) {
                      checkMultipleRootElements();
                  }
                  if (fDocumentHandler != null) {
                      augs = modifyAugmentations(augs);
                      attributes = processAttributes(attributes);
                      fDocumentHandler.startElement(element, attributes, augs);
                  }            
              }
          }
          else if (getState() == STATE_NORMAL_PROCESSING) {
              if (fResultDepth++ == 0) {
                  checkMultipleRootElements();
              }
              if (fDocumentHandler != null) {
                  augs = modifyAugmentations(augs);
                  attributes = processAttributes(attributes);
                  fDocumentHandler.startElement(element, attributes, augs);
              }            
          }
      }
  
      public void emptyElement(
          QName element,
          XMLAttributes attributes,
          Augmentations augs)
          throws XNIException {
          fDepth++;
          int lastState = getState(fDepth - 1);
          // If the last two states were fallback then this must be a descendant of an include
          // child which isn't a fallback. The specification says we should ignore such elements
          // and their children.
          if (lastState == STATE_EXPECT_FALLBACK && getState(fDepth - 2) == STATE_EXPECT_FALLBACK) {
              setState(STATE_IGNORE);
          }
          else {
              setState(lastState);
          }
  
          // we process the xml:base and xml:lang attributes regardless
          // of what type of element it is.
          processXMLBaseAttributes(attributes);
          if (fFixupLanguage) {
              processXMLLangAttributes(attributes);
          }
  
          if (isIncludeElement(element)) {
              boolean success = this.handleIncludeElement(attributes);
              if (success) {
                  setState(STATE_IGNORE);
              }
              else {
                  reportFatalError("NoFallback");
              }
          }
          else if (isFallbackElement(element)) {
              this.handleFallbackElement();
          }
          else if (hasXIncludeNamespace(element)) {
              if (getSawInclude(fDepth - 1)) {
                  reportFatalError(
                      "IncludeChild",
                      new Object[] { element.rawname });
              }
              if (getSawFallback(fDepth - 1)) {
                  reportFatalError(
                      "FallbackChild",
                      new Object[] { element.rawname });
              }
              if (getState() == STATE_NORMAL_PROCESSING) {
                  if (fResultDepth == 0) {
                      checkMultipleRootElements();
                  }
                  if (fDocumentHandler != null) {
                      augs = modifyAugmentations(augs);
                      attributes = processAttributes(attributes);
                      fDocumentHandler.emptyElement(element, attributes, augs);
                  }
              }
          }
          else if (getState() == STATE_NORMAL_PROCESSING) {
              if (fResultDepth == 0) {
                  checkMultipleRootElements();
              }
              if (fDocumentHandler != null) {
                  augs = modifyAugmentations(augs);
                  attributes = processAttributes(attributes);
                  fDocumentHandler.emptyElement(element, attributes, augs);
              }
          }
          // reset the out of scope stack elements
          setSawFallback(fDepth + 1, false);
          setSawInclude(fDepth, false);
  
          // check if an xml:base has gone out of scope
          if (fBaseURIScope.size() > 0 && fDepth == fBaseURIScope.peek()) {
              // pop the values from the stack
              restoreBaseURI();
          }
          fDepth--;
      }
  
      public void endElement(QName element, Augmentations augs)
          throws XNIException {
  
          if (isIncludeElement(element)) {
              // if we're ending an include element, and we were expecting a fallback
              // we check to see if the children of this include element contained a fallback
              if (getState() == STATE_EXPECT_FALLBACK
                  && !getSawFallback(fDepth + 1)) {
                  reportFatalError("NoFallback");
              }
          }
          if (isFallbackElement(element)) {
              // the state would have been set to normal processing if we were expecting the fallback element
              // now that we're done processing it, we should ignore all the other children of the include element
              if (getState() == STATE_NORMAL_PROCESSING) {
                  setState(STATE_IGNORE);
              }
          }
          else if (getState() == STATE_NORMAL_PROCESSING) {
              --fResultDepth;
              if (fDocumentHandler != null) {
                  fDocumentHandler.endElement(element, augs);
              }
          }
  
          // reset the out of scope stack elements
          setSawFallback(fDepth + 1, false);
          setSawInclude(fDepth, false);
  
          // check if an xml:base has gone out of scope
          if (fBaseURIScope.size() > 0 && fDepth == fBaseURIScope.peek()) {
              // pop the values from the stack
              restoreBaseURI();
          }
          
          // check if an xml:lang has gone out of scope
          if (fLanguageScope.size() > 0 && fDepth == fLanguageScope.peek()) {
              // pop the language from the stack
              fCurrentLanguage = restoreLanguage();
          }
          
          fDepth--;
      }
  
      public void startGeneralEntity(
          String name,
          XMLResourceIdentifier resId,
          String encoding,
          Augmentations augs)
          throws XNIException {
          if (getState() == STATE_NORMAL_PROCESSING) {
              if (fResultDepth == 0) {
                  if (augs != null && Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
                      reportFatalError("UnexpandedEntityReferenceIllegal");
                  }
              }
              else if (fDocumentHandler != null) {
                  fDocumentHandler.startGeneralEntity(name, resId, encoding, augs);
              }
          }
      }
  
      public void textDecl(String version, String encoding, Augmentations augs)
          throws XNIException {
          if (fDocumentHandler != null
              && getState() == STATE_NORMAL_PROCESSING) {
              fDocumentHandler.textDecl(version, encoding, augs);
          }
      }
  
      public void endGeneralEntity(String name, Augmentations augs)
          throws XNIException {
          if (fDocumentHandler != null
              && getState() == STATE_NORMAL_PROCESSING
              && fResultDepth != 0) {
              fDocumentHandler.endGeneralEntity(name, augs);
          }
      }
  
      public void characters(XMLString text, Augmentations augs)
          throws XNIException {
          if (getState() == STATE_NORMAL_PROCESSING) {
              if (fResultDepth == 0) {
                  checkWhitespace(text);
              }
              else if (fDocumentHandler != null) {
                  // we need to change the depth like this so that modifyAugmentations() works
                  fDepth++;
                  augs = modifyAugmentations(augs);
                  fDocumentHandler.characters(text, augs);
                  fDepth--;
              }
          }
      }
  
      public void ignorableWhitespace(XMLString text, Augmentations augs)
          throws XNIException {
          if (fDocumentHandler != null
              && getState() == STATE_NORMAL_PROCESSING
              && fResultDepth != 0) {
              fDocumentHandler.ignorableWhitespace(text, augs);
          }
      }
  
      public void startCDATA(Augmentations augs) throws XNIException {
          if (fDocumentHandler != null
              && getState() == STATE_NORMAL_PROCESSING
              && fResultDepth != 0) {
              fDocumentHandler.startCDATA(augs);
          }
      }
  
      public void endCDATA(Augmentations augs) throws XNIException {
          if (fDocumentHandler != null
              && getState() == STATE_NORMAL_PROCESSING
              && fResultDepth != 0) {
              fDocumentHandler.endCDATA(augs);
          }
      }
  
      public void endDocument(Augmentations augs) throws XNIException {
          if (isRootDocument()) {
              if (!fSeenRootElement) {
                  reportFatalError("RootElementRequired");
              }
              if (fDocumentHandler != null) {
                  fDocumentHandler.endDocument(augs);
              }
          }
      }
  
      public void setDocumentSource(XMLDocumentSource source) {
          fDocumentSource = source;
      }
  
      public XMLDocumentSource getDocumentSource() {
          return fDocumentSource;
      }
  
      // DTDHandler methods
      // We are only interested in the notation and unparsed entity declarations,
      // the rest we just pass on
  
      /* (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);
          }
          fInDTD = false;
      }
  
      /* (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 {
          fInDTD = true;
          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, fXIncludeMessageFormatter);
              // this ensures the proper location is displayed in error messages
              if (fDocLocation != null) {
                  fErrorReporter.setDocumentLocator(fDocLocation);
              }
          }
      }
  
      protected void handleFallbackElement() {
          if (!getSawInclude(fDepth - 1)) {
              if (getState() == STATE_IGNORE) {
                  return;
              }
              reportFatalError("FallbackParent");
          }
          
          setSawInclude(fDepth, false);
          fNamespaceContext.setContextInvalid();
  
          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 boolean handleIncludeElement(XMLAttributes attributes)
          throws XNIException {
          if (getSawInclude(fDepth - 1)) {
              reportFatalError("IncludeChild", new Object[] { XINCLUDE_INCLUDE });
          }
          if (getState() == STATE_IGNORE) {
              return true;
          }
          setSawInclude(fDepth, true);
          fNamespaceContext.setContextInvalid();
  
          // 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
          
          String href = attributes.getValue(XINCLUDE_ATTR_HREF);
          String parse = attributes.getValue(XINCLUDE_ATTR_PARSE);
          String xpointer =  attributes.getValue(XPOINTER);
          String accept = attributes.getValue(XINCLUDE_ATTR_ACCEPT);
          String acceptLanguage = attributes.getValue(XINCLUDE_ATTR_ACCEPT_LANGUAGE);
          
          if (parse == null) {
              parse = XINCLUDE_PARSE_XML;
          }
          if (href == null) {
              href = XMLSymbols.EMPTY_STRING;
          }
          if (href.length() == 0 && XINCLUDE_PARSE_XML.equals(parse)) {
              if (xpointer == null) {
                  reportFatalError("XpointerMissing");
              }
              else {
                  // When parse="xml" and an xpointer is specified treat 
                  // all absences of the href attribute as a resource error.
                  Locale locale = (fErrorReporter != null) ? fErrorReporter.getLocale() : null;
                  String reason = fXIncludeMessageFormatter.formatMessage(locale, "XPointerStreamability", null);
                  reportResourceError("XMLResourceError", new Object[] { href, reason });
                  return false;
              }
          }
  
          URI hrefURI = null;
          
          // Check whether href is correct and perform escaping as per section 4.1.1 of the XInclude spec.
          // Report fatal error if the href value contains a fragment identifier or if the value after
          // escaping is a syntactically invalid URI or IRI.
          try {
              hrefURI = new URI(href, true);
              if (hrefURI.getFragment() != null) {
                  reportFatalError("HrefFragmentIdentifierIllegal", new Object[] {href});
              }
          }
          catch (URI.MalformedURIException exc) {
  