You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by kn...@apache.org on 2002/07/11 20:22:14 UTC

cvs commit: xml-xerces/c/src/xercesc/internal XMLScanner2.cpp XMLScanner.hpp XMLScanner.cpp

knoaman     2002/07/11 11:22:14

  Modified:    c/src/xercesc/internal XMLScanner2.cpp XMLScanner.hpp
                        XMLScanner.cpp
  Log:
  Grammar caching/preparsing - initial implementation.
  
  Revision  Changes    Path
  1.12      +167 -91   xml-xerces/c/src/xercesc/internal/XMLScanner2.cpp
  
  Index: XMLScanner2.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/xercesc/internal/XMLScanner2.cpp,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- XMLScanner2.cpp	17 Jun 2002 18:09:20 -0000	1.11
  +++ XMLScanner2.cpp	11 Jul 2002 18:22:13 -0000	1.12
  @@ -532,6 +532,16 @@
                   if ((defType == XMLAttDef::Default)
                   ||  (defType == XMLAttDef::Fixed))
                   {
  +                    // Let the validator pass judgement on the attribute value
  +                    if (fValidate)
  +                    {
  +                        fValidator->validateAttrValue
  +                        (
  +                            &curDef
  +                            , curDef.getValue()
  +                        );
  +                    }
  +
                       XMLAttr* curAtt;
                       if (retCount >= curAttListSize)
                       {
  @@ -892,61 +902,33 @@
       //  This call implicitly tells us that we are going to reuse the scanner
       //  if it was previously used. So tell the validator to reset itself.
       //
  -    //  But, if the fReuseGrammar flag is set, then don't reset it.
  +    //  But, if the fUseCacheGrammar flag is set, then don't reset it.
       //
       //  NOTE:   The ReaderMgr is flushed on the way out, because that is
       //          required to insure that files are closed.
       //
  -    if (!fReuseGrammar) {
  -        fGrammarResolver->reset();
  -
  -        resetEntityDeclPool();
  -        if (fDoNamespaces)
  -            resetURIStringPool();
  +    fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar);
  +    fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar);
   
  -        // create a default grammar first
  -        fGrammar = new DTDGrammar();
  +    fDTDGrammar = new DTDGrammar();
  +    fGrammarResolver->putGrammar(XMLUni::fgDTDEntityString, fDTDGrammar);
  +    fGrammar = fDTDGrammar;
  +    fGrammarType = fGrammar->getGrammarType();
  +    fRootGrammar = 0;
   
  -        //
  -        if (fValidatorFromUser) {
  -            if (fValidator->handlesDTD())
  -                fValidator->setGrammar(fGrammar);
  -        }
  -        else {
  -            // set fValidator as fDTDValidator
  -            fValidator = fDTDValidator;
  +    if (fValidatorFromUser) {
  +        if (fValidator->handlesDTD())
               fValidator->setGrammar(fGrammar);
  -        }
  -
  -        fGrammarType = fGrammar->getGrammarType();
  -        fGrammarResolver->putGrammar(XMLUni::fgZeroLenString, fGrammar);
  -
  -        if (fValScheme == Val_Auto) {
  -            fValidate = false;
  -        }
       }
       else {
  -        // reusing grammar, thus the fGrammar must pre-exist already
  -        // make sure the validator handles this reuse grammar type
  -        if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) {
  -            if (fValidatorFromUser)
  -                ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  -            else {
  -                fValidator = fSchemaValidator;
  -            }
  -        }
  -        else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) {
  -            if (fValidatorFromUser)
  -                ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  -            else {
  -                fValidator = fDTDValidator;
  -            }
  -        }
  -
  -        if (!fValidator->getGrammar())
  -            fValidator->setGrammar(fGrammar);
  +        // set fValidator as fDTDValidator
  +        fValidator = fDTDValidator;
  +        fValidator->setGrammar(fGrammar);
  +    }
  + 
  +    if (fValScheme == Val_Auto) {
  +        fValidate = false;
       }
  -
   
       //
       //  And for all installed handlers, send reset events. This gives them
  @@ -1379,12 +1361,10 @@
                   const XMLCh* valuePtr = curPair->getValue();
                   const XMLCh* suffPtr = attName.getLocalPart();
   
  -                if (!fReuseGrammar) {
  -                    if (!XMLString::compareString(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCACTION))
  -                        parseSchemaLocation(valuePtr);
  -                    else if (!XMLString::compareString(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCACTION))
  -                        resolveSchemaGrammar(valuePtr, XMLUni::fgZeroLenString);
  -                }
  +                if (!XMLString::compareString(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCACTION))
  +                    parseSchemaLocation(valuePtr);
  +                else if (!XMLString::compareString(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCACTION))
  +                    resolveSchemaGrammar(valuePtr, XMLUni::fgZeroLenString);
   
                   if (!XMLString::compareString(suffPtr, SchemaSymbols::fgXSI_TYPE)) {
                           fXsiType.set(valuePtr);
  @@ -1547,7 +1527,7 @@
                       }
   
                       grammar = new SchemaGrammar();
  -                    TraverseSchema traverseSchema(root, fURIStringPool, (SchemaGrammar*) grammar, fGrammarResolver, this, fValidator, srcToFill->getSystemId(), fEntityHandler, fErrorReporter);
  +                    TraverseSchema traverseSchema(root, fURIStringPool, (SchemaGrammar*) grammar, fGrammarResolver, this, srcToFill->getSystemId(), fEntityHandler, fErrorReporter);
   
                       if (fGrammarType == Grammar::DTDGrammarType) {
                           fGrammar = grammar;
  @@ -1555,9 +1535,9 @@
                           fValidator->setGrammar(fGrammar);
                       }
   
  -                    if (!fReuseGrammar && fValidate) {
  +                    if (fValidate) {
                           //  validate the Schema scan so far
  -                        fValidator->preContentValidation(fReuseGrammar);
  +                        fValidator->preContentValidation(false);
                       }
                   }
               }
  @@ -1593,6 +1573,135 @@
       }
   }
   
  +InputSource* XMLScanner::resolveSystemId(const XMLCh* const sysId)
  +{
  +    // Create a buffer for expanding the system id
  +    XMLBufBid bbSys(&fBufMgr);
  +    XMLBuffer& expSysId = bbSys.getBuffer();
  +
  +    //
  +    //  Allow the entity handler to expand the system id if they choose
  +    //  to do so.
  +    //
  +    InputSource* srcToFill = 0;
  +    if (fEntityHandler)
  +    {
  +        if (!fEntityHandler->expandSystemId(sysId, expSysId))
  +            expSysId.set(sysId);
  +
  +        srcToFill = fEntityHandler->resolveEntity( XMLUni::fgZeroLenString
  +                                                 , expSysId.getRawBuffer());
  +    }
  +    else
  +    {
  +        expSysId.set(sysId);
  +    }
  +
  +    //
  +    //  If they didn't create a source via the entity handler, then we
  +    //  have to create one on our own.
  +    //
  +    if (!srcToFill)
  +    {
  +        ReaderMgr::LastExtEntityInfo lastInfo;
  +        fReaderMgr.getLastExtEntityInfo(lastInfo);
  +
  +        try
  +        {
  +            XMLURL urlTmp(lastInfo.systemId, expSysId.getRawBuffer());
  +            if (urlTmp.isRelative())
  +            {
  +                ThrowXML
  +                (
  +                    MalformedURLException
  +                    , XMLExcepts::URL_NoProtocolPresent
  +                );
  +            }
  +            srcToFill = new URLInputSource(urlTmp);
  +        }
  +
  +        catch(const MalformedURLException&)
  +        {
  +            // Its not a URL, so lets assume its a local file name.
  +            srcToFill = new LocalFileInputSource
  +            (
  +                lastInfo.systemId
  +                , expSysId.getRawBuffer()
  +            );
  +        }
  +    }
  +
  +    return srcToFill;
  +}
  +
  +
  +// ---------------------------------------------------------------------------
  +//  XMLScanner: Private grammar preparsing methods
  +// ---------------------------------------------------------------------------
  +Grammar* XMLScanner::loadXMLSchemaGrammar(const InputSource& src,
  +                                          const bool toCache)
  +{
  +   // Reset the validators
  +    fSchemaValidator->reset();
  +    if (fValidatorFromUser)
  +        fValidator->reset();
  +
  +    if (!fValidator->handlesSchema()) {
  +        if (fValidatorFromUser && fValidate)
  +            ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  +        else {
  +            fValidator = fSchemaValidator;
  +        }
  +    }
  +
  +    XSDDOMParser parser;
  +
  +    parser.setValidationScheme(XercesDOMParser::Val_Never);
  +    parser.setDoNamespaces(true);
  +    parser.setUserEntityHandler(fEntityHandler);
  +    parser.setUserErrorReporter(fErrorReporter);
  +
  +    // Should just issue warning if the schema is not found
  +    const bool flag = src.getIssueFatalErrorIfNotFound();
  +    ((InputSource&) src).setIssueFatalErrorIfNotFound(false);
  +
  +    parser.parse(src);
  +
  +    // Reset the InputSource
  +    ((InputSource&) src).setIssueFatalErrorIfNotFound(flag);
  +
  +    if (parser.getSawFatal() && fExitOnFirstFatal)
  +        emitError(XMLErrs::SchemaScanFatalError);
  +
  +    DOMDocument* document = parser.getDocument(); //Our Grammar
  +
  +    if (document != 0) {
  +
  +        DOMElement* root = document->getDocumentElement();// This is what we pass to TraverserSchema
  +        if (root != 0)
  +        {
  +            SchemaGrammar* grammar = new SchemaGrammar();
  +            TraverseSchema traverseSchema(root, fURIStringPool, (SchemaGrammar*) grammar, fGrammarResolver, this, src.getSystemId(), fEntityHandler, fErrorReporter);
  +
  +            if (fValidate) {
  +                //  validate the Schema scan so far
  +                fValidator->setGrammar(grammar);
  +                fValidator->preContentValidation(false, true);
  +            }
  +
  +            if (toCache) {
  +                fGrammarResolver->cacheGrammars();
  +            }
  +
  +            return grammar;
  +        }
  +    }
  +
  +    return 0;
  +}
  +
  +
  +
   // ---------------------------------------------------------------------------
   //  XMLScanner: Private parsing methods
   // ---------------------------------------------------------------------------
  @@ -2759,7 +2868,7 @@
           emitError(XMLErrs::PartialMarkupInEntity);
   
       // Look up the name in the general entity pool
  -    XMLEntityDecl* decl = fEntityDeclPool->getByKey(bbName.getRawBuffer());
  +    XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(bbName.getRawBuffer());
   
       // If it does not exist, then obviously an error
       if (!decl)
  @@ -2915,47 +3024,14 @@
       return toFill.getLen();
   }
   
  -bool XMLScanner::switchGrammar(unsigned int newGrammarNameSpaceIndex)
  -{
  -    XMLBufBid bbURI(&fBufMgr);
  -    XMLBuffer& bufURI = bbURI.getBuffer();
  -    getURIText(newGrammarNameSpaceIndex, bufURI);
  -    Grammar* tempGrammar = fGrammarResolver->getGrammar(bufURI.getRawBuffer());
  -    if (!tempGrammar) {
  -        // This is a case where namespaces is on with a DTD grammar.
  -        tempGrammar = fGrammarResolver->getGrammar(XMLUni::fgZeroLenString);
  -    }
  -    if (!tempGrammar)
  -        return false;
  -    else {
  -        fGrammar = tempGrammar;
  -        fGrammarType = fGrammar->getGrammarType();
  -        if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) {
  -            if (fValidatorFromUser)
  -                ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  -            else {
  -                fValidator = fSchemaValidator;
  -            }
  -        }
  -        else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) {
  -            if (fValidatorFromUser)
  -                ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  -            else {
  -                fValidator = fDTDValidator;
  -            }
  -        }
  -
  -        fValidator->setGrammar(fGrammar);
  -        return true;
  -    }
  -}
   
   bool XMLScanner::switchGrammar(const XMLCh* const newGrammarNameSpace)
   {
       Grammar* tempGrammar = fGrammarResolver->getGrammar(newGrammarNameSpace);
  +
       if (!tempGrammar) {
           // This is a case where namespaces is on with a DTD grammar.
  -        tempGrammar = fGrammarResolver->getGrammar(XMLUni::fgZeroLenString);
  +        tempGrammar = fDTDGrammar;
       }
       if (!tempGrammar)
           return false;
  
  
  
  1.8       +87 -51    xml-xerces/c/src/xercesc/internal/XMLScanner.hpp
  
  Index: XMLScanner.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/xercesc/internal/XMLScanner.hpp,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- XMLScanner.hpp	17 Jun 2002 16:13:01 -0000	1.7
  +++ XMLScanner.hpp	11 Jul 2002 18:22:13 -0000	1.8
  @@ -56,6 +56,9 @@
   
   /*
    * $Log$
  + * Revision 1.8  2002/07/11 18:22:13  knoaman
  + * Grammar caching/preparsing - initial implementation.
  + *
    * Revision 1.7  2002/06/17 16:13:01  tng
    * DOM L3: Add the flag fNormalizeData so that datatype normalization defined by schema is done only if asked.
    *
  @@ -389,16 +392,6 @@
       const XMLValidator* getValidator() const;
       XMLValidator* getValidator();
       int getErrorCount();
  -    const DTDEntityDecl* getEntityDecl
  -    (
  -        const   XMLCh* const    entName
  -    )   const;
  -
  -    DTDEntityDecl* getEntityDecl
  -    (
  -        const   XMLCh* const    entName
  -    );
  -    NameIdPoolEnumerator<DTDEntityDecl> getEntityEnumerator() const;
       NameIdPool<DTDEntityDecl>* getEntityDeclPool();
       const NameIdPool<DTDEntityDecl>* getEntityDeclPool() const;
       const XMLStringPool* getURIStringPool() const;
  @@ -408,6 +401,9 @@
       XMLCh* getExternalNoNamespaceSchemaLocation() const;
       bool getLoadExternalDTD() const;
       bool getNormalizeData() const;
  +    bool isCachingGrammarFromParse() const;
  +    bool isUsingCachedGrammarInParse() const;
  +    Grammar* getRootGrammar() const;
   
       // -----------------------------------------------------------------------
       //  Getter methods
  @@ -479,6 +475,8 @@
           , const ElemStack::MapModes mode
       );
   
  +    Grammar* getGrammar(const XMLCh* const nameSpaceKey);
  +
       /* tell if the validator comes from user */
       bool isValidatorFromUser();
   
  @@ -499,6 +497,8 @@
       void setDoSchema(const bool doSchema);
       void setValidationSchemaFullChecking(const bool schemaFullChecking);
       void setHasNoDTD(const bool hasNoDTD);
  +    void cacheGrammarFromParse(const bool newValue);
  +    void useCachedGrammarInParse(const bool newValue);
       void setRootElemName(XMLCh* rootElemName);
       void setExternalSchemaLocation(const XMLCh* const schemaLocation);
       void setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation);
  @@ -529,36 +529,30 @@
       void scanDocument
       (
           const   InputSource&    src
  -        , const bool            reuseGrammar = false
       );
       void scanDocument
       (
           const   XMLCh* const    systemId
  -        , const bool            reuseGrammar = false
       );
       void scanDocument
       (
           const   char* const     systemId
  -        , const bool            reuseGrammar = false
       );
   
       bool scanFirst
       (
           const   InputSource&    src
           ,       XMLPScanToken&  toFill
  -        , const bool            reuseGrammar = false
       );
       bool scanFirst
       (
           const   XMLCh* const    systemId
           ,       XMLPScanToken&  toFill
  -        , const bool            reuseGrammar = false
       );
       bool scanFirst
       (
           const   char* const     systemId
           ,       XMLPScanToken&  toFill
  -        , const bool            reuseGrammar = false
       );
   
       bool scanNext(XMLPScanToken& toFill);
  @@ -568,6 +562,33 @@
       bool checkXMLDecl(bool startWithAngle);
   
       // -----------------------------------------------------------------------
  +    //  Grammar preparsing methods
  +    // -----------------------------------------------------------------------
  +    Grammar* loadGrammar
  +    (
  +        const   InputSource&    src
  +        , const short           grammarType
  +        , const bool            toCache = false
  +    );
  +    Grammar* loadGrammar
  +    (
  +        const   XMLCh* const    systemId
  +        , const short           grammarType
  +        , const bool            toCache = false
  +    );
  +    Grammar* loadGrammar
  +    (
  +        const   char* const     systemId
  +        , const short           grammarType
  +        , const bool            toCache = false
  +    );
  +
  +    // -----------------------------------------------------------------------
  +    //  Reset pool of cached grammars
  +    // -----------------------------------------------------------------------
  +    void resetCachedGrammarPool();
  +
  +    // -----------------------------------------------------------------------
       //  Notification that lazy data has been deleted
       // -----------------------------------------------------------------------
   	static void reinitScannerMutex();
  @@ -588,8 +609,8 @@
       // -----------------------------------------------------------------------
       void commonInit();
       void initValidator(XMLValidator* theValidator);
  -    void resetEntityDeclPool();
       void resetURIStringPool();
  +    InputSource* resolveSystemId(const XMLCh* const sysId); // return owned by caller
   
   
       // -----------------------------------------------------------------------
  @@ -642,7 +663,6 @@
       void scanRawAttrListforNameSpaces(const RefVectorOf<KVStringPair>* theRawAttrList, int attCount);
       void parseSchemaLocation(const XMLCh* const schemaLocationStr);
       void resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri);
  -    bool switchGrammar(unsigned int newGrammarNameSpaceIndex);
       bool switchGrammar(const XMLCh* const newGrammarNameSpace);
       bool laxElementValidation(QName* element, ContentLeafNameTypeVector* cv,
                                 const XMLContentModel* const cm,
  @@ -710,6 +730,12 @@
       void activateSelectorFor(IdentityConstraint* const ic);
   
       // -----------------------------------------------------------------------
  +    //  Grammar preparsing methods
  +    // -----------------------------------------------------------------------
  +    Grammar* loadXMLSchemaGrammar(const InputSource& src, const bool toCache = false);
  +    Grammar* loadDTDGrammar(const InputSource& src, const bool toCache = false);
  +
  +    // -----------------------------------------------------------------------
       //  Data members
       //
       //  fAttrList
  @@ -782,13 +808,6 @@
       //      methods to do specialized checking for chars, sequences of chars,
       //      skipping chars, etc...
       //
  -    //  fReuseGrammar
  -    //      This flag is set on a per-scan basis. So its provided in the
  -    //      scanDocument() and scanFirst() methods, and applies for that
  -    //      one pass. It indicates if the Grammar should be reused or not.
  -    //      If so, then all the Grammar will be ignored.
  -    //      There cannot be any internal subset.
  -    //
       //  fScannerId
       //  fSequenceId
       //      These are used for progressive parsing, to make sure that the
  @@ -878,20 +897,21 @@
       //      wildcard validation
       //
       //  fGrammarResolver
  -    //      Grammar Pool that stores all the Grammar
  +    //      Grammar Pool that stores all the grammars. Key is namespace for
  +    //      schema and system id for external DTD. When caching a grammar, if
  +    //      a grammar is already in the pool, it will be replaced with the
  +    //      new parsed one.
       //
       //  fGrammar
       //      Current Grammar used by the Scanner and Validator
       //
  +    //  fRootGrammar
  +    //      The grammar where the root element is declared.
  +    //
       //  fGrammarType
       //      Current Grammar Type.  Store this value instead of calling getGrammarType
       //      all the time for faster performance.
       //
  -    //  fEntityDeclPool
  -    //      This is a pool of EntityDecl objects, which contains all of the
  -    //      general entities that are declared in the DTD subsets, plus the
  -    //      default entities (such as &gt; &lt; ...) defined by the XML Standard.
  -    //
       //  fURIStringPool
       //      This is a pool for URIs with unique ids assigned. We use a standard
       //      string pool class.  This pool is going to be shared by all Grammar.
  @@ -935,7 +955,6 @@
       bool                        fExitOnFirstFatal;
       bool                        fValidationConstraintFatal;
       bool                        fInException;
  -    bool                        fReuseGrammar;
       bool                        fStandalone;
       bool                        fHasNoDTD;
       bool                        fValidate;
  @@ -943,6 +962,8 @@
       bool                        fDoSchema;
       bool                        fSchemaFullChecking;
       bool                        fSeeXsi;
  +    bool                        fToCacheGrammar;
  +    bool                        fUseCachedGrammar;
       int                         fErrorCount;
       unsigned int                fEmptyNamespaceId;
       unsigned int                fUnknownNamespaceId;
  @@ -977,8 +998,9 @@
       XMLBuffer                   fURIBuf;
       GrammarResolver*            fGrammarResolver;
       Grammar*                    fGrammar;
  +    Grammar*                    fRootGrammar;
  +    DTDGrammar*                 fDTDGrammar;
       Grammar::GrammarType        fGrammarType;
  -    NameIdPool<DTDEntityDecl>*  fEntityDeclPool;
       XMLStringPool*              fURIStringPool;
       XPathMatcherStack*          fMatcherStack;
       ValueStoreCache*            fValueStoreCache;
  @@ -1140,30 +1162,14 @@
       return fXMLNSNamespaceId;
   }
   
  -inline NameIdPoolEnumerator<DTDEntityDecl>
  -XMLScanner::getEntityEnumerator() const
  -{
  -    return NameIdPoolEnumerator<DTDEntityDecl>(fEntityDeclPool);
  -}
  -
  -inline const DTDEntityDecl* XMLScanner::getEntityDecl(const  XMLCh* const    entName) const
  -{
  -    return fEntityDeclPool->getByKey(entName);
  -}
  -
  -inline DTDEntityDecl* XMLScanner::getEntityDecl(const XMLCh* const entName)
  -{
  -    return fEntityDeclPool->getByKey(entName);
  -}
  -
   inline NameIdPool<DTDEntityDecl>* XMLScanner::getEntityDeclPool()
   {
  -    return fEntityDeclPool;
  +    return fDTDGrammar->getEntityDeclPool();
   }
   
   inline const NameIdPool<DTDEntityDecl>* XMLScanner::getEntityDeclPool() const
   {
  -    return fEntityDeclPool;
  +    return fDTDGrammar->getEntityDeclPool();
   }
   
   inline const XMLStringPool* XMLScanner::getURIStringPool() const
  @@ -1201,6 +1207,26 @@
       return fNormalizeData;
   }
   
  +inline bool XMLScanner::isCachingGrammarFromParse() const
  +{
  +    return fToCacheGrammar;
  +}
  +
  +inline bool XMLScanner::isUsingCachedGrammarInParse() const
  +{
  +    return fUseCachedGrammar;
  +}
  +
  +inline Grammar* XMLScanner::getRootGrammar() const
  +{
  +    return fRootGrammar;
  +}
  +
  +inline Grammar* XMLScanner::getGrammar(const XMLCh* const nameSpaceKey)
  +{
  +    return fGrammarResolver->getGrammar(nameSpaceKey);
  +}
  +
   // ---------------------------------------------------------------------------
   //  XMLScanner: Setter methods
   // ---------------------------------------------------------------------------
  @@ -1328,6 +1354,16 @@
   inline void XMLScanner::setNormalizeData(const bool normalizeData)
   {
       fNormalizeData = normalizeData;
  +}
  +
  +inline void XMLScanner::cacheGrammarFromParse(const bool newValue)
  +{
  +    fToCacheGrammar = newValue;
  +}
  +
  +inline void XMLScanner::useCachedGrammarInParse(const bool newValue)
  +{
  +    fUseCachedGrammar = newValue;
   }
   
   
  
  
  
  1.14      +417 -150  xml-xerces/c/src/xercesc/internal/XMLScanner.cpp
  
  Index: XMLScanner.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/xercesc/internal/XMLScanner.cpp,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- XMLScanner.cpp	5 Jul 2002 18:42:44 -0000	1.13
  +++ XMLScanner.cpp	11 Jul 2002 18:22:13 -0000	1.14
  @@ -181,7 +181,6 @@
       , fExitOnFirstFatal(true)
       , fValidationConstraintFatal(false)
       , fInException(false)
  -    , fReuseGrammar(false)
       , fStandalone(false)
       , fHasNoDTD(true)
       , fValidate(false)
  @@ -189,6 +188,8 @@
       , fDoSchema(false)
       , fSchemaFullChecking(false)
       , fSeeXsi(false)
  +    , fToCacheGrammar(false)
  +    , fUseCachedGrammar(false)
       , fErrorCount(0)
       , fEmptyNamespaceId(0)
       , fUnknownNamespaceId(0)
  @@ -213,7 +214,8 @@
       , fValScheme(Val_Never)
       , fGrammarResolver(0)
       , fGrammar(0)
  -    , fEntityDeclPool(0)
  +    , fRootGrammar(0)
  +    , fDTDGrammar(0)
       , fURIStringPool(0)
       , fMatcherStack(0)
       , fValueStoreCache(0)
  @@ -246,7 +248,6 @@
       , fExitOnFirstFatal(true)
       , fValidationConstraintFatal(false)
       , fInException(false)
  -    , fReuseGrammar(false)
       , fStandalone(false)
       , fHasNoDTD(true)
       , fValidate(false)
  @@ -254,6 +255,8 @@
       , fDoSchema(false)
       , fSchemaFullChecking(false)
       , fSeeXsi(false)
  +    , fToCacheGrammar(false)
  +    , fUseCachedGrammar(false)
       , fErrorCount(0)
       , fEmptyNamespaceId(0)
       , fUnknownNamespaceId(0)
  @@ -278,7 +281,8 @@
       , fValScheme(Val_Never)
       , fGrammarResolver(0)
       , fGrammar(0)
  -    , fEntityDeclPool(0)
  +    , fRootGrammar(0)
  +    , fDTDGrammar(0)
       , fURIStringPool(0)
       , fMatcherStack(0)
       , fValueStoreCache(0)
  @@ -313,8 +317,6 @@
       delete fDTDValidator;
       delete fSchemaValidator;
   
  -    delete fEntityDeclPool;
  -
       //fGrammarResolver will delete the fGrammar as well
       delete fGrammarResolver;
   
  @@ -333,8 +335,7 @@
   // ---------------------------------------------------------------------------
   //  XMLScanner: Main entry point to scan a document
   // ---------------------------------------------------------------------------
  -void XMLScanner::scanDocument(  const   XMLCh* const    systemId
  -                                , const bool            reuseGrammar)
  +void XMLScanner::scanDocument(  const   XMLCh* const    systemId)
   {
       //
       //  First we try to parse it as a URL. If that fails, we assume its
  @@ -403,20 +404,19 @@
       }
   
       Janitor<InputSource> janSrc(srcToUse);
  -    scanDocument(*srcToUse, reuseGrammar);
  +    scanDocument(*srcToUse);
   }
   
  -void XMLScanner::scanDocument(  const   char* const systemId
  -                                , const bool        reuseGrammar)
  +void XMLScanner::scanDocument(  const   char* const systemId)
   {
       // We just delegate this to the XMLCh version after transcoding
       XMLCh* tmpBuf = XMLString::transcode(systemId);
       ArrayJanitor<XMLCh> janBuf(tmpBuf);
  -    scanDocument(tmpBuf, reuseGrammar);
  +    scanDocument(tmpBuf);
   }
   
   
  -void XMLScanner::scanDocument(const InputSource& src, const bool reuseGrammar)
  +void XMLScanner::scanDocument(const InputSource& src)
   {
       //
       //  Bump up the sequence id for this parser instance. This will invalidate
  @@ -424,9 +424,6 @@
       //
       fSequenceId++;
   
  -    // Store the reuse validator flag
  -    fReuseGrammar = reuseGrammar;
  -
       try
       {
           //
  @@ -570,8 +567,7 @@
   //  going to work on subsequent scanNext() calls.
   //
   bool XMLScanner::scanFirst( const   XMLCh* const    systemId
  -                            ,       XMLPScanToken&  toFill
  -                            , const bool            reuseGrammar)
  +                            ,       XMLPScanToken&  toFill)
   {
       //
       //  First we try to parse it as a URL. If that fails, we assume its
  @@ -639,26 +635,21 @@
       }
   
       Janitor<InputSource> janSrc(srcToUse);
  -    return scanFirst(*srcToUse, toFill, reuseGrammar);
  +    return scanFirst(*srcToUse, toFill);
   }
   
   bool XMLScanner::scanFirst( const   char* const     systemId
  -                            ,       XMLPScanToken&  toFill
  -                            , const bool            reuseGrammar)
  +                            ,       XMLPScanToken&  toFill)
   {
       // We just delegate this to the XMLCh version after transcoding
       XMLCh* tmpBuf = XMLString::transcode(systemId);
       ArrayJanitor<XMLCh> janBuf(tmpBuf);
  -    return scanFirst(tmpBuf, toFill, reuseGrammar);
  +    return scanFirst(tmpBuf, toFill);
   }
   
   bool XMLScanner::scanFirst( const   InputSource&    src
  -                            ,       XMLPScanToken&  toFill
  -                            , const bool            reuseGrammar)
  +                            ,       XMLPScanToken&  toFill)
   {
  -    // Store the reuse validator flag
  -    fReuseGrammar = reuseGrammar;
  -
       //
       //  Bump up the sequence id for this new scan cycle. This will invalidate
       //  any previous tokens we've returned.
  @@ -1061,14 +1052,9 @@
       //
       fIDRefList = new RefHashTableOf<XMLRefInfo>(109);
   
  -    //  Create the EntityDeclPool
  -    fEntityDeclPool = new NameIdPool<DTDEntityDecl>(109);
  -
       //  Create the GrammarResolver
       fGrammarResolver = new GrammarResolver();
   
  -    resetEntityDeclPool();
  -
       //  Create the Validator and init them
       fDTDValidator = new DTDValidator();
       initValidator(fDTDValidator);
  @@ -1099,25 +1085,6 @@
       }
   }
   
  -void XMLScanner::resetEntityDeclPool() {
  -
  -    fEntityDeclPool->removeAll();
  -    //
  -    //  Add the default entity entries for the character refs that must always
  -    //  be present. We indicate that they are from the internal subset. They
  -    //  aren't really, but they have to look that way so that they are still
  -    //  valid for use within a standalone document.
  -    //
  -    //  We also mark them as special char entities, which allows them to be
  -    //  used in places whether other non-numeric general entities cannot.
  -    //
  -    fEntityDeclPool->put(new DTDEntityDecl(gAmp, chAmpersand, true, true));
  -    fEntityDeclPool->put(new DTDEntityDecl(gLT, chOpenAngle, true, true));
  -    fEntityDeclPool->put(new DTDEntityDecl(gGT, chCloseAngle, true, true));
  -    fEntityDeclPool->put(new DTDEntityDecl(gQuot, chDoubleQuote, true, true));
  -    fEntityDeclPool->put(new DTDEntityDecl(gApos, chSingleQuote, true, true));
  -}
  -
   void XMLScanner::resetURIStringPool() {
       fURIStringPool->flushAll();
   
  @@ -2290,9 +2257,9 @@
   
                       // if reusing grammar, this has been validated already in first scan
                       // skip for performance
  -                    if (!fReuseGrammar && fValidate) {
  +                    if (fValidate && !fGrammar->getValidated()) {
                           //  validate the DTD scan so far
  -                        fValidator->preContentValidation(fReuseGrammar);
  +                        fValidator->preContentValidation(fUseCachedGrammar);
                       }
                   }
                    else
  @@ -2358,27 +2325,10 @@
   
   void XMLScanner::scanDocTypeDecl()
   {
  -    if (!fReuseGrammar && fValidatorFromUser && !fValidator->handlesDTD())
  -    {
  -        ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  -    }
  -
       //
  -    //  We have a doc type. So, create a DTDScanner and
  -    //  switch the Grammar to the emptyNamespace one.
  +    //  We have a doc type. So, switch the Grammar.
       //
  -
  -    if (!switchGrammar(XMLUni::fgZeroLenString) && fValidate)
  -    {
  -        fValidator->emitError
  -        (
  -            XMLValid::GrammarNotFound
  -          , XMLUni::fgZeroLenString
  -        );
  -    }
  -
  -    DTDScanner dtdScanner((DTDGrammar*)fGrammar, fEntityDeclPool, fDocTypeHandler);
  -    dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
  +    switchGrammar(XMLUni::fgDTDEntityString);
   
       if (fDocTypeHandler)
           fDocTypeHandler->resetDocType();
  @@ -2422,36 +2372,11 @@
       //  Only do this if we are not reusing the validator! If we are reusing,
       //  then look it up instead. It has to exist!
       //
  -    DTDElementDecl* rootDecl;
  -    Janitor<DTDElementDecl> janSrc(0);
  +    DTDElementDecl* rootDecl = new DTDElementDecl(bbRootName.getRawBuffer(), fEmptyNamespaceId);
   
  -    if (fReuseGrammar)
  -    {
  -        if (fGrammar->getGrammarType() == Grammar::DTDGrammarType) {
  -            rootDecl = (DTDElementDecl*) fGrammar->getElemDecl(fEmptyNamespaceId, 0, bbRootName.getRawBuffer(), Grammar::TOP_LEVEL_SCOPE);
  -            if (rootDecl)
  -                ((DTDGrammar*)fGrammar)->setRootElemId(rootDecl->getId());
  -            else {
  -                rootDecl = new DTDElementDecl(bbRootName.getRawBuffer(), fEmptyNamespaceId);
  -                rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  -                rootDecl->setExternalElemDeclaration(true);
  -                ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl));
  -            }
  -        }
  -        else {
  -            rootDecl = new DTDElementDecl(bbRootName.getRawBuffer(), fEmptyNamespaceId);
  -            rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  -            rootDecl->setExternalElemDeclaration(true);
  -            janSrc.reset(rootDecl);
  -        }
  -    }
  -     else
  -    {
  -        rootDecl = new DTDElementDecl(bbRootName.getRawBuffer(), fEmptyNamespaceId);
  -        rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  -        rootDecl->setExternalElemDeclaration(true);
  -        ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl));
  -    }
  +    rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  +    rootDecl->setExternalElemDeclaration(true);
  +    ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl));
   
       // Skip any spaces after the name
       fReaderMgr.skipPastSpaces();
  @@ -2472,17 +2397,17 @@
       }
   
       // either internal/external subset
  -    if(!fReuseGrammar) {
  -        if (fValScheme == Val_Auto && !fValidate)
  -            fValidate = true;
  -    }
  -
  +    if (fValScheme == Val_Auto && !fValidate)
  +        fValidate = true;
   
       bool    hasIntSubset = false;
       bool    hasExtSubset = false;
       XMLCh*  sysId = 0;
       XMLCh*  pubId = 0;
   
  +    DTDScanner dtdScanner((DTDGrammar*)fGrammar, fDocTypeHandler);
  +    dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
  +
       //
       //  If the next character is '[' then we have no external subset cause
       //  there is no system id, just the opening character of the internal
  @@ -2544,7 +2469,7 @@
           fReaderMgr.getNextChar();
   
           // We can't have any internal subset if we are reusing the validator
  -        if (fReuseGrammar)
  +        if (fUseCachedGrammar || fToCacheGrammar)
               ThrowXML(RuntimeException, XMLExcepts::Val_CantHaveIntSS);
   
           //
  @@ -2596,50 +2521,88 @@
       //  If we had an external subset, then we need to deal with that one
       //  next. If we are reusing the validator, then don't scan it.
       //
  -    if (hasExtSubset && !fReuseGrammar && (fLoadExternalDTD || fValidate))
  -    {
  -        // And now create a reader to read this entity
  -        InputSource* srcUsed;
  -        XMLReader* reader = fReaderMgr.createReader
  -        (
  -            sysId
  -            , pubId
  -            , false
  -            , XMLReader::RefFrom_NonLiteral
  -            , XMLReader::Type_General
  -            , XMLReader::Source_External
  -            , srcUsed
  -        );
  +    if (hasExtSubset) {
  +
  +        if (fUseCachedGrammar)
  +        {
  +            InputSource* sysIdSrc = resolveSystemId(sysId);
  +            Janitor<InputSource> janSysIdSrc(sysIdSrc);
  +            Grammar* grammar = fGrammarResolver->getGrammar(sysIdSrc->getSystemId());
   
  -        // Put a janitor on the input source
  -        Janitor<InputSource> janSrc(srcUsed);
  +            if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType) {
   
  -        //
  -        //  If it failed then throw an exception
  -        //
  -        if (!reader)
  -            ThrowXML1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed->getSystemId());
  +                fDTDGrammar = (DTDGrammar*) grammar;
  +                fGrammar = fDTDGrammar;
  +                fValidator->setGrammar(fGrammar);
  +                rootDecl = (DTDElementDecl*) fGrammar->getElemDecl(fEmptyNamespaceId, 0, bbRootName.getRawBuffer(), Grammar::TOP_LEVEL_SCOPE);
   
  -        //
  -        //  In order to make the processing work consistently, we have to
  -        //  make this look like an external entity. So create an entity
  -        //  decl and fill it in and push it with the reader, as happens
  -        //  with an external entity. Put a janitor on it to insure it gets
  -        //  cleaned up. The reader manager does not adopt them.
  -        //
  -        const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
  -        DTDEntityDecl* declDTD = new DTDEntityDecl(gDTDStr);
  -        declDTD->setSystemId(sysId);
  -        Janitor<DTDEntityDecl> janDecl(declDTD);
  +                if (rootDecl)
  +                    ((DTDGrammar*)fGrammar)->setRootElemId(rootDecl->getId());
  +                else {
  +                    rootDecl = new DTDElementDecl(bbRootName.getRawBuffer(), fEmptyNamespaceId);
  +                    rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  +                    rootDecl->setExternalElemDeclaration(true);
  +                    ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl));
  +                }
  +
  +                return;
  +            }
  +        }
  +
  +        if (fLoadExternalDTD || fValidate)
  +        {
  +            // And now create a reader to read this entity
  +            InputSource* srcUsed;
  +            XMLReader* reader = fReaderMgr.createReader
  +            (
  +                sysId
  +                , pubId
  +                , false
  +                , XMLReader::RefFrom_NonLiteral
  +                , XMLReader::Type_General
  +                , XMLReader::Source_External
  +                , srcUsed
  +            );
  +
  +            // Put a janitor on the input source
  +            Janitor<InputSource> janSrc(srcUsed);
  +
  +            //
  +            //  If it failed then throw an exception
  +            //
  +            if (!reader)
  +                ThrowXML1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed->getSystemId());
  +
  +            if (fToCacheGrammar) {
  +
  +                unsigned int stringId = fGrammarResolver->getStringPool()->addOrFind(srcUsed->getSystemId());
  +                const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(stringId);
  +
  +                fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
  +                fGrammarResolver->putGrammar(sysIdStr, fGrammar);
  +            }
  +
  +            //
  +            //  In order to make the processing work consistently, we have to
  +            //  make this look like an external entity. So create an entity
  +            //  decl and fill it in and push it with the reader, as happens
  +            //  with an external entity. Put a janitor on it to insure it gets
  +            //  cleaned up. The reader manager does not adopt them.
  +            //
  +            const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
  +            DTDEntityDecl* declDTD = new DTDEntityDecl(gDTDStr);
  +            declDTD->setSystemId(sysId);
  +            Janitor<DTDEntityDecl> janDecl(declDTD);
   
  -        // Mark this one as a throw at end
  -        reader->setThrowAtEnd(true);
  +            // Mark this one as a throw at end
  +            reader->setThrowAtEnd(true);
   
  -        // And push it onto the stack, with its pseudo name
  -        fReaderMgr.pushReader(reader, declDTD);
  +            // And push it onto the stack, with its pseudo name
  +            fReaderMgr.pushReader(reader, declDTD);
   
  -        // Tell it its not in an include section
  -        dtdScanner.scanExtSubsetDecl(false);
  +            // Tell it its not in an include section
  +            dtdScanner.scanExtSubsetDecl(false);
  +        }
       }
   }
   
  @@ -2734,6 +2697,8 @@
       //
       if (isRoot)
       {
  +        fRootGrammar = fGrammar;
  +
           if (fValidate)
           {
               //  If a DocType exists, then check if it matches the root name there.
  @@ -3125,6 +3090,16 @@
                   if ((defType == XMLAttDef::Default)
                   ||  (defType == XMLAttDef::Fixed))
                   {
  +                    // Let the validator pass judgement on the attribute value
  +                    if (fValidate)
  +                    {
  +                        fValidator->validateAttrValue
  +                        (
  +                            &curDef
  +                            , curDef.getValue()
  +                        );
  +                    }
  +
                       XMLAttr* curAtt;
                       if (attCount >= curAttListSize)
                       {
  @@ -3316,7 +3291,6 @@
       //  go through them first before scanning those specified in the instance document
       if (isRoot
           && fDoSchema
  -        && !fReuseGrammar
           && (fExternalSchemaLocation || fExternalNoNamespaceSchemaLocation)) {
   
           if (fExternalSchemaLocation)
  @@ -3468,7 +3442,8 @@
                           , nameRawBuf
                           , fPrefixBuf.getRawBuffer()
                           , qnameRawBuf
  -                        , currentScope);
  +                        , currentScope
  +                        , true);
               wasAdded = true;
           }
       }
  @@ -3556,7 +3531,8 @@
                           , nameRawBuf
                           , fPrefixBuf.getRawBuffer()
                           , qnameRawBuf
  -                        , currentScope);
  +                        , currentScope
  +                        , true);
               wasAdded = true;
           }
       }
  @@ -3617,6 +3593,9 @@
       fElemStack.setElement(elemDecl, fReaderMgr.getCurrentReaderNum());
       fElemStack.setCurrentURI(uriId);
   
  +    if (isRoot)
  +        fRootGrammar = fGrammar;
  +
       //  Validate the element
       if (fValidate)
           fValidator->validateElement(elemDecl);
  @@ -3631,7 +3610,7 @@
               const XMLCh poundStr[] = {chPound, chNull};
               if (!XMLString::startsWith(typeName, poundStr)) {
                   const int comma = XMLString::indexOf(typeName, chComma);
  -                if (comma != -1) {
  +                if (comma > 0) {
                       XMLBuffer prefixBuf(comma+1);
                       prefixBuf.append(typeName, comma);
                       const XMLCh* uriStr = prefixBuf.getRawBuffer();
  @@ -4289,3 +4268,291 @@
       matcher->startDocumentFragment();
   }
   
  +// ---------------------------------------------------------------------------
  +//  XMLScanner: Grammar preparsing
  +// ---------------------------------------------------------------------------
  +Grammar* XMLScanner::loadGrammar(const   XMLCh* const systemId
  +                                 , const short        grammarType
  +                                 , const bool         toCache)
  +{
  +    InputSource* srcToUse = 0;
  +
  +    if (fEntityHandler){
  +        srcToUse = fEntityHandler->resolveEntity(XMLUni::fgZeroLenString, systemId);
  +    }
  +
  +    //
  +    //  First we try to parse it as a URL. If that fails, we assume its
  +    //  a file and try it that way.
  +    //
  +    if (!srcToUse) {
  +
  +        try
  +        {
  +            //
  +            //  Create a temporary URL. Since this is the primary document,
  +            //  it has to be fully qualified. If not, then assume we are just
  +            //  mistaking a file for a URL.
  +            //
  +            XMLURL tmpURL(systemId);
  +            if (tmpURL.isRelative()) {
  +                srcToUse = new LocalFileInputSource(systemId);
  +            }
  +            else
  +            {
  +                srcToUse = new URLInputSource(tmpURL);
  +            }
  +        }
  +        catch(const MalformedURLException&)
  +        {
  +            srcToUse = new LocalFileInputSource(systemId);
  +        }
  +        catch(...)
  +        {
  +            // Just rethrow this, since its not our problem
  +            throw;
  +        }
  +    }
  +
  +    Janitor<InputSource> janSrc(srcToUse);
  +    return loadGrammar(*srcToUse, grammarType, toCache);
  +}
  +
  +Grammar* XMLScanner::loadGrammar(const   char* const systemId
  +                                 , const short       grammarType
  +                                 , const bool        toCache)
  +{
  +    // We just delegate this to the XMLCh version after transcoding
  +    XMLCh* tmpBuf = XMLString::transcode(systemId);
  +    ArrayJanitor<XMLCh> janBuf(tmpBuf);
  +    return loadGrammar(tmpBuf, grammarType, toCache);
  +}
  +
  +
  +Grammar* XMLScanner::loadGrammar(const   InputSource& src
  +                                 , const short        grammarType
  +                                 , const bool         toCache)
  +{
  +    try
  +    {
  +        fGrammarResolver->cacheGrammarFromParse(false);
  +        fGrammarResolver->useCachedGrammarInParse(false);
  +        fRootGrammar = 0;
  +
  +        if (fValScheme == Val_Auto) {
  +            fValidate = true;
  +        }
  +
  +        // Reset some status flags
  +        fInException = false;
  +        fStandalone = false;
  +        fErrorCount = 0;
  +        fHasNoDTD = true;
  +        fSeeXsi = false;
  +
  +        if (grammarType == Grammar::SchemaGrammarType) {
  +            return loadXMLSchemaGrammar(src, toCache);
  +        }
  +        else if (grammarType == Grammar::DTDGrammarType) {
  +            return loadDTDGrammar(src, toCache);
  +        }
  +
  +        // Reset the reader manager to close all files, sockets, etc...
  +        fReaderMgr.reset();
  +    }
  +
  +    //
  +    //  NOTE:
  +    //
  +    //  In all of the error processing below, the emitError() call MUST come
  +    //  before the flush of the reader mgr, or it will fail because it tries
  +    //  to find out the position in the XML source of the error.
  +    //
  +    catch(const XMLErrs::Codes)
  +    {
  +        // This is a 'first fatal error' type exit, so reset and fall through
  +        fReaderMgr.reset();
  +    }
  +
  +    catch(const XMLValid::Codes)
  +    {
  +        // This is a 'first fatal error' type exit, so reset and fall through
  +        fReaderMgr.reset();
  +       
  +    }
  +
  +    catch(const XMLException& excToCatch)
  +    {
  +        //
  +        //  Emit the error and catch any user exception thrown from here. Make
  +        //  sure in all cases we flush the reader manager.
  +        //
  +        fInException = true;
  +        try
  +        {
  +            if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
  +                emitError
  +                (
  +                    XMLErrs::XMLException_Warning
  +                    , excToCatch.getType()
  +                    , excToCatch.getMessage()
  +                );
  +            else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
  +                emitError
  +                (
  +                    XMLErrs::XMLException_Fatal
  +                    , excToCatch.getType()
  +                    , excToCatch.getMessage()
  +                );
  +            else
  +                emitError
  +                (
  +                    XMLErrs::XMLException_Error
  +                    , excToCatch.getType()
  +                    , excToCatch.getMessage()
  +                );
  +        }
  +
  +        catch(...)
  +        {
  +            // Flush the reader manager and rethrow user's error
  +            fReaderMgr.reset();
  +            throw;
  +        }
  +
  +        // If it returned, then reset the reader manager and fall through
  +        fReaderMgr.reset();
  +    }
  +
  +    catch(...)
  +    {
  +        // Reset and rethrow
  +        fReaderMgr.reset();
  +        throw;
  +    }
  +
  +    return 0;
  +}
  +
  +Grammar* XMLScanner::loadDTDGrammar(const InputSource& src,
  +                                    const bool toCache)
  +{
  +   // Reset the validators
  +    fDTDValidator->reset();
  +    if (fValidatorFromUser)
  +        fValidator->reset();
  +
  +    if (!fValidator->handlesDTD()) {
  +        if (fValidatorFromUser && fValidate)
  +            ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  +        else {
  +            fValidator = fDTDValidator;
  +        }
  +    }
  +
  +    fDTDGrammar = new DTDGrammar();
  +    fGrammarResolver->putGrammar(XMLUni::fgDTDEntityString, fDTDGrammar);
  +    fGrammar = fDTDGrammar;
  +    fGrammarType = fGrammar->getGrammarType();
  +    fValidator->setGrammar(fGrammar);
  +
  +    //
  +    //  And for all installed handlers, send reset events. This gives them
  +    //  a chance to flush any cached data.
  +    //
  +    if (fDocHandler)
  +        fDocHandler->resetDocument();
  +    if (fEntityHandler)
  +        fEntityHandler->resetEntities();
  +    if (fErrorReporter)
  +        fErrorReporter->resetErrors();
  +
  +    // Clear out the id reference list
  +    fIDRefList->removeAll();
  +
  +    if (toCache) {
  +
  +        unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId());
  +        const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId);
  +
  +        fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
  +        fGrammarResolver->putGrammar(sysIdStr, fGrammar);
  +    }
  +
  +    //
  +    //  Handle the creation of the XML reader object for this input source.
  +    //  This will provide us with transcoding and basic lexing services.
  +    //
  +    XMLReader* newReader = fReaderMgr.createReader
  +    (
  +        src
  +        , false
  +        , XMLReader::RefFrom_NonLiteral
  +        , XMLReader::Type_General
  +        , XMLReader::Source_External
  +    );
  +    if (!newReader) {
  +        if (src.getIssueFatalErrorIfNotFound())
  +            ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId());
  +        else
  +            ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId());
  +    }
  +
  +    //
  +    //  In order to make the processing work consistently, we have to
  +    //  make this look like an external entity. So create an entity
  +    //  decl and fill it in and push it with the reader, as happens
  +    //  with an external entity. Put a janitor on it to insure it gets
  +    //  cleaned up. The reader manager does not adopt them.
  +    //
  +    const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
  +    DTDEntityDecl* declDTD = new DTDEntityDecl(gDTDStr);
  +    declDTD->setSystemId(src.getSystemId());
  +    Janitor<DTDEntityDecl> janDecl(declDTD);
  +
  +    // Mark this one as a throw at end
  +    newReader->setThrowAtEnd(true);
  +
  +    // And push it onto the stack, with its pseudo name
  +    fReaderMgr.pushReader(newReader, declDTD);
  +
  +    //
  +    //  If we have a doc type handler and advanced callbacks are enabled,
  +    //  call the doctype event.
  +    //
  +    if (fDocTypeHandler) {
  +
  +        // Create a dummy root
  +        DTDElementDecl* rootDecl = new DTDElementDecl(gDTDStr, fEmptyNamespaceId);
  +        rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  +        rootDecl->setExternalElemDeclaration(true);
  +        Janitor<DTDElementDecl> janSrc(rootDecl);
  +
  +        fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false);
  +    }
  +
  +    // Create DTDScanner
  +    DTDScanner dtdScanner((DTDGrammar*)fGrammar, fDocTypeHandler);
  +    dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
  +
  +    // Tell it its not in an include section
  +    dtdScanner.scanExtSubsetDecl(false);
  +
  +    if (fValidate) {
  +        //  validate the DTD scan so far
  +        fValidator->preContentValidation(false, true);
  +    }
  +
  +    if (toCache)
  +        fGrammarResolver->cacheGrammars();
  +
  +    return fDTDGrammar;
  +}
  +
  +// ---------------------------------------------------------------------------
  +//  XMLScanner: Rest pool of cached grammars
  +// ---------------------------------------------------------------------------
  +void XMLScanner::resetCachedGrammarPool()
  +{
  +    fGrammarResolver->resetCachedGrammar();
  +}
  \ No newline at end of file
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org