text: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You 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.
   */
  
  /*
   * $Id: SAX2XMLReaderImpl.cpp 568078 2007-08-21 11:43:25Z amassari $
   */
  
  #include <xercesc/util/IOException.hpp>
  #include <xercesc/util/RefStackOf.hpp>
  #include <xercesc/util/XMLUniDefs.hpp>
  #include <xercesc/util/Janitor.hpp>
  #include <xercesc/sax2/ContentHandler.hpp>
  #include <xercesc/sax2/LexicalHandler.hpp>
  #include <xercesc/sax2/DeclHandler.hpp>
  #include <xercesc/sax2/XMLReaderFactory.hpp>
  #include <xercesc/sax/DTDHandler.hpp>
  #include <xercesc/sax/ErrorHandler.hpp>
  #include <xercesc/sax/EntityResolver.hpp>
  #include <xercesc/sax/SAXParseException.hpp>
  #include <xercesc/sax/SAXException.hpp>
  #include <xercesc/internal/XMLScannerResolver.hpp>
  #include <xercesc/parsers/SAX2XMLReaderImpl.hpp>
  #include <xercesc/validators/common/GrammarResolver.hpp>
  #include <xercesc/framework/XMLGrammarPool.hpp>
  #include <xercesc/framework/XMLSchemaDescription.hpp>
  #include <xercesc/util/OutOfMemoryException.hpp>
  #include <xercesc/util/XMLEntityResolver.hpp>
  #include <string.h>
  
  XERCES_CPP_NAMESPACE_BEGIN
  
  
  SAX2XMLReader * XMLReaderFactory::createXMLReader(  MemoryManager* const  manager
                                                    , XMLGrammarPool* const gramPool)
  {
      SAX2XMLReaderImpl* pImpl=new (manager) SAX2XMLReaderImpl(manager, gramPool);
  	return pImpl;
  }
  
  
  const XMLCh gDTDEntityStr[] =
  {
      chOpenSquare, chLatin_d, chLatin_t, chLatin_d, chCloseSquare, chNull
  };
  
  
  
  typedef JanitorMemFunCall<SAX2XMLReaderImpl>    CleanupType;
  typedef JanitorMemFunCall<SAX2XMLReaderImpl>    ResetInProgressType;
  
  
  SAX2XMLReaderImpl::SAX2XMLReaderImpl(MemoryManager* const  manager
                                     , XMLGrammarPool* const gramPool):
  
      fNamespacePrefix(false)
      , fAutoValidation(false)
      , fValidation(false)
      , fParseInProgress(false)
      , fHasExternalSubset(false)
      , fElemDepth(0)
      , fAdvDHCount(0)
      , fAdvDHListSize(32)
      , fDocHandler(0)
      , fTempAttrVec(0)
      , fPrefixesStorage(0)
      , fPrefixes(0)
      , fPrefixCounts(0)
      , fDTDHandler(0)
      , fEntityResolver(0)
      , fXMLEntityResolver(0)
      , fErrorHandler(0)
      , fPSVIHandler(0)
      , fLexicalHandler(0)
      , fDeclHandler(0)
      , fAdvDHList(0)
      , fScanner(0)
      , fGrammarResolver(0)
      , fURIStringPool(0)
      , fValidator(0)
      , fMemoryManager(manager)
      , fGrammarPool(gramPool)
  {
      CleanupType cleanup(this, &SAX2XMLReaderImpl::cleanUp);
  
      try
      {
          initialize();
      }
      catch(const OutOfMemoryException&)
      {
          // Don't cleanup when out of memory, since executing the
          // code can cause problems.
          cleanup.release();
  
          throw;
      }
  
      cleanup.release();
  }
  
  SAX2XMLReaderImpl::~SAX2XMLReaderImpl()
  {
      cleanUp();
  }
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Initialize/Cleanup methods
  // ---------------------------------------------------------------------------
  void SAX2XMLReaderImpl::initialize()
  {
      // Create grammar resolver and string pool that we pass to the scanner
      fGrammarResolver = new (fMemoryManager) GrammarResolver(fGrammarPool, fMemoryManager);
      fURIStringPool = fGrammarResolver->getStringPool();
  
      //  Create a scanner and tell it what validator to use. Then set us
      //  as the document event handler so we can fill the DOM document.
      fScanner = XMLScannerResolver::getDefaultScanner(0, fGrammarResolver, fMemoryManager);
      fScanner->setURIStringPool(fURIStringPool);
  
      // Create the initial advanced handler list array and zero it out
      fAdvDHList = (XMLDocumentHandler**) fMemoryManager->allocate
      (
          fAdvDHListSize * sizeof(XMLDocumentHandler*)
      );//new XMLDocumentHandler*[fAdvDHListSize];
      memset(fAdvDHList, 0, sizeof(void*) * fAdvDHListSize);
  	
  	// SAX2 default is for namespaces (feature http://xml.org/sax/features/namespaces) to be on
  	setDoNamespaces(true) ;
  
  	// default: schema is on
  	setDoSchema(true);
  	
      fPrefixesStorage = new (fMemoryManager) XMLStringPool(109, fMemoryManager) ;
  	fPrefixes    = new (fMemoryManager) ValueStackOf<unsigned int> (30, fMemoryManager) ;
  	fTempAttrVec  = new (fMemoryManager) RefVectorOf<XMLAttr>  (10, false, fMemoryManager) ;
  	fPrefixCounts = new (fMemoryManager) ValueStackOf<unsigned int>(10, fMemoryManager) ;
  }
  
  
  void SAX2XMLReaderImpl::cleanUp()
  {
      fMemoryManager->deallocate(fAdvDHList);//delete [] fAdvDHList;
      delete fScanner;
      delete fPrefixesStorage;
      delete fPrefixes;
      delete fTempAttrVec;
      delete fPrefixCounts;
      delete fGrammarResolver;
      // grammar pool must do this
      //delete fURIStringPool;
  }
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Advanced document handler list maintenance methods
  // ---------------------------------------------------------------------------
  void SAX2XMLReaderImpl::installAdvDocHandler(XMLDocumentHandler* const toInstall)
  {
      // See if we need to expand and do so now if needed
      if (fAdvDHCount == fAdvDHListSize)
      {
          // Calc a new size and allocate the new temp buffer
          const unsigned int newSize = (unsigned int)(fAdvDHListSize * 1.5);
          XMLDocumentHandler** newList = (XMLDocumentHandler**) fMemoryManager->allocate
          (
              newSize * sizeof(XMLDocumentHandler*)
          );//new XMLDocumentHandler*[newSize];
  
          // Copy over the old data to the new list and zero out the rest
          memcpy(newList, fAdvDHList, sizeof(void*) * fAdvDHListSize);
          memset
          (
              &newList[fAdvDHListSize]
              , 0
              , sizeof(void*) * (newSize - fAdvDHListSize)
          );
  
          // And now clean up the old array and store the new stuff
          fMemoryManager->deallocate(fAdvDHList);//delete [] fAdvDHList;
          fAdvDHList = newList;
          fAdvDHListSize = newSize;
      }
  
      // Add this new guy into the empty slot
      fAdvDHList[fAdvDHCount++] = toInstall;
  
      //
      //  Install ourself as the document handler with the scanner. We might
      //  already be, but its not worth checking, just do it.
      //
      fScanner->setDocHandler(this);
  }
  
  
  bool SAX2XMLReaderImpl::removeAdvDocHandler(XMLDocumentHandler* const toRemove)
  {
      // If our count is zero, can't be any installed
      if (!fAdvDHCount)
          return false;
  
      //
      //  Search the array until we find this handler. If we find a null entry
      //  first, we can stop there before the list is kept contiguous.
      //
      unsigned int index;
      for (index = 0; index < fAdvDHCount; index++)
      {
          //
          //  We found it. We have to keep the list contiguous, so we have to
          //  copy down any used elements after this one.
          //
          if (fAdvDHList[index] == toRemove)
          {
              //
              //  Optimize if only one entry (pretty common). Otherwise, we
              //  have to copy them down to compact them.
              //
              if (fAdvDHCount > 1)
              {
                  index++;
                  while (index < fAdvDHCount)
                      fAdvDHList[index - 1] = fAdvDHList[index];
              }
  
              // Bump down the count and zero out the last one
              fAdvDHCount--;
              fAdvDHList[fAdvDHCount] = 0;
  
              //
              //  If this leaves us with no advanced handlers and there is
              //  no SAX doc handler installed on us, then remove us from the
              //  scanner as the document handler.
              //
              if (!fAdvDHCount && !fDocHandler)
                  fScanner->setDocHandler(0);
  
              return true;
          }
      }
  
      // Never found it
      return false;
  }
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl Validator functions
  // ---------------------------------------------------------------------------
  void SAX2XMLReaderImpl::setValidator(XMLValidator* valueToAdopt)
  {
      fValidator = valueToAdopt;
  	fScanner->setValidator(valueToAdopt);
  }
  
  XMLValidator* SAX2XMLReaderImpl::getValidator() const
  {
  	return fScanner->getValidator();
  }
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReader Interface
  // ---------------------------------------------------------------------------
  int SAX2XMLReaderImpl::getErrorCount() const
  {
      return fScanner->getErrorCount();
  }
  
  void SAX2XMLReaderImpl::setContentHandler(ContentHandler* const handler)
  {
  	fDocHandler = handler;
      if (fDocHandler)
      {
          //
          //  Make sure we are set as the document handler with the scanner.
          //  We may already be (if advanced handlers are installed), but its
          //  not worthing checking, just do it.
          //
          fScanner->setDocHandler(this);
      }
       else
      {
          //
          //  If we don't have any advanced handlers either, then deinstall us
          //  from the scanner because we don't need document events anymore.
          //
          if (!fAdvDHCount)
              fScanner->setDocHandler(0);
      }
  
  }
  
  void SAX2XMLReaderImpl::setDTDHandler(DTDHandler* const handler)
  {
      fDTDHandler = handler;
      if (fDTDHandler)
          fScanner->setDocTypeHandler(this);
      else
          fScanner->setDocTypeHandler(0);
  }
  
  
  void SAX2XMLReaderImpl::setErrorHandler(ErrorHandler* const handler)
  {
      //
      //  Store the handler. Then either install or deinstall us as the
      //  error reporter on the scanner.
      //
      fErrorHandler = handler;
      if (fErrorHandler) {
          fScanner->setErrorReporter(this);
          fScanner->setErrorHandler(fErrorHandler);
      }
      else {
          fScanner->setErrorReporter(0);
          fScanner->setErrorHandler(0);
      }
  }
  
  void SAX2XMLReaderImpl::setPSVIHandler(PSVIHandler* const handler)
  {
      fPSVIHandler = handler;
      if (fPSVIHandler) {
          fScanner->setPSVIHandler(fPSVIHandler);        
      }
      else {
          fScanner->setPSVIHandler(0);       
      }
  }
  
  void SAX2XMLReaderImpl::setLexicalHandler(LexicalHandler* const handler)
  {
      fLexicalHandler = handler;
      if (fLexicalHandler)
          fScanner->setDocTypeHandler(this);
      else
          fScanner->setDocTypeHandler(0);
  }
  
  void SAX2XMLReaderImpl::setDeclarationHandler(DeclHandler* const handler)
  {
      fDeclHandler = handler;
      if (fDeclHandler)
          fScanner->setDocTypeHandler(this);
      else
          fScanner->setDocTypeHandler(0);
  }
  
  
  void SAX2XMLReaderImpl::setEntityResolver(EntityResolver* const resolver)
  {
      fEntityResolver = resolver;
      if (fEntityResolver) {
          fScanner->setEntityHandler(this);
          fXMLEntityResolver = 0;
      }
      else {
          fScanner->setEntityHandler(0);
      }
  }
  
  void SAX2XMLReaderImpl::setXMLEntityResolver(XMLEntityResolver* const resolver)
  {
      fXMLEntityResolver = resolver;
      if (fXMLEntityResolver) {
          fScanner->setEntityHandler(this);
          fEntityResolver = 0;
      }
      else {
          fScanner->setEntityHandler(0);
      }
  }
  
  void SAX2XMLReaderImpl::setExitOnFirstFatalError(const bool newState)
  {
      fScanner->setExitOnFirstFatal(newState);
  }
  
  void SAX2XMLReaderImpl::setValidationConstraintFatal(const bool newState)
  {
      fScanner->setValidationConstraintFatal(newState);
  }
  
  void SAX2XMLReaderImpl::parse (const   InputSource&    source)
  {
      // Avoid multiple entrance
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      ResetInProgressType     resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
  
      try
      {
          fParseInProgress = true;
          fScanner->scanDocument(source);
      }
      catch(const OutOfMemoryException&)
      {
          resetInProgress.release();
  
          throw;
      }
  }
  
  void SAX2XMLReaderImpl::parse (const   XMLCh* const    systemId)
  {
      // Avoid multiple entrance
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      ResetInProgressType     resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
  
      try
      {
          fParseInProgress = true;
          fScanner->scanDocument(systemId);
      }
      catch(const OutOfMemoryException&)
      {
          resetInProgress.release();
  
          throw;
      }
  }
  
  void SAX2XMLReaderImpl::parse (const   char* const     systemId)
  {
      // Avoid multiple entrance
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      ResetInProgressType     resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
  
      try
      {
          fParseInProgress = true;
          fScanner->scanDocument(systemId);
          fParseInProgress = false;
      }
      catch(const OutOfMemoryException&)
      {
          resetInProgress.release();
  
          throw;
      }
  }
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Progressive parse methods
  // ---------------------------------------------------------------------------
  bool SAX2XMLReaderImpl::parseFirst( const   XMLCh* const    systemId
                              ,       XMLPScanToken&  toFill)
  {
      //
      //  Avoid multiple entrance. We cannot enter here while a regular parse
      //  is in progress.
      //
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      return fScanner->scanFirst(systemId, toFill);
  }
  
  bool SAX2XMLReaderImpl::parseFirst( const   char* const     systemId
                              ,       XMLPScanToken&  toFill)
  {
      //
      //  Avoid multiple entrance. We cannot enter here while a regular parse
      //  is in progress.
      //
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      return fScanner->scanFirst(systemId, toFill);
  }
  
  bool SAX2XMLReaderImpl::parseFirst( const   InputSource&    source
                              ,       XMLPScanToken&  toFill)
  {
      //
      //  Avoid multiple entrance. We cannot enter here while a regular parse
      //  is in progress.
      //
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      return fScanner->scanFirst(source, toFill);
  }
  
  bool SAX2XMLReaderImpl::parseNext(XMLPScanToken& token)
  {
      return fScanner->scanNext(token);
  }
  
  void SAX2XMLReaderImpl::parseReset(XMLPScanToken& token)
  {
      // Reset the scanner
      fScanner->scanReset(token);
  }
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Overrides of the XMLDocumentHandler interface
  // ---------------------------------------------------------------------------
  void SAX2XMLReaderImpl::docCharacters(  const   XMLCh* const    chars
                                  , const unsigned int    length
                                  , const bool            cdataSection)
  {
      // Suppress the chars before the root element.
      if (fElemDepth)
      {
          // Call the installed LexicalHandler.
          if (cdataSection && fLexicalHandler)
              fLexicalHandler->startCDATA();
  
          // Just map to the SAX document handler
          if (fDocHandler)
              fDocHandler->characters(chars, length);
  
          // Call the installed LexicalHandler.
          if (cdataSection && fLexicalHandler)
              fLexicalHandler->endCDATA();
      }
  
      //
      //  If there are any installed advanced handlers, then lets call them
      //  with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->docCharacters(chars, length, cdataSection);
  }
  
  
  void SAX2XMLReaderImpl::docComment(const XMLCh* const commentText)
  {
      // Call the installed LexicalHandler.
      if (fLexicalHandler)
      {
          // SAX2 reports comment text like characters -- as an
          // array with a length.
          fLexicalHandler->comment(commentText, XMLString::stringLen(commentText));
      }
  
      //
      //  OK, if there are any installed advanced handlers,
      // then let's call them with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->docComment(commentText);
  }
  
  
  void SAX2XMLReaderImpl::XMLDecl( const  XMLCh* const    versionStr
                          , const XMLCh* const    encodingStr
                          , const XMLCh* const    standaloneStr
                          , const XMLCh* const    actualEncodingStr
                          )
  {
      // SAX has no way to report this event. But, if there are any installed
      //  advanced handlers, then lets call them with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->XMLDecl( versionStr,
                                      encodingStr,
                                      standaloneStr,
                                      actualEncodingStr );
  }
  
  
  void SAX2XMLReaderImpl::docPI(  const   XMLCh* const    target
                          , const XMLCh* const    data)
  {
      // Just map to the SAX document handler
      if (fDocHandler)
          fDocHandler->processingInstruction(target, data);
  
      //
      //  If there are any installed advanced handlers, then lets call them
      //  with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->docPI(target, data);
  }
  
  
  void SAX2XMLReaderImpl::endDocument()
  {
      if (fDocHandler)
          fDocHandler->endDocument();
  
      //
      //  If there are any installed advanced handlers, then lets call them
      //  with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->endDocument();
  }
  
  
  void SAX2XMLReaderImpl::endEntityReference(const XMLEntityDecl& entityDecl)
  {
     // Call the installed LexicalHandler.
     if (fLexicalHandler)
          fLexicalHandler->endEntity(entityDecl.getName());
  
      //
      //  SAX has no way to report this event. But, if there are any installed
      //  advanced handlers, then lets call them with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->endEntityReference(entityDecl);
  }
  
  
  void SAX2XMLReaderImpl::ignorableWhitespace(const   XMLCh* const    chars
                                      , const unsigned int    length
                                      , const bool            cdataSection)
  {
      // Do not report the whitespace before the root element.
      if (!fElemDepth)
          return;
  
      // Just map to the SAX document handler
      if (fDocHandler)
          fDocHandler->ignorableWhitespace(chars, length);
  
      //
      //  If there are any installed advanced handlers, then lets call them
      //  with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->ignorableWhitespace(chars, length, cdataSection);
  }
  
  
  void SAX2XMLReaderImpl::resetDocument()
  {
      //
      //  If there are any installed advanced handlers, then lets call them
      //  with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->resetDocument();
  
      // Make sure our element depth flag gets set back to zero
      fElemDepth = 0;
  
      // reset prefix counters and prefix map
      fPrefixCounts->removeAllElements();
      fPrefixes->removeAllElements();
      fPrefixesStorage->flushAll();
  }
  
  
  void SAX2XMLReaderImpl::startDocument()
  {
      // Just map to the SAX document handler
      if (fDocHandler)
      {
          fDocHandler->setDocumentLocator(fScanner->getLocator());
          fDocHandler->startDocument();
      }
  
      //
      //  If there are any installed advanced handlers, then lets call them
      //  with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->startDocument();
  }
  
  
  void SAX2XMLReaderImpl::
  startElement(   const   XMLElementDecl&         elemDecl
                  , const unsigned int            elemURLId
                  , const XMLCh* const            elemPrefix
                  , const RefVectorOf<XMLAttr>&   attrList
                  , const unsigned int            attrCount
                  , const bool                    isEmpty
                  , const bool                    isRoot)
  {
      // Bump the element depth counter if not empty
      if (!isEmpty)
          fElemDepth++;
  
      if (fDocHandler)
      {
          ArrayJanitor<XMLCh> janElemName(NULL);
          XMLCh* elemQName = NULL;
          if(elemPrefix==0 || *elemPrefix==0)
              elemQName=(XMLCh*)elemDecl.getBaseName();
          else if(XMLString::equals(elemPrefix, elemDecl.getElementName()->getPrefix()))
              elemQName=(XMLCh*)elemDecl.getElementName()->getRawName();
          else
          {
              unsigned int prefixLen=XMLString::stringLen(elemPrefix);
              elemQName=(XMLCh*)fMemoryManager->allocate((prefixLen+1+XMLString::stringLen(elemDecl.getBaseName())+1)*sizeof(XMLCh));
              XMLString::moveChars(elemQName, elemPrefix, prefixLen);
              elemQName[prefixLen] = chColon;
              XMLString::copyString(&elemQName[prefixLen+1], elemDecl.getBaseName());
              janElemName.reset(elemQName, fMemoryManager);
          }
  
          if (getDoNamespaces())
          {
              unsigned int numPrefix = 0;
              const XMLCh*   nsString = XMLUni::fgXMLNSString;
              const XMLAttr* tempAttr = 0;
  
              if (!fNamespacePrefix)
              {
                  fTempAttrVec->removeAllElements();
              }
  
              for (unsigned int i = 0; i < attrCount; i++)
              {
                  const XMLCh*   nsPrefix = 0;
                  const XMLCh*   nsURI    = 0;
  
                  tempAttr = attrList.elementAt(i);
                  if (XMLString::equals(tempAttr->getQName(), nsString))
                      nsURI = tempAttr->getValue();
                  if (XMLString::equals(tempAttr->getPrefix(), nsString))
                  {
                      nsPrefix = tempAttr->getName();
                      nsURI = tempAttr->getValue();
                  }
                  if (!fNamespacePrefix)
                  {
                      if (nsURI == 0)
                          fTempAttrVec->addElement((XMLAttr*)tempAttr);
                  }
                  if (nsURI != 0)
                  {
                      if (nsPrefix == 0)
                          nsPrefix = XMLUni::fgZeroLenString;
                      fDocHandler->startPrefixMapping(nsPrefix, nsURI);
                      unsigned int nPrefixId=fPrefixesStorage->addOrFind(nsPrefix);
                      fPrefixes->push(nPrefixId) ;
                      numPrefix++;
                  }
              }
              fPrefixCounts->push(numPrefix) ;
              if (!fNamespacePrefix)
                  fAttrList.setVector(fTempAttrVec, fTempAttrVec->size(), fScanner);
              else
                  fAttrList.setVector(&attrList, attrCount, fScanner);
  
              // call startElement() with namespace declarations
              fDocHandler->startElement
              (
                  fScanner->getURIText(elemURLId)
                  , elemDecl.getBaseName()
                  , elemQName
                  , fAttrList
              );
          }
          else // no namespace
          {
              fAttrList.setVector(&attrList, attrCount, fScanner);
              fDocHandler->startElement(XMLUni::fgZeroLenString,
  										elemDecl.getBaseName(),
  										elemQName,
  										fAttrList);
          }
  
  
          // If its empty, send the end tag event now
          if (isEmpty)
          {
              // call endPrefixMapping appropriately.
              if (getDoNamespaces())
              {
                  fDocHandler->endElement
                  (
                      fScanner->getURIText(elemURLId)
                      , elemDecl.getBaseName()
                      , elemQName
                  );
  
                  unsigned int numPrefix = fPrefixCounts->pop();
                  for (unsigned int i = 0; i < numPrefix; ++i)
                  {
                      unsigned int nPrefixId = fPrefixes->pop() ;
                      fDocHandler->endPrefixMapping( fPrefixesStorage->getValueForId(nPrefixId) );
                  }
              }
              else
              {
                  fDocHandler->endElement(XMLUni::fgZeroLenString,
                                  elemDecl.getBaseName(),
                                  elemQName);
              }
          }
      }
  
      //
      //  If there are any installed advanced handlers, then lets call them
      //  with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
      {
          fAdvDHList[index]->startElement
          (
              elemDecl
              , elemURLId
              , elemPrefix
              , attrList
              , attrCount
              , isEmpty
              , isRoot
          );
      }
  }
  
  void SAX2XMLReaderImpl::endElement( const   XMLElementDecl& elemDecl
                              , const unsigned int    uriId
                              , const bool            isRoot
                              , const XMLCh* const    elemPrefix)
  {
      // Just map to the SAX document handler
      if (fDocHandler)
      {
          ArrayJanitor<XMLCh> janElemName(NULL);
          XMLCh* elemQName = NULL;
          if(elemPrefix==0 || *elemPrefix==0)
              elemQName=(XMLCh*)elemDecl.getBaseName();
          else if(XMLString::equals(elemPrefix, elemDecl.getElementName()->getPrefix()))
              elemQName=(XMLCh*)elemDecl.getElementName()->getRawName();
          else
          {
              unsigned int prefixLen=XMLString::stringLen(elemPrefix);
              elemQName=(XMLCh*)fMemoryManager->allocate((prefixLen+1+XMLString::stringLen(elemDecl.getBaseName())+1)*sizeof(XMLCh));
              XMLString::moveChars(elemQName, elemPrefix, prefixLen);
              elemQName[prefixLen] = chColon;
              XMLString::copyString(&elemQName[prefixLen+1], elemDecl.getBaseName());
              janElemName.reset(elemQName, fMemoryManager);
          }
  
          if (getDoNamespaces())
          {
              fDocHandler->endElement
              (
                  fScanner->getURIText(uriId)
                  , elemDecl.getBaseName()
                  , elemQName
              );
  
              // get the prefixes back so that we can call endPrefixMapping()
              unsigned int numPrefix = fPrefixCounts->pop();
              for (unsigned int i = 0; i < numPrefix; i++)
              {
                  unsigned int nPrefixId = fPrefixes->pop() ;
                  fDocHandler->endPrefixMapping( fPrefixesStorage->getValueForId(nPrefixId) );
              }
          }
          else
          {
              fDocHandler->endElement
              (
                  XMLUni::fgZeroLenString,
                  elemDecl.getBaseName(),
                  elemQName 
              );
          }
      }
  
      //
      //  If there are any installed advanced handlers, then lets call them
      //  with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->endElement(elemDecl, uriId, isRoot, elemPrefix);
  
      //
      //  Dump the element depth down again. Don't let it underflow in case
      //  of malformed XML.
      //
      if (fElemDepth)
          fElemDepth--;
  }
  
  void SAX2XMLReaderImpl::startEntityReference(const XMLEntityDecl& entityDecl)
  {
     // Call the installed LexicalHandler.
     if (fLexicalHandler)
          fLexicalHandler->startEntity(entityDecl.getName());
      //
      //  SAX has no way to report this. But, If there are any installed
      //  advanced handlers, then lets call them with this info.
      //
      for (unsigned int index = 0; index < fAdvDHCount; index++)
          fAdvDHList[index]->startEntityReference(entityDecl);
  }
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Overrides of the DocTypeHandler interface
  // ---------------------------------------------------------------------------
  void SAX2XMLReaderImpl::attDef( const   DTDElementDecl& elemDecl
                          , const DTDAttDef&      attDef
                          , const bool            ignoring)
  {
      if (fDeclHandler && !ignoring) {
  
          XMLAttDef::AttTypes attType = attDef.getType();
          XMLAttDef::DefAttTypes defAttType = attDef.getDefaultType();
          const XMLCh* defAttTypeStr = XMLUni::fgNullString;
          bool isEnumeration = (attType == XMLAttDef::Notation || attType == XMLAttDef::Enumeration);
          XMLBuffer enumBuf(128, fMemoryManager);
  
          if (defAttType == XMLAttDef::Fixed ||
              defAttType == XMLAttDef::Implied ||
              defAttType == XMLAttDef::Required) {
              defAttTypeStr = attDef.getDefAttTypeString(defAttType, fMemoryManager);
          }
  
          if (isEnumeration) {
  
              const XMLCh* enumString = attDef.getEnumeration();
              unsigned int enumLen = XMLString::stringLen(enumString);
  
              if (attType == XMLAttDef::Notation) {
  
                  enumBuf.set(XMLUni::fgNotationString);
                  enumBuf.append(chSpace);
              }
  
              enumBuf.append(chOpenParen);
  
              for (unsigned int i=0; i<enumLen; i++) {
                  if (enumString[i] == chSpace)
                      enumBuf.append(chPipe);
                  else
                      enumBuf.append(enumString[i]);
              }
  
              enumBuf.append(chCloseParen);
          }
  
          fDeclHandler->attributeDecl(elemDecl.getFullName(),
                                      attDef.getFullName(),
                                      (isEnumeration) ? enumBuf.getRawBuffer()
                                                      : attDef.getAttTypeString(attDef.getType(), fMemoryManager),
                                      defAttTypeStr,
                                      attDef.getValue());
      }
  }
  
  
  void SAX2XMLReaderImpl::doctypeComment(const XMLCh* const commentText)
  {
     if (fLexicalHandler)
     {
          // SAX2 reports comment text like characters -- as an
          // array with a length.
          fLexicalHandler->comment(commentText, XMLString::stringLen(commentText));
     }
  }
  
  
  void SAX2XMLReaderImpl::doctypeDecl(const   DTDElementDecl& elemDecl
                              , const XMLCh* const    publicId
                              , const XMLCh* const    systemId
                              , const bool            hasIntSubset
                              , const bool            hasExtSubset)
  {
      // Call the installed LexicalHandler.
      if (fLexicalHandler && (hasIntSubset || hasExtSubset))
          fLexicalHandler->startDTD(elemDecl.getFullName(), publicId, systemId);
  
      fHasExternalSubset = hasExtSubset;
  
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  void SAX2XMLReaderImpl::doctypePI(  const   XMLCh* const
                              , const XMLCh* const)
  {
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  void SAX2XMLReaderImpl::doctypeWhitespace(  const   XMLCh* const
                                      , const unsigned int)
  {
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  void SAX2XMLReaderImpl::elementDecl(const DTDElementDecl& elemDecl,
                                      const bool isIgnored)
  {
      if (fDeclHandler && !isIgnored)
          fDeclHandler->elementDecl(elemDecl.getFullName(),
                                    elemDecl.getFormattedContentModel());
  }
  
  
  void SAX2XMLReaderImpl::endAttList(const DTDElementDecl&)
  {
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  void SAX2XMLReaderImpl::endIntSubset()
  {
     // Call the installed LexicalHandler.
     if (!fHasExternalSubset && fLexicalHandler)
          fLexicalHandler->endDTD();
  
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  void SAX2XMLReaderImpl::endExtSubset()
  {
      // Call the installed LexicalHandler.
      if (fLexicalHandler) {
  
          fLexicalHandler->endEntity(gDTDEntityStr);
          fLexicalHandler->endDTD();
      }
  
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  void SAX2XMLReaderImpl::entityDecl( const   DTDEntityDecl&  entityDecl
                              , const bool            isPEDecl
                              , const bool            isIgnored)
  {
      //
      //  If we have a DTD handler, and this entity is not ignored, and
      //  its an unparsed entity, then send this one, else if we have a Decl
      //  handler then send this one.
      //
      if (!isIgnored) {
  
          if (entityDecl.isUnparsed()) {
  
              if (fDTDHandler) {
                  fDTDHandler->unparsedEntityDecl
                  (
                      entityDecl.getName()
                      , entityDecl.getPublicId()
                      , entityDecl.getSystemId()
                      , entityDecl.getNotationName()
                  );
              }
          }
          else if (fDeclHandler) {
  
              const XMLCh* entityName = entityDecl.getName();
              ArrayJanitor<XMLCh> tmpNameJan(0);
  
              if (isPEDecl) {
  
                  unsigned int nameLen = XMLString::stringLen(entityName);
                  XMLCh* tmpName = (XMLCh*) fMemoryManager->allocate
                  (
                      (nameLen + 2) * sizeof(XMLCh)
                  );//new XMLCh[nameLen + 2];
  
                  tmpNameJan.reset(tmpName, fMemoryManager);
                  tmpName[0] = chPercent;
                  XMLString::copyString(tmpName + 1, entityName);
                  entityName = tmpName;
              }
  
              if (entityDecl.isExternal()) {
                  fDeclHandler->externalEntityDecl
                  (
                      entityName
                      , entityDecl.getPublicId()
                      , entityDecl.getSystemId()
                  );
              }
              else {
                  fDeclHandler->internalEntityDecl
                  (
                      entityName
                      , entityDecl.getValue()
                  );
              }
          }
      }
  }
  
  
  void SAX2XMLReaderImpl::resetDocType()
  {
      fHasExternalSubset = false;
      // Just map to the DTD handler
      if (fDTDHandler)
          fDTDHandler->resetDocType();
  }
  
  
  void SAX2XMLReaderImpl::notationDecl(   const   XMLNotationDecl&    notDecl
                                  , const bool                isIgnored)
  {
      if (fDTDHandler && !isIgnored)
      {
          fDTDHandler->notationDecl
          (
              notDecl.getName()
              , notDecl.getPublicId()
              , notDecl.getSystemId()
          );
      }
  }
  
  
  void SAX2XMLReaderImpl::startAttList(const DTDElementDecl&)
  {
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  void SAX2XMLReaderImpl::startIntSubset()
  {
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  void SAX2XMLReaderImpl::startExtSubset()
  {
      if (fLexicalHandler)
          fLexicalHandler->startEntity(gDTDEntityStr);
  }
  
  
  void SAX2XMLReaderImpl::TextDecl(   const  XMLCh* const
                              , const XMLCh* const)
  {
      // Unused by SAX DTDHandler interface at this time
  }
  
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Handlers for the XMLEntityHandler interface
  // ---------------------------------------------------------------------------
  void SAX2XMLReaderImpl::endInputSource(const InputSource&)
  {
  }
  
  bool SAX2XMLReaderImpl::expandSystemId(const XMLCh* const, XMLBuffer&)
  {
      return false;
  }
  
  
  void SAX2XMLReaderImpl::resetEntities()
  {
      // Nothing to do for this one
  }
  
  
  InputSource* SAX2XMLReaderImpl::resolveEntity(   const   XMLCh* const    publicId
                                                 , const   XMLCh* const    systemId
                                                 , const   XMLCh* const)
  {
      // Just map to the SAX entity resolver handler
      if (fEntityResolver)
          return fEntityResolver->resolveEntity(publicId, systemId);
      return 0;
  }
  
  InputSource* SAX2XMLReaderImpl::resolveEntity(XMLResourceIdentifier* resourceIdentifier)
  {
      //
      //  Just map it to the SAX entity resolver. If there is not one installed,
      //  return a null pointer to cause the default resolution.
      //
      if (fEntityResolver)
          return fEntityResolver->resolveEntity(resourceIdentifier->getPublicId(), 
                                                  resourceIdentifier->getSystemId());
      if (fXMLEntityResolver)
          return fXMLEntityResolver->resolveEntity(resourceIdentifier);
  
      return 0;
  }
   
  void SAX2XMLReaderImpl::startInputSource(const InputSource&)
  {
      // Nothing to do for this one
  }
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Overrides of the XMLErrorReporter interface
  // ---------------------------------------------------------------------------
  void SAX2XMLReaderImpl::resetErrors()
  {
      if (fErrorHandler)
          fErrorHandler->resetErrors();
  }
  
  
  void SAX2XMLReaderImpl::error(  const   unsigned int
                          , const XMLCh* const
                          , const XMLErrorReporter::ErrTypes  errType
                          , const XMLCh* const                errorText
                          , const XMLCh* const                systemId
                          , const XMLCh* const                publicId
                          , const XMLSSize_t                  lineNum
                          , const XMLSSize_t                  colNum)
  {
      SAXParseException toThrow = SAXParseException
      (
          errorText
          , publicId
          , systemId
          , lineNum
          , colNum
          , fMemoryManager
      );
  
      if (!fErrorHandler)
      {
          if (errType == XMLErrorReporter::ErrType_Fatal)
              throw toThrow;
          else
              return;
      }
  
      if (errType == XMLErrorReporter::ErrType_Warning)
          fErrorHandler->warning(toThrow);
      else if (errType == XMLErrorReporter::ErrType_Fatal)
          fErrorHandler->fatalError(toThrow);
      else
          fErrorHandler->error(toThrow);
  }
  
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Features and Properties
  // ---------------------------------------------------------------------------
  
  void SAX2XMLReaderImpl::setFeature(const XMLCh* const name, const bool value)
  {
  
      if (fParseInProgress)
          throw SAXNotSupportedException("Feature modification is not supported during parse.", fMemoryManager);
  	
      if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpaces) == 0)
      {
          setDoNamespaces(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreValidation) == 0)
      {
          fValidation = value;
          if (fValidation)
              if (fAutoValidation)
                  setValidationScheme(Val_Auto);
              else
                  setValidationScheme(Val_Always);
          else
              setValidationScheme(Val_Never);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpacePrefixes) == 0)
      {
          fNamespacePrefix = value;
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDynamic) == 0)
      {
          fAutoValidation = value;
          // for auto validation, the sax2 core validation feature must also be enabled.
          if (fValidation)
              if (fAutoValidation)
                  setValidationScheme(Val_Auto);
              else
                  setValidationScheme(Val_Always);
          else
              setValidationScheme(Val_Never);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0)
      {
          setDoSchema(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0)
      {
          fScanner->setValidationSchemaFullChecking(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0)
      {
          fScanner->setIdentityConstraintChecking(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0)
      {
          fScanner->setLoadExternalDTD(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0)
      {
          fScanner->setExitOnFirstFatal(!value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0)
      {
          fScanner->setValidationConstraintFatal(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0)
      {
          fScanner->cacheGrammarFromParse(value);
  
          if (value)
              fScanner->useCachedGrammarInParse(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0)
      {
          if (value || !fScanner->isCachingGrammarFromParse())
              fScanner->useCachedGrammarInParse(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0)
      {
          fScanner->setCalculateSrcOfs(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0)
      {
          fScanner->setStandardUriConformant(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0)
      {
          fScanner->setGenerateSyntheticAnnotations(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0)
      {
          fScanner->setValidateAnnotations(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0)
      {
          fScanner->setIgnoredCachedDTD(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0)
      {
          fScanner->setIgnoreAnnotations(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0)
      {
          fScanner->setDisableDefaultEntityResolution(value);
      }
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0)
      {
          fScanner->setSkipDTDValidation(value);
      }
      else
         throw SAXNotRecognizedException("Unknown Feature", fMemoryManager);
  }
  
  bool SAX2XMLReaderImpl::getFeature(const XMLCh* const name) const
  {
      if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpaces) == 0)
          return getDoNamespaces();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreValidation) == 0)
          return fValidation;
      else if (XMLString::compareIStringASCII(name, XMLUni::fgSAX2CoreNameSpacePrefixes) == 0)
          return fNamespacePrefix;
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDynamic) == 0)
          return fAutoValidation;
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchema) == 0)
          return getDoSchema();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaFullChecking) == 0)
          return fScanner->getValidationSchemaFullChecking();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIdentityConstraintChecking) == 0)
          return fScanner->getIdentityConstraintChecking();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesLoadExternalDTD) == 0)
          return fScanner->getLoadExternalDTD();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesContinueAfterFatalError) == 0)
          return !fScanner->getExitOnFirstFatal();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidationErrorAsFatal) == 0)
          return fScanner->getValidationConstraintFatal();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCacheGrammarFromParse) == 0)
          return fScanner->isCachingGrammarFromParse();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesUseCachedGrammarInParse) == 0)
          return fScanner->isUsingCachedGrammarInParse();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesCalculateSrcOfs) == 0)
          return fScanner->getCalculateSrcOfs();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesStandardUriConformant) == 0)
          return fScanner->getStandardUriConformant();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesGenerateSyntheticAnnotations) == 0)
          return fScanner->getGenerateSyntheticAnnotations();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesValidateAnnotations) == 0)
          return fScanner->getValidateAnnotations();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreCachedDTD) == 0)
          return fScanner->getIgnoreCachedDTD();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesIgnoreAnnotations) == 0)
          return fScanner->getIgnoreAnnotations();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesDisableDefaultEntityResolution) == 0)
          return fScanner->getDisableDefaultEntityResolution();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSkipDTDValidation) == 0)
          return fScanner->getSkipDTDValidation();
      else
         throw SAXNotRecognizedException("Unknown Feature", fMemoryManager);
  
      return false;
  }
  
  void SAX2XMLReaderImpl::setProperty(const XMLCh* const name, void* value)
  {
  	if (fParseInProgress)
  		throw SAXNotSupportedException("Property modification is not supported during parse.", fMemoryManager);
  
  	if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0)
  	{
  		fScanner->setExternalSchemaLocation((XMLCh*)value);
  	}
  	else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0)
  	{
  		fScanner->setExternalNoNamespaceSchemaLocation((XMLCh*)value);
  	}
  	else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0)
  	{
  		fScanner->setSecurityManager((SecurityManager*)value);
  	}
      else if (XMLString::equals(name, XMLUni::fgXercesScannerName))
      {
          XMLScanner* tempScanner = XMLScannerResolver::resolveScanner
          (
              (const XMLCh*) value
              , fValidator
              , fGrammarResolver
              , fMemoryManager
          );
  
          if (tempScanner) {
  
              tempScanner->setParseSettings(fScanner);
              tempScanner->setURIStringPool(fURIStringPool);
              delete fScanner;
              fScanner = tempScanner;
          }
      }
      else
         throw SAXNotRecognizedException("Unknown Property", fMemoryManager);
  }
  
  
  void* SAX2XMLReaderImpl::getProperty(const XMLCh* const name) const
  {
      if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalSchemaLocation) == 0)
          return (void*)fScanner->getExternalSchemaLocation();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation) == 0)
          return (void*)fScanner->getExternalNoNamespaceSchemaLocation();
      else if (XMLString::compareIStringASCII(name, XMLUni::fgXercesSecurityManager) == 0)
          return (void*)fScanner->getSecurityManager();
      else if (XMLString::equals(name, XMLUni::fgXercesScannerName))
          return (void*)fScanner->getName();
      else
          throw SAXNotRecognizedException("Unknown Property", fMemoryManager);
      return 0;
  }
  
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Private getters and setters for conveniences
  // ---------------------------------------------------------------------------
  
  void SAX2XMLReaderImpl::setValidationScheme(const ValSchemes newScheme)
  {
      if (newScheme == Val_Never)
          fScanner->setValidationScheme(XMLScanner::Val_Never);
      else if (newScheme == Val_Always)
          fScanner->setValidationScheme(XMLScanner::Val_Always);
      else
          fScanner->setValidationScheme(XMLScanner::Val_Auto);
  }
  
  void SAX2XMLReaderImpl::setDoNamespaces(const bool newState)
  {
      fScanner->setDoNamespaces(newState);
  }
  
  bool SAX2XMLReaderImpl::getDoNamespaces() const
  {
      return fScanner->getDoNamespaces();
  }
  
  void SAX2XMLReaderImpl::setDoSchema(const bool newState)
  {
      fScanner->setDoSchema(newState);
  }
  
  bool SAX2XMLReaderImpl::getDoSchema() const
  {
      return fScanner->getDoSchema();
  }
  
  
  // ---------------------------------------------------------------------------
  //  SAX2XMLReaderImpl: Grammar preparsing
  // ---------------------------------------------------------------------------
  Grammar* SAX2XMLReaderImpl::loadGrammar(const char* const systemId,
                                          const short grammarType,
                                          const bool toCache)
  {
      // Avoid multiple entrance
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      ResetInProgressType     resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
  
      Grammar* grammar = 0;
      try
      {
          fParseInProgress = true;
          grammar = fScanner->loadGrammar(systemId, grammarType, toCache);
      }
      catch(const OutOfMemoryException&)
      {
          resetInProgress.release();
  
          throw;
      }
  
      return grammar;
  }
  
  Grammar* SAX2XMLReaderImpl::loadGrammar(const XMLCh* const systemId,
                                          const short grammarType,
                                          const bool toCache)
  {
      // Avoid multiple entrance
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      ResetInProgressType     resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
  
      Grammar* grammar = 0;
      try
      {
          fParseInProgress = true;
          grammar = fScanner->loadGrammar(systemId, grammarType, toCache);
      }
      catch(const OutOfMemoryException&)
      {
          resetInProgress.release();
  
          throw;
      }
  
      return grammar;
  }
  
  Grammar* SAX2XMLReaderImpl::loadGrammar(const InputSource& source,
                                          const short grammarType,
                                          const bool toCache)
  {
      // Avoid multiple entrance
      if (fParseInProgress)
          ThrowXMLwithMemMgr(IOException, XMLExcepts::Gen_ParseInProgress, fMemoryManager);
  
      ResetInProgressType     resetInProgress(this, &SAX2XMLReaderImpl::resetInProgress);
  
      Grammar* grammar = 0;
      try
      {
          fParseInProgress = true;
          grammar = fScanner->loadGrammar(source, grammarType, toCache);
      }
      catch(const OutOfMemoryException&)
      {
          resetInProgress.release();
  
          throw;
      }
  
      return grammar;
  }
  
  void SAX2XMLReaderImpl::resetInProgress()
  {
      fParseInProgress = false;
  }
  
  void SAX2XMLReaderImpl::resetCachedGrammarPool()
  {
      fGrammarResolver->resetCachedGrammar();
  }
  
  void SAX2XMLReaderImpl::setInputBufferSize(const size_t bufferSize)
  {
      fScanner->setInputBufferSize(bufferSize);
  }
  
  Grammar* SAX2XMLReaderImpl::getGrammar(const XMLCh* const nameSpaceKey)
  {
      return fGrammarResolver->getGrammar(nameSpaceKey);
  }
  
  
  XERCES_CPP_NAMESPACE_END
  
  