ReaderMgr.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:27k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  * 
  4.  * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  * 
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer. 
  13.  * 
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  * 
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:  
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  * 
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written 
  29.  *    permission, please contact apache@apache.org.
  30.  * 
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  * 
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  * 
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: ReaderMgr.cpp,v 1.14 2001/09/14 14:44:01 peiyongz Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <util/BinMemInputStream.hpp>
  63. #include <util/Janitor.hpp>
  64. #include <util/PlatformUtils.hpp>
  65. #include <util/RuntimeException.hpp>
  66. #include <util/UnexpectedEOFException.hpp>
  67. #include <util/XMLURL.hpp>
  68. #include <util/XMLUniDefs.hpp>
  69. #include <util/XMLUni.hpp>
  70. #include <sax/InputSource.hpp>
  71. #include <framework/LocalFileInputSource.hpp>
  72. #include <framework/URLInputSource.hpp>
  73. #include <framework/XMLBuffer.hpp>
  74. #include <framework/XMLDocumentHandler.hpp>
  75. #include <framework/XMLEntityDecl.hpp>
  76. #include <framework/XMLEntityHandler.hpp>
  77. #include <internal/EndOfEntityException.hpp>
  78. #include <internal/ReaderMgr.hpp>
  79. // ---------------------------------------------------------------------------
  80. //  ReaderMgr: Constructors and Destructor
  81. // ---------------------------------------------------------------------------
  82. ReaderMgr::ReaderMgr() :
  83.     fCurEntity(0)
  84.     , fCurReader(0)
  85.     , fEntityHandler(0)
  86.     , fEntityStack(0)
  87.     , fNextReaderNum(1)
  88.     , fReaderStack(0)
  89.     , fThrowEOE(false)
  90. {
  91. }
  92. ReaderMgr::~ReaderMgr()
  93. {
  94.     //
  95.     //  Clean up the reader and entity stacks. Note that we don't own the
  96.     //  entities, so we don't delete the current entity (and the entity stack
  97.     //  does not own its elements either, so deleting it will not delete the
  98.     //  entities it still references!)
  99.     //
  100.     delete fCurReader;
  101.     delete fReaderStack;
  102.     delete fEntityStack;
  103. }
  104. // ---------------------------------------------------------------------------
  105. //  ReaderMgr: Getter methods
  106. // ---------------------------------------------------------------------------
  107. bool ReaderMgr::isEmpty() const
  108. {
  109.     return fReaderStack->empty();
  110. }
  111. // ---------------------------------------------------------------------------
  112. //  ReaderMgr: Scanning APIs
  113. // ---------------------------------------------------------------------------
  114. XMLCh ReaderMgr::getNextChar()
  115. {
  116.     XMLCh chRet;
  117.     if (fCurReader->getNextChar(chRet))
  118.         return chRet;
  119.     //
  120.     //  Didn't get anything back so this reader is hosed. So lets move to
  121.     //  the next reader on the stack. If this fails, it will be because
  122.     //  its the end of the original file, and we just return zero.
  123.     //
  124.     //  If its the end of an entity and fThrowEOE is set, it will throw out
  125.     //  of here. Otherwise, it will take us down to the next reader and
  126.     //  we'll have more chars.
  127.     //
  128.     if (!popReader())
  129.         return XMLCh(0);
  130.     // Else try again and return the new character
  131.     fCurReader->getNextChar(chRet);
  132.     return chRet;
  133. }
  134. void ReaderMgr::getSpaces(XMLBuffer& toFill)
  135. {
  136.     // Reset the buffer before we start
  137.     toFill.reset();
  138.     while (true)
  139.     {
  140.         //
  141.         //  Get all the spaces from the current reader. If it returns true,
  142.         //  it hit a non-space and we are done. Else we have to pop a reader
  143.         //  and keep going.
  144.         //
  145.         if (fCurReader->getSpaces(toFill))
  146.             break;
  147.         // We wore that one out, so lets pop a reader and try again
  148.         if (!popReader())
  149.             break;
  150.     }
  151. }
  152. void ReaderMgr::getUpToCharOrWS(XMLBuffer& toFill, const XMLCh toCheck)
  153. {
  154.     // Reset the target buffer before we start
  155.     toFill.reset();
  156.     //
  157.     //  Ok, enter a loop where we ask the current reader to get chars until
  158.     //  it meets the criteria. It returns false if it came back due to eating
  159.     //  up all of its data. Else it returned because something matched, and
  160.     //  we are done.
  161.     //
  162.     while (true)
  163.     {
  164.         if (fCurReader->getUpToCharOrWS(toFill, toCheck))
  165.             break;
  166.         // We ate that one up, lets try to pop another. If not, break out
  167.         if (!popReader())
  168.             break;
  169.     }
  170. }
  171. XMLCh ReaderMgr::peekNextChar()
  172. {
  173.     XMLCh chRet;
  174.     if (fCurReader->peekNextChar(chRet))
  175.         return chRet;
  176.     //
  177.     //  Didn't get anything back so this reader is hosed. So lets move to
  178.     //  the next reader on the stack. If this fails, it will be because
  179.     //  its the end of the original file, and we just return zero.
  180.     //
  181.     if (!popReader())
  182.         return XMLCh(0);
  183.     // Else peek again and return the character
  184.     fCurReader->peekNextChar(chRet);
  185.     return chRet;
  186. }
  187. bool ReaderMgr::skippedChar(const XMLCh toCheck)
  188. {
  189.     while (true)
  190.     {
  191.         // If we get it, then just return true now
  192.         if (fCurReader->skippedChar(toCheck))
  193.             return true;
  194.         //
  195.         //  Check to see if we hit end of input on this reader. If so, then
  196.         //  lets pop and try again. Else, we failed. If we cannot pop another
  197.         //  then we failed.
  198.         //
  199.         if (!fCurReader->getNoMoreFlag())
  200.             break;
  201.         if (!popReader())
  202.             break;
  203.     }
  204.     return false;
  205. }
  206. bool ReaderMgr::skippedSpace()
  207. {
  208.     while (true)
  209.     {
  210.         // If we get it, then just return true now
  211.         if (fCurReader->skippedSpace())
  212.             return true;
  213.         //
  214.         //  Check to see if we hit end of input on this reader. If so, then
  215.         //  lets pop and try again. Else, we failed. If we cannot pop another
  216.         //  then we failed.
  217.         //
  218.         if (!fCurReader->getNoMoreFlag())
  219.             break;
  220.         if (!popReader())
  221.             break;
  222.     }
  223.     return false;
  224. }
  225. bool ReaderMgr::skipIfQuote(XMLCh& chGotten)
  226. {
  227.     while (true)
  228.     {
  229.         // If we get it, then just return true now
  230.         if (fCurReader->skipIfQuote(chGotten))
  231.             return true;
  232.         //
  233.         //  Check to see if we hit end of input on this reader. If so, then
  234.         //  lets pop and try again. Else, we failed. If we cannot pop another
  235.         //  then we failed.
  236.         //
  237.         if (!fCurReader->getNoMoreFlag())
  238.             break;
  239.         if (!popReader())
  240.             break;
  241.     }
  242.     return false;
  243. }
  244. bool ReaderMgr::skipPastSpaces()
  245. {
  246.     bool skippedSomething = false;
  247.     bool tmpFlag;
  248.     while (true)
  249.     {
  250.         //
  251.         //  Skip all the spaces in the current reader. If it returned because
  252.         //  it hit a non-space, break out. Else we have to pop another entity
  253.         //  and keep going.
  254.         //
  255.         if (fCurReader->skipSpaces(tmpFlag))
  256.             break;
  257.         if (tmpFlag)
  258.             skippedSomething = true;
  259.         // Try to pop another enitity. If we can't then we are done
  260.         if (!popReader())
  261.             break;
  262.     }
  263.     return (tmpFlag || skippedSomething);
  264. }
  265. void ReaderMgr::skipQuotedString(const XMLCh quoteCh)
  266. {
  267.     XMLCh nextCh;
  268.     while (true)
  269.     {
  270.         nextCh = getNextChar();
  271.         // If we get an end of file char, then return
  272.         if (!nextCh)
  273.             break;
  274.         // If we get the quote char, then break out
  275.         if (nextCh == quoteCh)
  276.             break;
  277.     }
  278. }
  279. XMLCh ReaderMgr::skipUntilIn(const XMLCh* const listToSkip)
  280. {
  281.     XMLCh nextCh;
  282.     while (true)
  283.     {
  284.         nextCh = peekNextChar();
  285.         if (!nextCh)
  286.             break;
  287.         if (XMLString::indexOf(listToSkip, nextCh) != -1)
  288.             break;
  289.         // Its one of ours so eat it
  290.         getNextChar();
  291.     }
  292.     return nextCh;
  293. }
  294. XMLCh ReaderMgr::skipUntilInOrWS(const XMLCh* const listToSkip)
  295. {
  296.     XMLCh nextCh;
  297.     while (true)
  298.     {
  299.         nextCh = peekNextChar();
  300.         if (!nextCh)
  301.             break;
  302.         if (XMLReader::isWhitespace(nextCh))
  303.             break;
  304.         if (XMLString::indexOf(listToSkip, nextCh) != -1)
  305.             break;
  306.         // Its one of ours, so eat it
  307.         getNextChar();
  308.     }
  309.     return nextCh;
  310. }
  311. // ---------------------------------------------------------------------------
  312. //  ReaderMgr: Control methods
  313. // ---------------------------------------------------------------------------
  314. //
  315. //  If the reader stack is empty, then there is only the original main XML
  316. //  entity left. If its empty, then we have no more input.
  317. //
  318. bool ReaderMgr::atEOF() const
  319. {
  320.     return fReaderStack->empty() && fCurReader->getNoMoreFlag();
  321. }
  322. //
  323. //  This method is called in the case of errors to clean up the stack when
  324. //  entities have been incorrectly left on the stack due to syntax errors.
  325. //  It just cleans back the stack, and sends no entity events.
  326. //
  327. void ReaderMgr::cleanStackBackTo(const unsigned int readerNum)
  328. {
  329.     //
  330.     //  Just start popping readers until we find the one with the indicated
  331.     //  reader number.
  332.     //
  333.     while (true)
  334.     {
  335.         if (fCurReader->getReaderNum() == readerNum)
  336.             break;
  337.         if (fReaderStack->empty())
  338.             ThrowXML(RuntimeException, XMLExcepts::RdrMgr_ReaderIdNotFound);
  339.         delete fCurReader;
  340.         fCurReader = fReaderStack->pop();
  341.         fCurEntity = fEntityStack->pop();
  342.     }
  343. }
  344. XMLReader* ReaderMgr::createReader( const   InputSource&        src
  345.                                     , const bool                xmlDecl
  346.                                     , const XMLReader::RefFrom  refFrom
  347.                                     , const XMLReader::Types    type
  348.                                     , const XMLReader::Sources  source)
  349. {
  350.     //
  351.     //  Ask the input source to create us an input stream. The particular
  352.     //  type of input source will know what kind to create.
  353.     //
  354.     BinInputStream* newStream = src.makeStream();
  355.     if (!newStream)
  356.         return 0;
  357.     //
  358.     //  Create a new reader and return it. If the source has an encoding that
  359.     //  it wants to force, then we call the constructor that does that.
  360.     //  Otherwise, we just call the one that provides the provisional encoding
  361.     //  to be possibly updated later by the encoding="" setting.
  362.     //
  363.     XMLReader* retVal = 0;
  364.     // XMLReader ctor invokes refreshRawBuffer() which calls 
  365.     // newStream->readBytes().
  366.     // This readBytes() may throw exception, which neither 
  367.     // refresRawBuffer(), nor XMLReader ctor catches. 
  368.     // We need to handle this exception to avoid leak on newStream.
  369.     try {
  370.         if (src.getEncoding())
  371.         {
  372.             retVal = new XMLReader
  373.                 (
  374.                 src.getPublicId()
  375.                 , src.getSystemId()
  376.                 , newStream
  377.                 , src.getEncoding()
  378.                 , refFrom
  379.                 , type
  380.                 , source
  381.                 );
  382.         }
  383.         else
  384.         {
  385.             retVal = new XMLReader
  386.                 (
  387.                 src.getPublicId()
  388.                 , src.getSystemId()
  389.                 , newStream
  390.                 , refFrom
  391.                 , type
  392.                 , source
  393.                 );
  394.         }
  395.     }
  396.     catch (...) //NetAccessorException&
  397.     {
  398.         delete newStream;
  399.         throw;
  400.     }
  401.     // Set the next available reader number on this reader
  402.     retVal->setReaderNum(fNextReaderNum++);
  403.     return retVal;
  404. }
  405. XMLReader* ReaderMgr::createReader( const   XMLCh* const        sysId
  406.                                     , const XMLCh* const        pubId
  407.                                     , const bool                xmlDecl
  408.                                     , const XMLReader::RefFrom  refFrom
  409.                                     , const XMLReader::Types    type
  410.                                     , const XMLReader::Sources  source
  411.                                     ,       InputSource*&       srcToFill)
  412. {
  413.     // Create a buffer for expanding the system id
  414.     XMLBuffer expSysId;
  415.     //
  416.     //  Allow the entity handler to expand the system id if they choose
  417.     //  to do so.
  418.     //
  419.     if (fEntityHandler)
  420.     {
  421.         if (!fEntityHandler->expandSystemId(sysId, expSysId))
  422.             expSysId.set(sysId);
  423.     }
  424.      else
  425.     {
  426.         expSysId.set(sysId);
  427.     }
  428.     // Call the entity resolver interface to get an input source
  429.     srcToFill = 0;
  430.     if (fEntityHandler)
  431.     {
  432.         srcToFill = fEntityHandler->resolveEntity
  433.         (
  434.             pubId
  435.             , expSysId.getRawBuffer()
  436.         );
  437.     }
  438.     //
  439.     //  If they didn't create a source via the entity resolver, then we
  440.     //  have to create one on our own.
  441.     //
  442.     if (!srcToFill)
  443.     {
  444.         LastExtEntityInfo lastInfo;
  445.         getLastExtEntityInfo(lastInfo);
  446.         try
  447.         {
  448.             XMLURL urlTmp(lastInfo.systemId, expSysId.getRawBuffer());
  449.             if (urlTmp.isRelative())
  450.             {
  451.                 ThrowXML
  452.                 (
  453.                     MalformedURLException
  454.                     , XMLExcepts::URL_NoProtocolPresent
  455.                 );
  456.             }
  457.             srcToFill = new URLInputSource(urlTmp);
  458.         }
  459.         catch(const MalformedURLException&)
  460.         {
  461.             // Its not a URL, so lets assume its a local file name.
  462.             srcToFill = new LocalFileInputSource
  463.             (
  464.                 lastInfo.systemId
  465.                 , expSysId.getRawBuffer()
  466.             );
  467.         }
  468.     }
  469.     // Put a janitor on the input source
  470.     Janitor<InputSource> janSrc(srcToFill);
  471.     //
  472.     //  Now call the other version with the input source that we have, and
  473.     //  return the resulting reader.
  474.     //
  475.     XMLReader* retVal = createReader
  476.     (
  477.         *srcToFill
  478.         , xmlDecl
  479.         , refFrom
  480.         , type
  481.         , source
  482.     );
  483.     // Either way, we can release the input source now
  484.     janSrc.orphan();
  485.     // If it failed for any reason, then return zero.
  486.     if (!retVal)
  487.         return 0;
  488.     // Give this reader the next available reader number and return it
  489.     retVal->setReaderNum(fNextReaderNum++);
  490.     return retVal;
  491. }
  492. XMLReader*
  493. ReaderMgr::createIntEntReader(  const   XMLCh* const        sysId
  494.                                 , const XMLReader::RefFrom  refFrom
  495.                                 , const XMLReader::Types    type
  496.                                 , const XMLCh* const        dataBuf
  497.                                 , const unsigned int        dataLen
  498.                                 , const bool                copyBuf)
  499. {
  500.     //
  501.     //  This one is easy, we just create an input stream for the data and
  502.     //  provide a few extra goodies.
  503.     //
  504.     //  NOTE: We use a special encoding string that will be recognized
  505.     //  as a 'do nothing' transcoder for the already internalized XMLCh
  506.     //  data that makes up an internal entity.
  507.     //
  508.     XMLReader* retVal = new XMLReader
  509.     (
  510.         sysId
  511.         , 0
  512.         , new BinMemInputStream
  513.           (
  514.             (const XMLByte*)dataBuf
  515.             , dataLen * sizeof(XMLCh)
  516.             , copyBuf ? BinMemInputStream::BufOpt_Copy
  517.                         : BinMemInputStream::BufOpt_Reference
  518.           )
  519.         , XMLUni::fgXMLChEncodingString
  520.         , refFrom
  521.         , type
  522.         , XMLReader::Source_Internal
  523.     );
  524.     // Set the reader number to the next available number
  525.     retVal->setReaderNum(fNextReaderNum++);
  526.     return retVal;
  527. }
  528. const XMLCh* ReaderMgr::getCurrentEncodingStr() const
  529. {
  530.     const XMLEntityDecl*    theEntity;
  531.     const XMLReader*        theReader = getLastExtEntity(theEntity);
  532.     return theReader->getEncodingStr();
  533. }
  534. const XMLEntityDecl* ReaderMgr::getCurrentEntity() const
  535. {
  536.     return fCurEntity;
  537. }
  538. XMLEntityDecl* ReaderMgr::getCurrentEntity()
  539. {
  540.     return fCurEntity;
  541. }
  542. const XMLReader* ReaderMgr::getCurrentReader() const
  543. {
  544.     return fCurReader;
  545. }
  546. XMLReader* ReaderMgr::getCurrentReader()
  547. {
  548.     return fCurReader;
  549. }
  550. unsigned int ReaderMgr::getReaderDepth() const
  551. {
  552.     // If the stack doesn't exist, its obviously zero
  553.     if (!fEntityStack)
  554.         return 0;
  555.     //
  556.     //  The return is the stack size, plus one if there is a current
  557.     //  reader. So if there is no current reader and none on the stack,
  558.     //  its zero, else its some non-zero value.
  559.     //
  560.     unsigned int retVal = fEntityStack->size();
  561.     if (fCurReader)
  562.         retVal++;
  563.     return retVal;
  564. }
  565. void ReaderMgr::getLastExtEntityInfo(LastExtEntityInfo& lastInfo) const
  566. {
  567.     //
  568.     //  If the reader stack never got created or we've not managed to open any
  569.     //  main entity yet, then we can't give this information.
  570.     //
  571.     if (!fReaderStack || !fCurReader)
  572.     {
  573.         lastInfo.systemId = XMLUni::fgZeroLenString;
  574.         lastInfo.publicId = XMLUni::fgZeroLenString;
  575.         lastInfo.lineNumber = 0;
  576.         lastInfo.colNumber = 0;
  577.         return;
  578.     }
  579.     // We have at least one entity so get the data
  580.     const XMLEntityDecl*    theEntity;
  581.     const XMLReader*        theReader = getLastExtEntity(theEntity);
  582.     // Fill in the info structure with the reader we found
  583.     lastInfo.systemId = theReader->getSystemId();
  584.     lastInfo.publicId = theReader->getPublicId();
  585.     lastInfo.lineNumber = theReader->getLineNumber();
  586.     lastInfo.colNumber = theReader->getColumnNumber();
  587. }
  588. bool ReaderMgr::isScanningPERefOutOfLiteral() const
  589. {
  590.     // If the current reader is not for an entity, then definitely not
  591.     if (!fCurEntity)
  592.         return false;
  593.     //
  594.     //  If this is a PE entity, and its not being expanded in a literal
  595.     //  then its true.
  596.     //
  597.     if ((fCurReader->getType() == XMLReader::Type_PE)
  598.     &&  (fCurReader->getRefFrom() == XMLReader::RefFrom_NonLiteral))
  599.     {
  600.         return true;
  601.     }
  602.     return false;
  603. }
  604. bool ReaderMgr::pushReader(         XMLReader* const        reader
  605.                             ,       XMLEntityDecl* const    entity)
  606. {
  607.     //
  608.     //  First, if an entity was passed, we have to confirm that this entity
  609.     //  is not already on the entity stack. If so, then this is a recursive
  610.     //  entity expansion, so we issue an error and refuse to put the reader
  611.     //  on the stack.
  612.     //
  613.     //  If there is no entity passed, then its not an entity being pushed, so
  614.     //  nothing to do. If there is no entity stack yet, then of coures it
  615.     //  cannot already be there.
  616.     //
  617.     if (entity && fEntityStack)
  618.     {
  619.         const unsigned int count = fEntityStack->size();
  620.         const XMLCh* const theName = entity->getName();
  621.         for (unsigned int index = 0; index < count; index++)
  622.         {
  623.             const XMLEntityDecl* curDecl = fEntityStack->elementAt(index);
  624.             if (curDecl)
  625.             {
  626.                 if (!XMLString::compareString(theName, curDecl->getName()))
  627.                 {
  628.                     // Oops, already there so delete reader and return
  629.                     delete reader;
  630.                     return false;
  631.                 }
  632.             }
  633.         }
  634.     }
  635.     //
  636.     //  Fault in the reader stack. Give it an initial capacity of 16, and
  637.     //  tell it it does own its elements.
  638.     //
  639.     if (!fReaderStack)
  640.         fReaderStack = new RefStackOf<XMLReader>(16, true);
  641.     // And the entity stack, which does not own its elements
  642.     if (!fEntityStack)
  643.         fEntityStack = new RefStackOf<XMLEntityDecl>(16, false);
  644.     //
  645.     //  Push the current reader and entity onto their respective stacks.
  646.     //  Note that the the current entity can be null if the current reader
  647.     //  is not for an entity.
  648.     //
  649.     if (fCurReader)
  650.     {
  651.         fReaderStack->push(fCurReader);
  652.         fEntityStack->push(fCurEntity);
  653.     }
  654.     //
  655.     //  Make the passed reader and entity the current top of stack. The
  656.     //  passed entity can (and often is) null.
  657.     //
  658.     fCurReader = reader;
  659.     fCurEntity = entity;
  660.     return true;
  661. }
  662. void ReaderMgr::reset()
  663. {
  664.     // Reset all of the flags
  665.     fThrowEOE = false;
  666.     // Delete the current reader and flush the reader stack
  667.     delete fCurReader;
  668.     fCurReader = 0;
  669.     if (fReaderStack)
  670.         fReaderStack->removeAllElements();
  671.     //
  672.     //  And do the same for the entity stack, but don't delete the current
  673.     //  entity (if any) since we don't own them.
  674.     //
  675.     fCurEntity = 0;
  676.     if (fEntityStack)
  677.         fEntityStack->removeAllElements();
  678. }
  679. // ---------------------------------------------------------------------------
  680. //  ReaderMgr: Implement the SAX Locator interface
  681. // ---------------------------------------------------------------------------
  682. const XMLCh* ReaderMgr::getPublicId() const
  683. {
  684.     if (!fReaderStack && !fCurReader)
  685.         return XMLUni::fgZeroLenString;
  686.     const XMLEntityDecl* theEntity;
  687.     return getLastExtEntity(theEntity)->getPublicId();
  688. }
  689. const XMLCh* ReaderMgr::getSystemId() const
  690. {
  691.     if (!fReaderStack && !fCurReader)
  692.         return XMLUni::fgZeroLenString;
  693.     const XMLEntityDecl* theEntity;
  694.     return getLastExtEntity(theEntity)->getSystemId();
  695. }
  696. int ReaderMgr::getColumnNumber() const
  697. {
  698.     if (!fReaderStack && !fCurReader)
  699.         return 0;
  700.     const XMLEntityDecl* theEntity;
  701.     return getLastExtEntity(theEntity)->getColumnNumber();
  702. }
  703. int ReaderMgr::getLineNumber() const
  704. {
  705.     if (!fReaderStack && !fCurReader)
  706.         return 0;
  707.     const XMLEntityDecl* theEntity;
  708.     return getLastExtEntity(theEntity)->getLineNumber();
  709. }
  710. // ---------------------------------------------------------------------------
  711. //  ReaderMgr: Private helper methods
  712. // ---------------------------------------------------------------------------
  713. const XMLReader*
  714. ReaderMgr::getLastExtEntity(const XMLEntityDecl*& itsEntity) const
  715. {
  716.     //
  717.     //  Scan down the reader stack until we find a reader for an entity that
  718.     //  is external. First check that there is anything in the stack at all,
  719.     //  in which case the current reader is the main file and that's the one
  720.     //  that we want.
  721.     //
  722.     const XMLReader* theReader = fCurReader;
  723.     //
  724.     //  If there is a current entity and it is not an external entity, then
  725.     //  search the stack; else, keep the reader that we've got since its
  726.     //  either an external entity reader or the main file reader.
  727.     //
  728.     const XMLEntityDecl* curEntity = fCurEntity;
  729.     if (curEntity && !curEntity->isExternal())
  730.     {
  731.         unsigned int index = fReaderStack->size();
  732.         if (index)
  733.         {
  734.             while (true)
  735.             {
  736.                 // Move down to the previous element and get a pointer to it
  737.                 index--;
  738.                 curEntity = fEntityStack->elementAt(index);
  739.                 //
  740.                 //  If its null or its an external entity, then this reader
  741.                 //  is what we want, so break out with that one.
  742.                 //
  743.                 if (!curEntity)
  744.                 {
  745.                     theReader = fReaderStack->elementAt(index);
  746.                     break;
  747.                 }
  748.                  else if (curEntity->isExternal())
  749.                 {
  750.                     theReader = fReaderStack->elementAt(index);
  751.                     break;
  752.                 }
  753.                 // We hit the end, so leave the main file reader as the one
  754.                 if (!index)
  755.                     break;
  756.             }
  757.         }
  758.     }
  759.     itsEntity = curEntity;
  760.     return theReader;
  761. }
  762. bool ReaderMgr::popReader()
  763. {
  764.     //
  765.     //  We didn't get any more, so try to pop off a reader. If the reader
  766.     //  stack is empty, then we are at the end, so return false.
  767.     //
  768.     if (fReaderStack->empty())
  769.         return false;
  770.     //
  771.     //  Remember the current entity, before we pop off a new one. We might
  772.     //  need this to throw the end of entity exception at the end.
  773.     //
  774.     XMLEntityDecl* prevEntity = fCurEntity;
  775.     const bool prevReaderThrowAtEnd = fCurReader->getThrowAtEnd();
  776.     const unsigned int readerNum = fCurReader->getReaderNum();
  777.     //
  778.     //  Delete the current reader and pop a new reader and entity off
  779.     //  the stacks.
  780.     //
  781.     delete fCurReader;
  782.     fCurReader = fReaderStack->pop();
  783.     fCurEntity = fEntityStack->pop();
  784.     //
  785.     //  If there was a previous entity, and either the fThrowEOE flag is set
  786.     //  or reader was marked as such, then throw an end of entity.
  787.     //
  788.     if (prevEntity && fThrowEOE || prevReaderThrowAtEnd)
  789.         throw EndOfEntityException(prevEntity, readerNum);
  790.     while (true)
  791.     {
  792.         //
  793.         //  They don't want us to throw, so lets just return with a new
  794.         //  reader. Here we have to do a loop because we might have multiple
  795.         //  readers on these stack that are empty (i.e. the last char in them
  796.         //  was the ';' at the end of the entity ref that caused the next
  797.         //  entity to be pushed.
  798.         //
  799.         //  So we loop until we find a non-empty reader, or hit the main
  800.         //  file entity. If we find one with some chars available, then break
  801.         //  out and take that one.
  802.         //
  803.         if (fCurReader->charsLeftInBuffer())
  804.             break;
  805.         fCurReader->refreshCharBuffer();
  806.         if (fCurReader->charsLeftInBuffer())
  807.             break;
  808.         //
  809.         //  The current one is hosed. So, if the reader stack is empty we
  810.         //  are dead meat and can give up now.
  811.         //
  812.         if (fReaderStack->empty())
  813.             return false;
  814.         // Else pop again and try it one more time
  815.         delete fCurReader;
  816.         fCurReader = fReaderStack->pop();
  817.         fCurEntity = fEntityStack->pop();
  818.     }
  819.     return true;
  820. }