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 jaxp.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription;
  import jaxp.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  import jaxp.sun.org.apache.xerces.internal.util.NamespaceSupport;
  import jaxp.sun.org.apache.xerces.internal.util.XMLChar;
  import jaxp.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl;
  import jaxp.sun.org.apache.xerces.internal.util.XMLStringBuffer;
  import jaxp.sun.org.apache.xerces.internal.utils.SecuritySupport;
  import jaxp.sun.org.apache.xerces.internal.xni.Augmentations;
  import jaxp.sun.org.apache.xerces.internal.xni.NamespaceContext;
  import jaxp.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  import jaxp.sun.org.apache.xerces.internal.xni.XMLString;
  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.parser.XMLDTDScanner;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  import jaxp.sun.xml.internal.stream.Entity;
  import jaxp.sun.xml.internal.stream.StaxXMLInputSource;
  import jaxp.sun.xml.internal.stream.dtd.DTDGrammarUtil;
  import java.io.EOFException;
  import java.io.IOException;
  import jaxp.xml.stream.XMLInputFactory;
  import jaxp.xml.stream.events.XMLEvent;
  
  
  /**
   * This class is responsible for scanning XML document structure
   * and content.
   *
   * 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.
   *
   * @author Neeraj Bajaj, Sun Microsystems
   * @author K.Venugopal, Sun Microsystems
   * @author Glenn Marcy, IBM
   * @author Andy Clark, IBM
   * @author Arnaud  Le Hors, IBM
   * @author Eric Ye, IBM
   * @author Sunitha Reddy, Sun Microsystems
   *
   * Refer to the table in unit-test javax.xml.stream.XMLStreamReaderTest.SupportDTD for changes
   * related to property SupportDTD.
   * @author Joe Wang, Sun Microsystems
   * @version $Id: XMLDocumentScannerImpl.java,v 1.17 2010-11-01 04:39:41 joehw Exp $
   */
  public class XMLDocumentScannerImpl
          extends XMLDocumentFragmentScannerImpl{
  
      //
      // Constants
      //
  
      // scanner states
  
      /** Scanner state: XML declaration. */
      protected static final int SCANNER_STATE_XML_DECL = 42;
  
      /** Scanner state: prolog. */
      protected static final int SCANNER_STATE_PROLOG = 43;
  
      /** Scanner state: trailing misc. */
      protected static final int SCANNER_STATE_TRAILING_MISC = 44;
  
      /** Scanner state: DTD internal declarations. */
      protected static final int SCANNER_STATE_DTD_INTERNAL_DECLS = 45;
  
      /** Scanner state: open DTD external subset. */
      protected static final int SCANNER_STATE_DTD_EXTERNAL = 46;
  
      /** Scanner state: DTD external declarations. */
      protected static final int SCANNER_STATE_DTD_EXTERNAL_DECLS = 47;
  
      /** Scanner state: NO MORE ELEMENTS. */
      protected static final int SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION = 48;
  
      // feature identifiers
  
      /** Property identifier document scanner: */
      protected static final String DOCUMENT_SCANNER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
  
      /** Feature identifier: load external DTD. */
      protected static final String LOAD_EXTERNAL_DTD =
              Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
  
      /** Feature identifier: load external DTD. */
      protected static final String DISALLOW_DOCTYPE_DECL_FEATURE =
              Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
  
      // property identifiers
  
      /** Property identifier: DTD scanner. */
      protected static final String DTD_SCANNER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
  
      // property identifier:  ValidationManager
      protected static final String VALIDATION_MANAGER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
  
      /** property identifier:  NamespaceContext */
      protected static final String NAMESPACE_CONTEXT =
          Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY;
  
      // recognized features and properties
  
      /** Recognized features. */
      private static final String[] RECOGNIZED_FEATURES = {
          LOAD_EXTERNAL_DTD,
                  DISALLOW_DOCTYPE_DECL_FEATURE,
      };
  
      /** Feature defaults. */
      private static final Boolean[] FEATURE_DEFAULTS = {
          Boolean.TRUE,
                  Boolean.FALSE,
      };
  
      /** Recognized properties. */
      private static final String[] RECOGNIZED_PROPERTIES = {
          DTD_SCANNER,
                  VALIDATION_MANAGER
      };
  
      /** Property defaults. */
      private static final Object[] PROPERTY_DEFAULTS = {
              null,
                  null
      };
  
      //
      // Data((Boolean)propertyManager.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue();
      //
  
      // properties
  
      /** DTD scanner. */
      protected XMLDTDScanner fDTDScanner = null;
  
      /** Validation manager . */
      //xxx: fValidationManager code needs to be added yet!
      protected ValidationManager fValidationManager;
  
      protected XMLStringBuffer fDTDDecl = null;
      protected boolean fReadingDTD = false;
      protected boolean fAddedListener = false;
  
      // protected data
  
      // other info
  
      /** Doctype name. */
      protected String fDoctypeName;
  
      /** Doctype declaration public identifier. */
      protected String fDoctypePublicId;
  
      /** Doctype declaration system identifier. */
      protected String fDoctypeSystemId;
  
      /** Namespace support. */
      protected NamespaceContext fNamespaceContext = new NamespaceSupport();
  
      // features
  
      /** Load external DTD. */
      protected boolean fLoadExternalDTD = true;
  
      // state
  
      /** Seen doctype declaration. */
      protected boolean fSeenDoctypeDecl;
  
      protected boolean fScanEndElement;
  
      //protected int fScannerLastState ;
  
      // drivers
  
      /** XML declaration driver. */
      protected Driver fXMLDeclDriver = new XMLDeclDriver();
  
      /** Prolog driver. */
      protected Driver fPrologDriver = new PrologDriver();
  
      /** DTD driver. */
      protected Driver fDTDDriver = null ;
  
      /** Trailing miscellaneous section driver. */
      protected Driver fTrailingMiscDriver = new TrailingMiscDriver();
      protected int fStartPos = 0;
      protected int fEndPos = 0;
      protected boolean fSeenInternalSubset= false;
      // temporary variables
  
      /** Array of 3 strings. */
      private String[] fStrings = new String[3];
  
      /** External subset source. */
      private XMLInputSource fExternalSubsetSource = null;
  
      /** A DTD Description. */
      private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null);
  
      /** String. */
      private XMLString fString = new XMLString();
  
      private static final char [] DOCTYPE = {'D','O','C','T','Y','P','E'};
      private static final char [] COMMENTSTRING = {'-','-'};
  
      //
      // Constructors
      //
  
      /** Default constructor. */
      public XMLDocumentScannerImpl() {} // <init>()
  
  
      //
      // XMLDocumentScanner methods
      //
  
  
      /**
       * Sets the input source.
       *
       * @param inputSource The input source.
       *
       * @throws IOException Thrown on i/o error.
       */
      public void setInputSource(XMLInputSource inputSource) throws IOException {
          fEntityManager.setEntityHandler(this);
          //this starts a new entity and sets the current entity to the document entity.
          fEntityManager.startDocumentEntity(inputSource);
          // fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());
          setScannerState(XMLEvent.START_DOCUMENT);
      } // setInputSource(XMLInputSource)
  
  
  
      /**return the state of the scanner */
      public int getScannetState(){
          return fScannerState ;
      }
  
  
  
  
      public void reset(PropertyManager propertyManager) {
          super.reset(propertyManager);
          // other settings
          fDoctypeName = null;
          fDoctypePublicId = null;
          fDoctypeSystemId = null;
          fSeenDoctypeDecl = false;
          fNamespaceContext.reset();
          fSupportDTD = ((Boolean)propertyManager.getProperty(XMLInputFactory.SUPPORT_DTD)).booleanValue();
  
          // xerces features
          fLoadExternalDTD = !((Boolean)propertyManager.getProperty(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.IGNORE_EXTERNAL_DTD)).booleanValue();
          setScannerState(XMLEvent.START_DOCUMENT);
          setDriver(fXMLDeclDriver);
          fSeenInternalSubset = false;
          if(fDTDScanner != null){
              ((XMLDTDScannerImpl)fDTDScanner).reset(propertyManager);
          }
          fEndPos = 0;
          fStartPos = 0;
          if(fDTDDecl != null){
              fDTDDecl.clear();
          }
  
      }
  
      /**
       * Resets the component. The component can query the component manager
       * about any features and properties that affect the operation of the
       * component.
       *
       * @param componentManager The component manager.
       *
       * @throws SAXException Thrown by component on initialization error.
       *                      For example, if a feature or property is
       *                      required for the operation of the component, the
       *                      component manager may throw a
       *                      SAXNotRecognizedException or a
       *                      SAXNotSupportedException.
       */
      public void reset(XMLComponentManager componentManager)
      throws XMLConfigurationException {
  
          super.reset(componentManager);
  
          // other settings
          fDoctypeName = null;
          fDoctypePublicId = null;
          fDoctypeSystemId = null;
          fSeenDoctypeDecl = false;
          fExternalSubsetSource = null;
  
          // xerces features
          fLoadExternalDTD = componentManager.getFeature(LOAD_EXTERNAL_DTD, true);
          fDisallowDoctype = componentManager.getFeature(DISALLOW_DOCTYPE_DECL_FEATURE, false);
  
          fNamespaces = componentManager.getFeature(NAMESPACES, true);
  
          fSeenInternalSubset = false;
          // xerces properties
          fDTDScanner = (XMLDTDScanner)componentManager.getProperty(DTD_SCANNER);
  
          fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER, null);
  
          try {
              fNamespaceContext = (NamespaceContext)componentManager.getProperty(NAMESPACE_CONTEXT);
          }
          catch (XMLConfigurationException e) { }
          if (fNamespaceContext == null) {
              fNamespaceContext = new NamespaceSupport();
          }
          fNamespaceContext.reset();
  
          fEndPos = 0;
          fStartPos = 0;
          if(fDTDDecl != null)
              fDTDDecl.clear();
  
  
          //fEntityScanner.registerListener((XMLBufferListener)componentManager.getProperty(DOCUMENT_SCANNER));
  
          // setup driver
          setScannerState(SCANNER_STATE_XML_DECL);
          setDriver(fXMLDeclDriver);
  
      } // 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() {
          String[] featureIds = super.getRecognizedFeatures();
          int length = featureIds != null ? featureIds.length : 0;
          String[] combinedFeatureIds = new String[length + RECOGNIZED_FEATURES.length];
          if (featureIds != null) {
              System.arraycopy(featureIds, 0, combinedFeatureIds, 0, featureIds.length);
          }
          System.arraycopy(RECOGNIZED_FEATURES, 0, combinedFeatureIds, length, RECOGNIZED_FEATURES.length);
          return combinedFeatureIds;
      } // 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 {
  
          super.setFeature(featureId, state);
  
          // Xerces properties
          if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
              final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
  
              if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
                  featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
                  fLoadExternalDTD = state;
                  return;
              }
              else if (suffixLength == Constants.DISALLOW_DOCTYPE_DECL_FEATURE.length() &&
                  featureId.endsWith(Constants.DISALLOW_DOCTYPE_DECL_FEATURE)) {
                  fDisallowDoctype = state;
                  return;
              }
          }
  
      } // 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() {
          String[] propertyIds = super.getRecognizedProperties();
          int length = propertyIds != null ? propertyIds.length : 0;
          String[] combinedPropertyIds = new String[length + RECOGNIZED_PROPERTIES.length];
          if (propertyIds != null) {
              System.arraycopy(propertyIds, 0, combinedPropertyIds, 0, propertyIds.length);
          }
          System.arraycopy(RECOGNIZED_PROPERTIES, 0, combinedPropertyIds, length, RECOGNIZED_PROPERTIES.length);
          return combinedPropertyIds;
      } // 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 {
  
          super.setProperty(propertyId, value);
  
          // Xerces properties
          if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
              final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
  
              if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
                  propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
                  fDTDScanner = (XMLDTDScanner)value;
              }
              if (suffixLength == Constants.NAMESPACE_CONTEXT_PROPERTY.length() &&
                  propertyId.endsWith(Constants.NAMESPACE_CONTEXT_PROPERTY)) {
                  if (value != null) {
                      fNamespaceContext = (NamespaceContext)value;
                  }
              }
  
              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 super.getFeatureDefault(featureId);
      } // 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 super.getPropertyDefault(propertyId);
      } // getPropertyDefault(String):Object
  
      //
      // XMLEntityHandler methods
      //
  
      /**
       * This method notifies of the start of an entity. The DTD has the
       * pseudo-name of "[dtd]" parameter entity names start with '%'; and
       * general entities are just specified by their name.
       *
       * @param name     The name of the entity.
       * @param identifier The resource identifier.
       * @param encoding The auto-detected IANA encoding name of the entity
       *                 stream. This value will be null in those situations
       *                 where the entity encoding is not auto-detected (e.g.
       *                 internal entities or a document entity that is
       *                 parsed from a java.io.Reader).
       *
       * @throws XNIException Thrown by handler to signal an error.
       */
      public void startEntity(String name,
              XMLResourceIdentifier identifier,
              String encoding, Augmentations augs) throws XNIException {
  
          super.startEntity(name, identifier, encoding,augs);
  
          //register current document scanner as a listener for XMLEntityScanner
          fEntityScanner.registerListener(this);
  
          // prepare to look for a TextDecl if external general entity
          if (!name.equals("[xml]") && fEntityScanner.isExternal()) {
              // Don't do this if we're skipping the entity!
              if (augs == null || !((Boolean) augs.getItem(Constants.ENTITY_SKIPPED)).booleanValue()) {
                  setScannerState(SCANNER_STATE_TEXT_DECL);
              }
          }
  
          // call handler
          /** comment this part.. LOCATOR problem.. */
          if (fDocumentHandler != null && name.equals("[xml]")) {
              fDocumentHandler.startDocument(fEntityScanner, encoding, fNamespaceContext, null);
          }
  
      } // startEntity(String,identifier,String)
  
  
      /**
       * This method notifies the end of an entity. The DTD has the pseudo-name
       * of "[dtd]" parameter entity names start with '%'; and general entities
       * are just specified by their name.
       *
       * @param name The name of the entity.
       *
       * @throws XNIException Thrown by handler to signal an error.
       */
      public void endEntity(String name, Augmentations augs) throws IOException, XNIException {
  
          super.endEntity(name, augs);
  
          if(name.equals("[xml]")){
              //if fMarkupDepth has reached 0.
              //and driver is fTrailingMiscDriver (which
              //handles end of document in normal case)
              //set the scanner state of SCANNER_STATE_TERMINATED
              if(fMarkupDepth == 0 && fDriver == fTrailingMiscDriver){
                  //set the scanner set to SCANNER_STATE_TERMINATED
                  setScannerState(SCANNER_STATE_TERMINATED) ;
              } else{
                  //else we have reached the end of document prematurely
                  //so throw EOFException.
                  throw new java.io.EOFException();
              }
  
              //this is taken care in wrapper which generates XNI callbacks, There are no next events
  
              //if (fDocumentHandler != null) {
                  //fDocumentHandler.endDocument(null);
              //}
          }
      } // endEntity(String)
  
  
      public XMLStringBuffer getDTDDecl(){
          Entity entity = fEntityScanner.getCurrentEntity();
          fDTDDecl.append(((Entity.ScannedEntity)entity).ch,fStartPos , fEndPos-fStartPos);
          if(fSeenInternalSubset)
              fDTDDecl.append("]>");
          return fDTDDecl;
      }
  
      public String getCharacterEncodingScheme(){
          return fDeclaredEncoding;
      }
  
      /** return the next state on the input
       *
       * @return int
       */
  
      public int next() throws IOException, XNIException {
          return fDriver.next();
      }
  
      //getNamespaceContext
      public NamespaceContext getNamespaceContext(){
          return fNamespaceContext ;
      }
  
  
  
      //
      // Protected methods
      //
  
      // driver factory methods
  
      /** Creates a content driver. */
      protected Driver createContentDriver() {
          return new ContentDriver();
      } // createContentDriver():Driver
  
      // scanning methods
  
      /** Scans a doctype declaration. */
      protected boolean scanDoctypeDecl(boolean supportDTD) throws IOException, XNIException {
  
          // spaces
          if (!fEntityScanner.skipSpaces()) {
              reportFatalError("MSG_SPACE_REQUIRED_BEFORE_ROOT_ELEMENT_TYPE_IN_DOCTYPEDECL",
                      null);
          }
  
          // root element name
          fDoctypeName = fEntityScanner.scanName();
          if (fDoctypeName == null) {
              reportFatalError("MSG_ROOT_ELEMENT_TYPE_REQUIRED", null);
          }
  
          // external id
          if (fEntityScanner.skipSpaces()) {
              scanExternalID(fStrings, false);
              fDoctypeSystemId = fStrings[0];
              fDoctypePublicId = fStrings[1];
              fEntityScanner.skipSpaces();
          }
  
          fHasExternalDTD = fDoctypeSystemId != null;
  
          // Attempt to locate an external subset with an external subset resolver.
          if (supportDTD && !fHasExternalDTD && fExternalSubsetResolver != null) {
              fDTDDescription.setValues(null, null, fEntityManager.getCurrentResourceIdentifier().getExpandedSystemId(), null);
              fDTDDescription.setRootName(fDoctypeName);
              fExternalSubsetSource = fExternalSubsetResolver.getExternalSubset(fDTDDescription);
              fHasExternalDTD = fExternalSubsetSource != null;
          }
  
          // call handler
          if (supportDTD && fDocumentHandler != null) {
              // NOTE: I don't like calling the doctypeDecl callback until
              //       end of the *full* doctype line (including internal
              //       subset) is parsed correctly but SAX2 requires that
              //       it knows the root element name and public and system
              //       identifier for the startDTD call. -Ac
              if (fExternalSubsetSource == null) {
                  fDocumentHandler.doctypeDecl(fDoctypeName, fDoctypePublicId, fDoctypeSystemId, null);
              }
              else {
                  fDocumentHandler.doctypeDecl(fDoctypeName, fExternalSubsetSource.getPublicId(), fExternalSubsetSource.getSystemId(), null);
              }
          }
  
          // is there an internal subset?
          boolean internalSubset = true;
          if (!fEntityScanner.skipChar('[')) {
              internalSubset = false;
              fEntityScanner.skipSpaces();
              if (!fEntityScanner.skipChar('>')) {
                  reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName});
              }
              fMarkupDepth--;
          }
          return internalSubset;
  
      } // scanDoctypeDecl():boolean
  
      //
      // Private methods
      //
      /** Set the scanner state after scanning DTD */
      protected void setEndDTDScanState() {
          setScannerState(SCANNER_STATE_PROLOG);
          setDriver(fPrologDriver);
          fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this);
          fReadingDTD=false;
      }
  
      /** Returns the scanner state name. */
      protected String getScannerStateName(int state) {
  
          switch (state) {
              case SCANNER_STATE_XML_DECL: return "SCANNER_STATE_XML_DECL";
              case SCANNER_STATE_PROLOG: return "SCANNER_STATE_PROLOG";
              case SCANNER_STATE_TRAILING_MISC: return "SCANNER_STATE_TRAILING_MISC";
              case SCANNER_STATE_DTD_INTERNAL_DECLS: return "SCANNER_STATE_DTD_INTERNAL_DECLS";
              case SCANNER_STATE_DTD_EXTERNAL: return "SCANNER_STATE_DTD_EXTERNAL";
              case SCANNER_STATE_DTD_EXTERNAL_DECLS: return "SCANNER_STATE_DTD_EXTERNAL_DECLS";
          }
          return super.getScannerStateName(state);
  
      } // getScannerStateName(int):String
  
      //
      // Classes
      //
  
      /**
       * Driver to handle XMLDecl scanning.
       *
       * This class has been modified as per the new design which is more suited to
       * efficiently build pull parser. Lots of performance improvements have been done and
       * the code has been added to support stax functionality/features.
       *
       * @author Neeraj Bajaj, Sun Microsystems.
       *
       * @author Andy Clark, IBM
       */
      protected final class XMLDeclDriver
              implements Driver {
  
          //
          // Driver methods
          //
  
  
          public int next() throws IOException, XNIException {
              if(DEBUG_NEXT){
                  System.out.println("NOW IN XMLDeclDriver");
              }
  
              // next driver is prolog regardless of whether there
              // is an XMLDecl in this document
              setScannerState(SCANNER_STATE_PROLOG);
              setDriver(fPrologDriver);
  
              //System.out.println("fEntityScanner = " + fEntityScanner);
              // scan XMLDecl
              try {
                  if (fEntityScanner.skipString(xmlDecl)) {
                      fMarkupDepth++;
                      // NOTE: special case where document starts with a PI
                      //       whose name starts with "xml" (e.g. "xmlfoo")
                      if (XMLChar.isName(fEntityScanner.peekChar())) {
                          fStringBuffer.clear();
                          fStringBuffer.append("xml");
                          while (XMLChar.isName(fEntityScanner.peekChar())) {
                              fStringBuffer.append((char)fEntityScanner.scanChar());
                          }
                          String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
                          //this function should fill the data.. and set the fEvent object to this event.
                          fContentBuffer.clear() ;
                          scanPIData(target, fContentBuffer);
                          //REVISIT:where else we can set this value to 'true'
                          fEntityManager.fCurrentEntity.mayReadChunks = true;
                          //return PI event since PI was encountered
                          return XMLEvent.PROCESSING_INSTRUCTION ;
                      }
                      // standard XML declaration
                      else {
                          scanXMLDeclOrTextDecl(false);
                          //REVISIT:where else we can set this value to 'true'
                          fEntityManager.fCurrentEntity.mayReadChunks = true;
                          return XMLEvent.START_DOCUMENT;
                      }
                  } else{
                      //REVISIT:where else we can set this value to 'true'
                      fEntityManager.fCurrentEntity.mayReadChunks = true;
                      //In both case return the START_DOCUMENT. ony difference is that first block will
                      //cosume the XML declaration if any.
                      return XMLEvent.START_DOCUMENT;
                  }
  
  
                  //START_OF_THE_DOCUMENT
  
  
              }
  
              // premature end of file
              catch (EOFException e) {
                  reportFatalError("PrematureEOF", null);
                  return -1;
                  //throw e;
              }
  
          }
      } // class XMLDeclDriver
  
      /**
       * Driver to handle prolog scanning.
       *
       * @author Andy Clark, IBM
       */
      protected final class PrologDriver
              implements Driver {
  
          /**
           * Drives the parser to the next state/event on the input. Parser is guaranteed
           * to stop at the next state/event.
           *
           * Internally XML document is divided into several states. Each state represents
           * a sections of XML document. When this functions returns normally, it has read
           * the section of XML document and returns the state corresponding to section of
           * document which has been read. For optimizations, a particular driver
           * can read ahead of the section of document (state returned) just read and
           * can maintain a different internal state.
           *
           * @return state representing the section of document just read.
           *
           * @throws IOException  Thrown on i/o error.
           * @throws XNIException Thrown on parse error.
           */
  
          public int next() throws IOException, XNIException {
              //System.out.println("here in next");
  
              if(DEBUG_NEXT){
                  System.out.println("NOW IN PrologDriver");
              }
              try {
                  do {
                      switch (fScannerState) {
                          case SCANNER_STATE_PROLOG: {
                              fEntityScanner.skipSpaces();
                              if (fEntityScanner.skipChar('<')) {
                                  setScannerState(SCANNER_STATE_START_OF_MARKUP);
                              } else if (fEntityScanner.skipChar('&')) {
                                  setScannerState(SCANNER_STATE_REFERENCE);
                              } else {
                                  setScannerState(SCANNER_STATE_CONTENT);
                              }
                              break;
                          }
  
                          case SCANNER_STATE_START_OF_MARKUP: {
                              fMarkupDepth++;
  
                              if (fEntityScanner.skipChar('?')) {
                                  setScannerState(SCANNER_STATE_PI);
                              } else if (fEntityScanner.skipChar('!')) {
                                  if (fEntityScanner.skipChar('-')) {
                                      if (!fEntityScanner.skipChar('-')) {
                                          reportFatalError("InvalidCommentStart",
                                                  null);
                                      }
                                      setScannerState(SCANNER_STATE_COMMENT);
                                  } else if (fEntityScanner.skipString(DOCTYPE)) {
                                      setScannerState(SCANNER_STATE_DOCTYPE);
                                      Entity entity = fEntityScanner.getCurrentEntity();
                                      if(entity instanceof Entity.ScannedEntity){
                                          fStartPos=((Entity.ScannedEntity)entity).position;
                                      }
                                      fReadingDTD=true;
                                      if(fDTDDecl == null)
                                          fDTDDecl = new XMLStringBuffer();
                                      fDTDDecl.append("<!DOCTYPE");
  
                                  } else {
                                      reportFatalError("MarkupNotRecognizedInProlog",
                                              null);
                                  }
                              } else if (XMLChar.isNameStart(fEntityScanner.peekChar())) {
                                  setScannerState(SCANNER_STATE_ROOT_ELEMENT);
                                  setDriver(fContentDriver);
                                  //from now onwards this would be handled by fContentDriver,in the same next() call
                                  return fContentDriver.next();
  
                              } else {
                                  reportFatalError("MarkupNotRecognizedInProlog",
                                          null);
                              }
                              break;
                          }
                      }
                  } while (fScannerState == SCANNER_STATE_PROLOG || fScannerState == SCANNER_STATE_START_OF_MARKUP );
  
                  switch(fScannerState){
                      /**
                      //this part is handled by FragmentContentHandler
                      case SCANNER_STATE_ROOT_ELEMENT: {
                          //we have read '<' and beginning of reading the start element tag
                          setScannerState(SCANNER_STATE_START_ELEMENT_TAG);
                          setDriver(fContentDriver);
                          //from now onwards this would be handled by fContentDriver,in the same next() call
                          return fContentDriver.next();
                      }
                       */
                      case SCANNER_STATE_COMMENT: {
                          //this function fills the data..
                          scanComment();
                          setScannerState(SCANNER_STATE_PROLOG);
                          return XMLEvent.COMMENT;
                          //setScannerState(SCANNER_STATE_PROLOG);
                          //break;
                      }
                      case SCANNER_STATE_PI: {
                          fContentBuffer.clear() ;
                          scanPI(fContentBuffer);
                          setScannerState(SCANNER_STATE_PROLOG);
                          return XMLEvent.PROCESSING_INSTRUCTION;
                      }
  
                      case SCANNER_STATE_DOCTYPE: {
                          if (fDisallowDoctype) {
                              reportFatalError("DoctypeNotAllowed", null);
                          }
  
                          if (fSeenDoctypeDecl) {
                              reportFatalError("AlreadySeenDoctype", null);
                          }
                          fSeenDoctypeDecl = true;
  
                          // scanDoctypeDecl() sends XNI doctypeDecl event that
                          // in SAX is converted to startDTD() event.
                          if (scanDoctypeDecl(fSupportDTD)) {
                              //allow parsing of entity decls to continue in order to stay well-formed
                              setScannerState(SCANNER_STATE_DTD_INTERNAL_DECLS);
                              fSeenInternalSubset = true;
                              if(fDTDDriver == null){
                                  fDTDDriver = new DTDDriver();
                              }
                              setDriver(fContentDriver);
                              //always return DTD event, the event however, will not contain any entities
                              return fDTDDriver.next();
                          }
  
                          if(fSeenDoctypeDecl){
                              Entity entity = fEntityScanner.getCurrentEntity();
                              if(entity instanceof Entity.ScannedEntity){
                                  fEndPos = ((Entity.ScannedEntity)entity).position;
                              }
                              fReadingDTD = false;
                          }
  
                          // handle external subset
                          if (fDoctypeSystemId != null) {
                              if (((fValidation || fLoadExternalDTD)
                                  && (fValidationManager == null || !fValidationManager.isCachedDTD()))) {
                                  if (fSupportDTD) {
                                      setScannerState(SCANNER_STATE_DTD_EXTERNAL);
                                  } else {
                                      setScannerState(SCANNER_STATE_PROLOG);
                                  }
  
                                  setDriver(fContentDriver);
                                  if(fDTDDriver == null) {
                                      fDTDDriver = new DTDDriver();
                                  }
  
                                  return fDTDDriver.next();
                              }
                          }
                          else if (fExternalSubsetSource != null) {
                              if (((fValidation || fLoadExternalDTD)
                                  && (fValidationManager == null || !fValidationManager.isCachedDTD()))) {
                                  // This handles the case of a DOCTYPE that had neither an internal subset or an external subset.
                                  fDTDScanner.setInputSource(fExternalSubsetSource);
                                  fExternalSubsetSource = null;
                              if (fSupportDTD)
                                  setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS);
                              else
                                  setScannerState(SCANNER_STATE_PROLOG);
                              setDriver(fContentDriver);
                              if(fDTDDriver == null)
                                  fDTDDriver = new DTDDriver();
                              return fDTDDriver.next();
                              }
                          }
  
                          // Send endDTD() call if:
                          // a) systemId is null or if an external subset resolver could not locate an external subset.
                          // b) "load-external-dtd" and validation are false
                          // c) DTD grammar is cached
  
                          // in XNI this results in 3 events:  doctypeDecl, startDTD, endDTD
                          // in SAX this results in 2 events: startDTD, endDTD
                          if (fDTDScanner != null) {
                              fDTDScanner.setInputSource(null);
                          }
                          setScannerState(SCANNER_STATE_PROLOG);
                          return XMLEvent.DTD;
                      }
  
                      case SCANNER_STATE_CONTENT: {
                          reportFatalError("ContentIllegalInProlog", null);
                          fEntityScanner.scanChar();
                      }
                      case SCANNER_STATE_REFERENCE: {
                          reportFatalError("ReferenceIllegalInProlog", null);
                      }
  
                      /**
                       * if (complete) {
                       * if (fEntityScanner.scanChar() != '<') {
                       * reportFatalError("RootElementRequired", null);
                       * }
                       * setScannerState(SCANNER_STATE_ROOT_ELEMENT);
                       * setDriver(fContentDriver);
                       * }
                       */
                  }
              }
              // premature end of file
              catch (EOFException e) {
                  reportFatalError("PrematureEOF", null);
                  //xxx  what should be returned here.... ???
                  return -1 ;
                  //throw e;
              }
              //xxx  what should be returned here.... ???
              return -1;
  
          }
  
  
      } // class PrologDriver
  
      /**
       * Driver to handle the internal and external DTD subsets.
       *
       * @author Andy Clark, IBM
       */
      protected final class DTDDriver
              implements Driver {
  
          //
          // Driver methods
          //
  
          public int next() throws IOException, XNIException{
              // throw new XNIException("DTD Parsing is currently not supported");
              if(DEBUG_NEXT){
                  System.out.println("Now in DTD Driver");
              }
  
              dispatch(true);
  
              if(DEBUG_NEXT){
                  System.out.println("After calling dispatch(true) -- At this point whole DTD is read.");
              }
  
              //xxx: remove this hack and align this with reusing DTD components
              //currently this routine will only be executed from Stax
              if(fPropertyManager != null){
                  dtdGrammarUtil =  new DTDGrammarUtil(((XMLDTDScannerImpl)fDTDScanner).getGrammar(),fSymbolTable, fNamespaceContext);
              }
  
              return XMLEvent.DTD ;
          }
  
          /**
           * Dispatch an XML "event".
           *
           * @param complete True if this driver is intended to scan
           *                 and dispatch as much as possible.
           *
           * @return True if there is more to dispatch either from this
           *          or a another driver.
           *
           * @throws IOException  Thrown on i/o error.
           * @throws XNIException Thrown on parse error.
           */
          public boolean dispatch(boolean complete)
          throws IOException, XNIException {
              fEntityManager.setEntityHandler(null);
              try {
                  boolean again;
                  XMLResourceIdentifierImpl resourceIdentifier = new XMLResourceIdentifierImpl();
                  if( fDTDScanner == null){
  
                      if (fEntityManager.getEntityScanner() instanceof XML11EntityScanner){
                          fDTDScanner = new XML11DTDScannerImpl();
                      } else
  
                      fDTDScanner = new XMLDTDScannerImpl();
  
                      ((XMLDTDScannerImpl)fDTDScanner).reset(fPropertyManager);
                  }
  
                  fDTDScanner.setLimitAnalyzer(fLimitAnalyzer);
                  do {
                      again = false;
                      switch (fScannerState) {
                          case SCANNER_STATE_DTD_INTERNAL_DECLS: {
                              // REVISIT: Should there be a feature for
                              //          the "complete" parameter?
                              boolean completeDTD = true;
  
                              boolean moreToScan = fDTDScanner.scanDTDInternalSubset(completeDTD, fStandalone, fHasExternalDTD && fLoadExternalDTD);
                              Entity entity = fEntityScanner.getCurrentEntity();
                              if(entity instanceof Entity.ScannedEntity){
                                  fEndPos=((Entity.ScannedEntity)entity).position;
                              }
                              fReadingDTD=false;
                              if (!moreToScan) {
                                  // end doctype declaration
                                  if (!fEntityScanner.skipChar(']')) {
                                      reportFatalError("EXPECTED_SQUARE_BRACKET_TO_CLOSE_INTERNAL_SUBSET",
                                              null);
                                  }
                                  fEntityScanner.skipSpaces();
                                  if (!fEntityScanner.skipChar('>')) {
                                      reportFatalError("DoctypedeclUnterminated", new Object[]{fDoctypeName});
                                  }
                                  fMarkupDepth--;
  
                                  if (!fSupportDTD) {
                                      //simply reset the entity store without having to mess around
                                      //with the DTD Scanner code
                                      fEntityStore = fEntityManager.getEntityStore();
                                      fEntityStore.reset();
                                  } else {
                                      // scan external subset next unless we are ignoring DTDs
                                      if (fDoctypeSystemId != null && (fValidation || fLoadExternalDTD)) {
                                          setScannerState(SCANNER_STATE_DTD_EXTERNAL);
                                          break;
                                      }
                                  }
  
                                  setEndDTDScanState();
                                  return true;
  
                              }
                              break;
                          }
                          case SCANNER_STATE_DTD_EXTERNAL: {
                              /**
                              fDTDDescription.setValues(fDoctypePublicId, fDoctypeSystemId, null, null);
                              fDTDDescription.setRootName(fDoctypeName);
                              XMLInputSource xmlInputSource =
                                  fEntityManager.resolveEntity(fDTDDescription);
                              fDTDScanner.setInputSource(xmlInputSource);
                              setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS);
                              again = true;
                              break;
                               */
  
                              resourceIdentifier.setValues(fDoctypePublicId, fDoctypeSystemId, null, null);
                              XMLInputSource xmlInputSource = null ;
                              StaxXMLInputSource staxInputSource =  fEntityManager.resolveEntityAsPerStax(resourceIdentifier);
  
                              // Check access permission. If the source is resolved by a resolver, the check is skipped.
                              if (!staxInputSource.hasResolver()) {
                                  String accessError = checkAccess(fDoctypeSystemId, fAccessExternalDTD);
                                  if (accessError != null) {
                                      reportFatalError("AccessExternalDTD", new Object[]{ SecuritySupport.sanitizePath(fDoctypeSystemId), accessError });
                                  }
                              }
                              xmlInputSource = staxInputSource.getXMLInputSource();
                              fDTDScanner.setInputSource(xmlInputSource);
                              if (fEntityScanner.fCurrentEntity != null) {
                                  setScannerState(SCANNER_STATE_DTD_EXTERNAL_DECLS);
                              } else {
                                  setScannerState(SCANNER_STATE_PROLOG);
                              }
                              again = true;
                              break;
                          }
                          case SCANNER_STATE_DTD_EXTERNAL_DECLS: {
                              // REVISIT: Should there be a feature for
                              //          the "complete" parameter?
                              boolean completeDTD = true;
                              boolean moreToScan = fDTDScanner.scanDTDExternalSubset(completeDTD);
                              if (!moreToScan) {
                                  setEndDTDScanState();
                                  return true;
                              }
                              break;
                          }
                          case SCANNER_STATE_PROLOG : {
                              // skip entity decls
                              setEndDTDScanState();
                              return true;
                          }
                          default: {
                              throw new XNIException("DTDDriver#dispatch: scanner state="+fScannerState+" ("+getScannerStateName(fScannerState)+')');
                          }
                      }
                  } while (complete || again);
              }
  
              // premature end of file
              catch (EOFException e) {
                  e.printStackTrace();
                  reportFatalError("PrematureEOF", null);
                  return false;
                  //throw e;
              }
  
              // cleanup
              finally {
                  fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this);
              }
  
              return true;
  
          }
  
          // dispatch(boolean):boolean
  
      } // class DTDDriver
  
      /**
       * Driver to handle content scanning.
       *
       * @author Andy Clark, IBM
       * @author Eric Ye, IBM
       */
      protected class ContentDriver
              extends FragmentContentDriver {
  
          //
          // Protected methods
          //
  
          // hooks
  
          // NOTE: These hook methods are added so that the full document
          //       scanner can share the majority of code with this class.
  
          /**
           * Scan for DOCTYPE hook. This method is a hook for subclasses
           * to add code to handle scanning for a the "DOCTYPE" string
           * after the string "<!" has been scanned.
           *
           * @return True if the "DOCTYPE" was scanned; false if "DOCTYPE"
           *          was not scanned.
           */
          protected boolean scanForDoctypeHook()
          throws IOException, XNIException {
  
              if (fEntityScanner.skipString(DOCTYPE)) {
                  setScannerState(SCANNER_STATE_DOCTYPE);
                  //                fEntityScanner.markStartOfDTD();
                  return true;
              }
              return false;
  
          } // scanForDoctypeHook():boolean
  
          /**
           * Element depth iz zero. This methos is a hook for subclasses
           * to add code to handle when the element depth hits zero. When
           * scanning a document fragment, an element depth of zero is
           * normal. However, when scanning a full XML document, the
           * scanner must handle the trailing miscellanous section of
           * the document after the end of the document's root element.
           *
           * @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 elementDepthIsZeroHook()
          throws IOException, XNIException {
  
              setScannerState(SCANNER_STATE_TRAILING_MISC);
              setDriver(fTrailingMiscDriver);
              return true;
  
          } // elementDepthIsZeroHook():boolean
  
          /**
           * Scan for root element hook. This method is a hook for
           * subclasses to add code that handles scanning for the root
           * element. When scanning a document fragment, there is no
           * "root" element. However, when scanning a full XML document,
           * the scanner must handle the root element specially.
           *
           * @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 {
  
              if (scanStartElement()) {
                  setScannerState(SCANNER_STATE_TRAILING_MISC);
                  setDriver(fTrailingMiscDriver);
                  return true;
              }
              return false;
  
          } // scanRootElementHook():boolean
  
          /**
           * End of file hook. This method is a hook for subclasses to
           * add code that handles the end of file. The end of file in
           * a document fragment is OK if the markup depth is zero.
           * However, when scanning a full XML document, an end of file
           * is always premature.
           */
          protected void endOfFileHook(EOFException e)
          throws IOException, XNIException {
  
              reportFatalError("PrematureEOF", null);
              // in case continue-after-fatal-error set, should not do this...
              //throw e;
  
          } // endOfFileHook()
  
          protected void resolveExternalSubsetAndRead()
          throws IOException, XNIException {
  
              fDTDDescription.setValues(null, null, fEntityManager.getCurrentResourceIdentifier().getExpandedSystemId(), null);
              fDTDDescription.setRootName(fElementQName.rawname);
              XMLInputSource src = fExternalSubsetResolver.getExternalSubset(fDTDDescription);
  
              if (src != null) {
                  fDoctypeName = fElementQName.rawname;
                  fDoctypePublicId = src.getPublicId();
                  fDoctypeSystemId = src.getSystemId();
                  // call document handler
                  if (fDocumentHandler != null) {
                      // This inserts a doctypeDecl event into the stream though no
                      // DOCTYPE existed in the instance document.
                      fDocumentHandler.doctypeDecl(fDoctypeName, fDoctypePublicId, fDoctypeSystemId, null);
                  }
                  try {
                      fDTDScanner.setInputSource(src);
                      while (fDTDScanner.scanDTDExternalSubset(true));
                  } finally {
                      fEntityManager.setEntityHandler(XMLDocumentScannerImpl.this);
                  }
              }
          } // resolveExternalSubsetAndRead()
  
  
  
      } // class ContentDriver
  
      /**
       * Driver to handle trailing miscellaneous section scanning.
       *
       * @author Andy Clark, IBM
       * @author Eric Ye, IBM
       */
      protected final class TrailingMiscDriver
              implements Driver {
  
          //
          // Driver methods
          //
          public int next() throws IOException, XNIException{
              //this could for cases like <foo/>
              //look at scanRootElementHook
              if(fEmptyElement){
                  fEmptyElement = false;
                  return XMLEvent.END_ELEMENT;
              }
  
              try {
                  if(fScannerState == SCANNER_STATE_TERMINATED){
                      return XMLEvent.END_DOCUMENT ;}
                  do {
                      switch (fScannerState) {
                          case SCANNER_STATE_TRAILING_MISC: {
  
                              fEntityScanner.skipSpaces();
                              //we should have reached the end of the document in
                              //most cases.
                              if(fScannerState == SCANNER_STATE_TERMINATED ){
                                  return XMLEvent.END_DOCUMENT ;
                              }
                              if (fEntityScanner.skipChar('<')) {
                                  setScannerState(SCANNER_STATE_START_OF_MARKUP);
                              } else {
                                  setScannerState(SCANNER_STATE_CONTENT);
                              }
                              break;
                          }
                          case SCANNER_STATE_START_OF_MARKUP: {
                              fMarkupDepth++;
                              if (fEntityScanner.skipChar('?')) {
                                  setScannerState(SCANNER_STATE_PI);
                              } else if (fEntityScanner.skipChar('!')) {
                                  setScannerState(SCANNER_STATE_COMMENT);
                              } else if (fEntityScanner.skipChar('/')) {
                                  reportFatalError("MarkupNotRecognizedInMisc",
                                          null);
                              } else if (XMLChar.isNameStart(fEntityScanner.peekChar())) {
                                  reportFatalError("MarkupNotRecognizedInMisc",
                                          null);
                                  scanStartElement();
                                  setScannerState(SCANNER_STATE_CONTENT);
                              } else {
                                  reportFatalError("MarkupNotRecognizedInMisc",
                                          null);
                              }
                              break;
                          }
                      }
                  }while(fScannerState == SCANNER_STATE_START_OF_MARKUP || fScannerState == SCANNER_STATE_TRAILING_MISC);
                  if(DEBUG_NEXT){
                      System.out.println("State set by deciding while loop [TrailingMiscellaneous] is = " + getScannerStateName(fScannerState));
                  }
                  switch (fScannerState){
                      case SCANNER_STATE_PI: {
                          fContentBuffer.clear();
                          scanPI(fContentBuffer);
                          setScannerState(SCANNER_STATE_TRAILING_MISC);
                          return XMLEvent.PROCESSING_INSTRUCTION ;
                      }
                      case SCANNER_STATE_COMMENT: {
                          if (!fEntityScanner.skipString(COMMENTSTRING)) {
                              reportFatalError("InvalidCommentStart", null);
                          }
                          scanComment();
                          setScannerState(SCANNER_STATE_TRAILING_MISC);
                          return XMLEvent.COMMENT;
                      }
                      case SCANNER_STATE_CONTENT: {
                          int ch = fEntityScanner.peekChar();
                          if (ch == -1) {
                              setScannerState(SCANNER_STATE_TERMINATED);
                              return XMLEvent.END_DOCUMENT ;
                          } else{
                              reportFatalError("ContentIllegalInTrailingMisc",
                                      null);
                              fEntityScanner.scanChar();
                              setScannerState(SCANNER_STATE_TRAILING_MISC);
                              return XMLEvent.CHARACTERS;
                          }
  
                      }
                      case SCANNER_STATE_REFERENCE: {
                          reportFatalError("ReferenceIllegalInTrailingMisc",
                                  null);
                          setScannerState(SCANNER_STATE_TRAILING_MISC);
                          return XMLEvent.ENTITY_REFERENCE ;
                      }
                      case SCANNER_STATE_TERMINATED: {
                          //there can't be any element after SCANNER_STATE_TERMINATED or when the parser
                          //has reached the end of document
                          setScannerState(SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION);
                          //xxx what to do when the scanner has reached the terminating state.
                          return XMLEvent.END_DOCUMENT ;
                      }
                      case SCANNER_STATE_NO_SUCH_ELEMENT_EXCEPTION:{
                          throw new java.util.NoSuchElementException("No more events to be parsed");
                      }
                      default: throw new XNIException("Scanner State " + fScannerState + " not Recognized ");
                  }//switch
  
              } catch (EOFException e) {
                  // NOTE: This is the only place we're allowed to reach
                  //       the real end of the document stream. Unless the
                  //       end of file was reached prematurely.
                  if (fMarkupDepth != 0) {
                      reportFatalError("PrematureEOF", null);
                      return -1;
                      //throw e;
                  }
                  //System.out.println("EOFException thrown") ;
                  setScannerState(SCANNER_STATE_TERMINATED);
              }
  
              return XMLEvent.END_DOCUMENT;
  
          }//next
  
      } // class TrailingMiscDriver
  
      /**
       * Implements XMLBufferListener interface.
       */
  
  
      /**
       * receives callbacks from {@link XMLEntityReader } when buffer
       * is being changed.
       * @param refreshPosition
       */
      public void refresh(int refreshPosition){
          super.refresh(refreshPosition);
          if(fReadingDTD){
              Entity entity = fEntityScanner.getCurrentEntity();
              if(entity instanceof Entity.ScannedEntity){
                  fEndPos=((Entity.ScannedEntity)entity).position;
              }
              fDTDDecl.append(((Entity.ScannedEntity)entity).ch,fStartPos , fEndPos-fStartPos);
              fStartPos = refreshPosition;
          }
      }
  
  } // class XMLDocumentScannerImpl
  