content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
   */
  
  /*
   * Copyright 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 jaxp.sun.org.apache.xerces.internal.impl;
  
  import java.io.IOException;
  import jaxp.sun.org.apache.xerces.internal.xni.XMLString;
  import jaxp.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidatorFilter;
  import jaxp.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  import jaxp.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
  import jaxp.sun.org.apache.xerces.internal.util.XMLSymbols;
  import jaxp.sun.org.apache.xerces.internal.xni.NamespaceContext;
  import jaxp.sun.org.apache.xerces.internal.xni.QName;
  import jaxp.sun.org.apache.xerces.internal.xni.XNIException;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  import jaxp.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  
  import jaxp.sun.org.apache.xerces.internal.util.NamespaceSupport;
  
  import jaxp.xml.stream.events.XMLEvent;
  
  /**
   * This class adds the functionality of namespace processing.
   *
   * This class has been modified as per the new design which is more suited to
   * efficiently build pull parser. Lot of improvements have been done and
   * the code has been added to support stax functionality/features.
   *
   *
   * This class scans an XML document, checks if document has a DTD, and if
   * DTD is not found the scanner will remove the DTD Validator from the pipeline and perform
   * namespace binding.
   *
   *
   * @author Neeraj Bajaj, Sun Microsystems
   * @author Venugopal Rao K, Sun Microsystems
   * @author Elena Litani, IBM
   * @version $Id: XMLNSDocumentScannerImpl.java,v 1.11 2010-11-01 04:39:41 joehw Exp $
   */
  public class XMLNSDocumentScannerImpl
          extends XMLDocumentScannerImpl {
  
      /**
       * If is true, the dtd validator is no longer in the pipeline
       * and the scanner should bind namespaces
       */
      protected boolean fBindNamespaces;
  
      /** If validating parser, make sure we report an error in the
       *   scanner if DTD grammar is missing.*/
      protected boolean fPerformValidation;
  
  
      /** Default value of this feature is false, when in Stax mode this should be true */
      protected boolean fNotAddNSDeclAsAttribute = false;
  
      /** DTD validator */
       private XMLDTDValidatorFilter fDTDValidator;
  
       /** xmlns, default Namespace, declared */
       private boolean fXmlnsDeclared = false;
  
      /** Resets the fields of this scanner.
       */
      public void reset(PropertyManager propertyManager) {
          setPropertyManager(propertyManager);
          super.reset(propertyManager);
          fBindNamespaces = false;
          fNotAddNSDeclAsAttribute = !((Boolean)propertyManager.getProperty(Constants.ADD_NAMESPACE_DECL_AS_ATTRIBUTE)).booleanValue();
      }
  
      public void reset(XMLComponentManager componentManager)
      throws XMLConfigurationException {
          super.reset(componentManager);
          fNotAddNSDeclAsAttribute = false ;
          fPerformValidation = false;
          fBindNamespaces = false;
      }
  
      /** return the next state on the input
       *
       * @return int
       */
  
      public int next() throws IOException, XNIException {
          //since namespace context should still be valid when the parser is at the end element state therefore
          //we pop the context only when next() has been called after the end element state was encountered. - nb.
  
          if((fScannerLastState == XMLEvent.END_ELEMENT) && fBindNamespaces){
              fScannerLastState = -1;
              fNamespaceContext.popContext();
          }
  
          return fScannerLastState = super.next();
      }
  
      /**
       * The scanner is responsible for removing DTD validator
       * from the pipeline if it is not needed.
       *
       * @param previous The filter component before DTDValidator
       * @param dtdValidator
       *                 The DTDValidator
       * @param next     The documentHandler after the DTDValidator
       */
      public void setDTDValidator(XMLDTDValidatorFilter dtd){
          fDTDValidator = dtd;
      }
  
  
  
      /**
       * Scans a start element. This method will handle the binding of
       * namespace information and notifying the handler of the start
       * of the element.
       * <p>
       * <pre>
       * [44] EmptyElemTag ::= '&lt;' Name (S Attribute)* S? '/>'
       * [40] STag ::= '&lt;' Name (S Attribute)* S? '>'
       * </pre>
       * <p>
       * <strong>Note:</strong> This method assumes that the leading
       * '&lt;' character has been consumed.
       * <p>
       * <strong>Note:</strong> This method uses the fElementQName and
       * fAttributes variables. The contents of these variables will be
       * destroyed. The caller should copy important information out of
       * these variables before calling this method.
       *
       * @return True if element is empty. (i.e. It matches
       *          production [44].
       */
      protected boolean scanStartElement()
      throws IOException, XNIException {
  
          if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanStartElement()");
          //when skipping is true and no more elements should be added
          if(fSkip && !fAdd){
              //get the stored element -- if everything goes right this should match the
              //token in the buffer
  
              QName name = fElementStack.getNext();
  
              if(DEBUG_SKIP_ALGORITHM){
                  System.out.println("Trying to skip String = " + name.rawname);
              }
  
              //Be conservative -- if skipping fails -- stop.
              fSkip = fEntityScanner.skipString(name.rawname); // skipQElement(name);
  
              if(fSkip){
                  if(DEBUG_SKIP_ALGORITHM){
                      System.out.println("Element SUCESSFULLY skipped = " + name.rawname);
                  }
                  fElementStack.push();
                  fElementQName = name;
              }else{
                  //if skipping fails reposition the stack or fallback to normal way of processing
                  fElementStack.reposition();
                  if(DEBUG_SKIP_ALGORITHM){
                      System.out.println("Element was NOT skipped, REPOSITIONING stack" );
                  }
              }
          }
  
          //we are still at the stage of adding elements
          //the elements were not matched or
          //fSkip is not set to true
          if(!fSkip || fAdd){
              //get the next element from the stack
              fElementQName = fElementStack.nextElement();
              // There are two variables,fNamespaces and fBindNamespaces
              //StAX uses XMLNSDocumentScannerImpl so this distinction needs to be maintained
              if (fNamespaces) {
                  fEntityScanner.scanQName(fElementQName);
              } else {
                  String name = fEntityScanner.scanName();
                  fElementQName.setValues(null, name, name, null);
              }
  
              if(DEBUG)System.out.println("Element scanned in start element is " + fElementQName.toString());
              if(DEBUG_SKIP_ALGORITHM){
                  if(fAdd){
                      System.out.println("Elements are being ADDED -- elemet added is = " + fElementQName.rawname + " at count = " + fElementStack.fCount);
                  }
              }
  
          }
  
          //when the elements are being added , we need to check if we are set for skipping the elements
          if(fAdd){
              //this sets the value of fAdd variable
              fElementStack.matchElement(fElementQName);
          }
  
          //xxx: We dont need another pointer, fCurrentElement, we can use fElementQName
          fCurrentElement = fElementQName;
  
          String rawname = fElementQName.rawname;
          if (fBindNamespaces) {
              fNamespaceContext.pushContext();
              if (fScannerState == SCANNER_STATE_ROOT_ELEMENT) {
                  if (fPerformValidation) {
                      fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                              "MSG_GRAMMAR_NOT_FOUND",
                              new Object[]{ rawname},
                              XMLErrorReporter.SEVERITY_ERROR);
  
                              if (fDoctypeName == null || !fDoctypeName.equals(rawname)) {
                                  fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
                                          "RootElementTypeMustMatchDoctypedecl",
                                          new Object[]{fDoctypeName, rawname},
                                          XMLErrorReporter.SEVERITY_ERROR);
                              }
                  }
              }
          }
  
  
          fEmptyElement = false;
          fAttributes.removeAllAttributes();
  
          if(!seekCloseOfStartTag()){
              fReadingAttributes = true;
              fAttributeCacheUsedCount =0;
              fStringBufferIndex =0;
              fAddDefaultAttr = true;
              fXmlnsDeclared = false;
  
              do {
                  scanAttribute(fAttributes);
                  if (fSecurityManager != null && (!fSecurityManager.isNoLimit(fElementAttributeLimit)) &&
                          fAttributes.getLength() > fElementAttributeLimit){
                      fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                   "ElementAttributeLimit",
                                                   new Object[]{rawname, fElementAttributeLimit },
                                                   XMLErrorReporter.SEVERITY_FATAL_ERROR );
                  }
  
              } while (!seekCloseOfStartTag());
              fReadingAttributes=false;
          }
  
          if (fBindNamespaces) {
              // REVISIT: is it required? forbit xmlns prefix for element
              if (fElementQName.prefix == XMLSymbols.PREFIX_XMLNS) {
                  fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                          "ElementXMLNSPrefix",
                          new Object[]{fElementQName.rawname},
                          XMLErrorReporter.SEVERITY_FATAL_ERROR);
              }
  
              // bind the element
              String prefix = fElementQName.prefix != null
                      ? fElementQName.prefix : XMLSymbols.EMPTY_STRING;
              // assign uri to the element
              fElementQName.uri = fNamespaceContext.getURI(prefix);
              // make sure that object in the element stack is updated as well
              fCurrentElement.uri = fElementQName.uri;
  
              if (fElementQName.prefix == null && fElementQName.uri != null) {
                  fElementQName.prefix = XMLSymbols.EMPTY_STRING;
              }
              if (fElementQName.prefix != null && fElementQName.uri == null) {
                  fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                          "ElementPrefixUnbound",
                          new Object[]{fElementQName.prefix, fElementQName.rawname},
                          XMLErrorReporter.SEVERITY_FATAL_ERROR);
              }
  
              // bind attributes (xmlns are already bound bellow)
              int length = fAttributes.getLength();
              // fLength = 0; //initialize structure
              for (int i = 0; i < length; i++) {
                  fAttributes.getName(i, fAttributeQName);
  
                  String aprefix = fAttributeQName.prefix != null
                          ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
                  String uri = fNamespaceContext.getURI(aprefix);
                  // REVISIT: try removing the first "if" and see if it is faster.
                  //
                  if (fAttributeQName.uri != null && fAttributeQName.uri == uri) {
                      // checkDuplicates(fAttributeQName, fAttributes);
                      continue;
                  }
                  if (aprefix != XMLSymbols.EMPTY_STRING) {
                      fAttributeQName.uri = uri;
                      if (uri == null) {
                          fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                  "AttributePrefixUnbound",
                                  new Object[]{fElementQName.rawname,fAttributeQName.rawname,aprefix},
                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
                      }
                      fAttributes.setURI(i, uri);
                      // checkDuplicates(fAttributeQName, fAttributes);
                  }
              }
  
              if (length > 1) {
                  QName name = fAttributes.checkDuplicatesNS();
                  if (name != null) {
                      if (name.uri != null) {
                          fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                  "AttributeNSNotUnique",
                                  new Object[]{fElementQName.rawname, name.localpart, name.uri},
                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
                      } else {
                          fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                  "AttributeNotUnique",
                                  new Object[]{fElementQName.rawname, name.rawname},
                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
                      }
                  }
              }
          }
  
  
          if (fEmptyElement) {
              //decrease the markup depth..
              fMarkupDepth--;
  
              // check that this element was opened in the same entity
              if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
                  reportFatalError("ElementEntityMismatch",
                          new Object[]{fCurrentElement.rawname});
              }
              // call handler
              if (fDocumentHandler != null) {
                  if(DEBUG)
                      System.out.println("emptyElement = " + fElementQName);
  
                  fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
              }
  
              //We should not be popping out the context here in endELement becaause the namespace context is still
              //valid when parser is at the endElement state.
              fScanEndElement = true;
              //if (fBindNamespaces) {
              //  fNamespaceContext.popContext();
              //}
  
              //pop the element off the stack..
              fElementStack.popElement();
  
          } else {
  
              if(dtdGrammarUtil != null)
                  dtdGrammarUtil.startElement(fElementQName,fAttributes);
              if(fDocumentHandler != null){
                  //complete element and attributes are traversed in this function so we can send a callback
                  //here.
                  //<strong>we shouldn't be sending callback in scanDocument()</strong>
                  if(DEBUG)
                      System.out.println("startElement = " + fElementQName);
                  fDocumentHandler.startElement(fElementQName, fAttributes, null);
              }
          }
  
  
          if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanStartElement(): "+fEmptyElement);
          return fEmptyElement;
  
      } // scanStartElement():boolean
  
  
  
      /**
       * Scans an attribute.
       * <p>
       * <pre>
       * [41] Attribute ::= Name Eq AttValue
       * </pre>
       * <p>
       * <strong>Note:</strong> This method assumes that the next
       * character on the stream is the first character of the attribute
       * name.
       * <p>
       * <strong>Note:</strong> This method uses the fAttributeQName and
       * fQName variables. The contents of these variables will be
       * destroyed.
       *
       * @param attributes The attributes list for the scanned attribute.
       */
      protected void scanAttribute(XMLAttributesImpl attributes)
      throws IOException, XNIException {
          if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()");
  
          // name
          fEntityScanner.scanQName(fAttributeQName);
  
          // equals
          fEntityScanner.skipSpaces();
          if (!fEntityScanner.skipChar('=')) {
              reportFatalError("EqRequiredInAttribute",
                      new Object[]{fCurrentElement.rawname,fAttributeQName.rawname});
          }
          fEntityScanner.skipSpaces();
  
          // content
          int attrIndex = 0 ;
  
  
          //REVISIT: one more case needs to be included: external PE and standalone is no
          boolean isVC =  fHasExternalDTD && !fStandalone;
  
          // REVISIT: it seems that this function should not take attributes, and length
          //fTempString would store attribute value
          ///fTempString2 would store attribute non-normalized value
  
          //this function doesn't use 'attIndex'. We are adding the attribute later
          //after we have figured out that current attribute is not namespace declaration
          //since scanAttributeValue doesn't use attIndex parameter therefore we
          //can safely add the attribute later..
          XMLString tmpStr = getString();
          scanAttributeValue(tmpStr, fTempString2,
                  fAttributeQName.rawname, attributes,
                  attrIndex, isVC);
  
          String value = null;
          //fTempString.toString();
  
          // record namespace declarations if any.
          if (fBindNamespaces) {
  
              String localpart = fAttributeQName.localpart;
              String prefix = fAttributeQName.prefix != null
                      ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING;
              // when it's of form xmlns="..." or xmlns:prefix="...",
              // it's a namespace declaration. but prefix:xmlns="..." isn't.
              if (prefix == XMLSymbols.PREFIX_XMLNS ||
                      prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS) {
  
                  // get the internalized value of this attribute
                  String uri = fSymbolTable.addSymbol(tmpStr.ch,tmpStr.offset,tmpStr.length);
                  value = uri;
                  // 1. "xmlns" can't be bound to any namespace
                  if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) {
                      fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                              "CantBindXMLNS",
                              new Object[]{fAttributeQName},
                              XMLErrorReporter.SEVERITY_FATAL_ERROR);
                  }
  
                  // 2. the namespace for "xmlns" can't be bound to any prefix
                  if (uri == NamespaceContext.XMLNS_URI) {
                      fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                              "CantBindXMLNS",
                              new Object[]{fAttributeQName},
                              XMLErrorReporter.SEVERITY_FATAL_ERROR);
                  }
  
                  // 3. "xml" can't be bound to any other namespace than it's own
                  if (localpart == XMLSymbols.PREFIX_XML) {
                      if (uri != NamespaceContext.XML_URI) {
                          fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                  "CantBindXML",
                                  new Object[]{fAttributeQName},
                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
                      }
                  }
                  // 4. the namespace for "xml" can't be bound to any other prefix
                  else {
                      if (uri ==NamespaceContext.XML_URI) {
                          fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                                  "CantBindXML",
                                  new Object[]{fAttributeQName},
                                  XMLErrorReporter.SEVERITY_FATAL_ERROR);
                      }
                  }
                  prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING;
                  //set it equal to XMLSymbols.PREFIX_XMLNS when namespace declaration
                  // is of type xmlns = "..", in this case prefix = "" and localname = XMLSymbols.PREFIX_XMLNS
                  //this special behavior is because of dependency on this behavior in DOM components
                  if(prefix == XMLSymbols.EMPTY_STRING && localpart == XMLSymbols.PREFIX_XMLNS){
                      fAttributeQName.prefix = XMLSymbols.PREFIX_XMLNS;
                  }
                  // http://www.w3.org/TR/1999/REC-xml-names-19990114/#dt-prefix
                  // We should only report an error if there is a prefix,
                  // that is, the local part is not "xmlns". -SG
                  if (uri == XMLSymbols.EMPTY_STRING && localpart != XMLSymbols.PREFIX_XMLNS) {
                      fErrorReporter.reportError(XMLMessageFormatter.XMLNS_DOMAIN,
                              "EmptyPrefixedAttName",
                              new Object[]{fAttributeQName},
                              XMLErrorReporter.SEVERITY_FATAL_ERROR);
                  }
  
                  // check for duplicate prefix bindings
                  if (((NamespaceSupport) fNamespaceContext).containsPrefixInCurrentContext(prefix)) {
                      reportFatalError("AttributeNotUnique",
                              new Object[]{fCurrentElement.rawname,
                              fAttributeQName.rawname});
                  }
  
                  // declare prefix in context
                  boolean declared = fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null);
  
                  // check for duplicate xmlns declarations
                  if (!declared) { // by convention, prefix == "xmlns" | "xml"
                      // error if duplicate declaration
                      if (fXmlnsDeclared) {
                          reportFatalError("AttributeNotUnique",
                                  new Object[]{fCurrentElement.rawname,
                                  fAttributeQName.rawname});
                      }
  
                      // xmlns declared
                      fXmlnsDeclared = true;
                  }
  
                  //xerces internals (XSAttributeChecker) has dependency on namespace declaration returned
                  //as part of XMLAttributes.
                  //addition of namespace declaration to the attribute list is controlled by fNotAddNSDeclAsAttribute
                  //feature. This is required in Stax where namespace declarations are not considered as attribute
  
                  if(fNotAddNSDeclAsAttribute){
                      return ;
                  }
              }
          }
  
          //add the attributes to the list of attributes
          if (fBindNamespaces) {
              attrIndex = attributes.getLength();
              attributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, null);
          } else {
              int oldLen = attributes.getLength();
              attrIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
  
              // WFC: Unique Att Spec
              if (oldLen == attributes.getLength()) {
                  reportFatalError("AttributeNotUnique",
                          new Object[]{fCurrentElement.rawname,
                                  fAttributeQName.rawname});
              }
          }
  
          attributes.setValue(attrIndex, value,tmpStr);
          //attributes.setNonNormalizedValue(attrIndex, fTempString2.toString());
          //removing  as we are not using non-normalized values . -Venu
          attributes.setSpecified(attrIndex, true);
  
          // attempt to bind attribute
          if (fAttributeQName.prefix != null) {
              attributes.setURI(attrIndex, fNamespaceContext.getURI(fAttributeQName.prefix));
          }
  
          if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanAttribute()");
      } // scanAttribute(XMLAttributes)
  
  
  
  
  
      /** Creates a content driver. */
      protected Driver createContentDriver() {
          return new NSContentDriver();
      } // createContentDriver():Driver
  
      /**
       * Driver to handle content scanning.
       */
      protected final class NSContentDriver
              extends ContentDriver {
          /**
           * Scan for root element hook. This method is a hook for
           * subclasses to add code that handles scanning for the root
           * element. This method will also attempt to remove DTD validator
           * from the pipeline, if there is no DTD grammar. If DTD validator
           * is no longer in the pipeline bind namespaces in the scanner.
           *
           *
           * @return True if the caller should stop and return true which
           *          allows the scanner to switch to a new scanning
           *          driver. A return value of false indicates that
           *          the content driver should continue as normal.
           */
          protected boolean scanRootElementHook()
          throws IOException, XNIException {
  
              reconfigurePipeline();
              if (scanStartElement()) {
                  setScannerState(SCANNER_STATE_TRAILING_MISC);
                  setDriver(fTrailingMiscDriver);
                  return true;
              }
              return false;
  
          } // scanRootElementHook():boolean
  
          /**
           * Re-configures pipeline by removing the DTD validator
           * if no DTD grammar exists. If no validator exists in the
           * pipeline or there is no DTD grammar, namespace binding
           * is performed by the scanner in the enclosing class.
           */
          private void reconfigurePipeline() {
              //fDTDValidator will be null in Stax mode
              if (fNamespaces && fDTDValidator == null) {
                  fBindNamespaces = true;
              }
              else if (fNamespaces && !fDTDValidator.hasGrammar() ) {
                  fBindNamespaces = true;
                  fPerformValidation = fDTDValidator.validate();
                  // re-configure pipeline by removing DTDValidator
                  XMLDocumentSource source = fDTDValidator.getDocumentSource();
                  XMLDocumentHandler handler = fDTDValidator.getDocumentHandler();
                  source.setDocumentHandler(handler);
                  if (handler != null)
                      handler.setDocumentSource(source);
                  fDTDValidator.setDocumentSource(null);
                  fDTDValidator.setDocumentHandler(null);
              }
          } // reconfigurePipeline()
      }
  
  } // class XMLNSDocumentScannerImpl
  