source: icXML/icXML-devel/src/icxercesc/internal/IGXMLScanner.cpp @ 3157

Last change on this file since 3157 was 3157, checked in by cameron, 6 years ago

Fixes for icXML 0.9

File size: 44.9 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: IGXMLScanner.cpp 882548 2009-11-20 13:44:14Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  Includes
24// ---------------------------------------------------------------------------
25#include <icxercesc/internal/IGXMLScanner.hpp>
26#include <xercesc/util/RuntimeException.hpp>
27#include <xercesc/util/UnexpectedEOFException.hpp>
28#include <xercesc/sax/InputSource.hpp>
29#include <icxercesc/framework/XMLDocumentHandler.hpp>
30#include <xercesc/framework/XMLEntityHandler.hpp>
31#include <xercesc/framework/XMLPScanToken.hpp>
32#include <xercesc/framework/MemoryManager.hpp>
33#include <icxercesc/framework/XMLGrammarPool.hpp>
34#include <xercesc/framework/XMLDTDDescription.hpp>
35#include <xercesc/framework/psvi/PSVIElement.hpp>
36#include <xercesc/framework/psvi/PSVIHandler.hpp>
37#include <xercesc/framework/psvi/PSVIAttributeList.hpp>
38#include <icxercesc/validators/common/GrammarResolver.hpp>
39#include <xercesc/validators/DTD/DocTypeHandler.hpp>
40#include <icxercesc/validators/DTD/DTDScanner.hpp>
41#include <icxercesc/validators/DTD/DTDValidator.hpp>
42#include <icxercesc/validators/schema/SchemaValidator.hpp>
43#include <icxercesc/validators/schema/identity/IdentityConstraintHandler.hpp>
44#include <xercesc/validators/schema/identity/IC_Selector.hpp>
45#include <xercesc/util/OutOfMemoryException.hpp>
46#include <icxercesc/util/XMLString.hpp>
47#include <icxmlc/XMLNamespaceResolver.hpp>
48#include <icxmlc/XMLStringU.hpp>
49
50XERCES_CPP_NAMESPACE_BEGIN
51
52typedef JanitorMemFunCall<IGXMLScanner> CleanupType;
53typedef JanitorMemFunCall<ReaderMgr>    ReaderMgrResetType;
54
55// ---------------------------------------------------------------------------
56//  IGXMLScanner: Constructors and Destructor
57// ---------------------------------------------------------------------------
58IGXMLScanner::IGXMLScanner( XMLValidator* const  valToAdopt
59                                                  , GrammarResolver* const grammarResolver
60                                                  , MemoryManager* const manager) :
61
62        XMLScanner(valToAdopt, grammarResolver, manager)
63        , fGrammarType(Grammar::UnKnown)
64        , fElemStateSize(16)
65        , fElemState(0)
66        , fElemLoopState(0)
67        , fContent(1023, manager)
68        , fWSNormalizeBuf(1023, manager)
69        , fDTDValidator(0)
70        , fSchemaValidator(0)
71        , fDTDGrammar(0)
72        , fICHandler(0)
73        , fDTDElemNonDeclPool(0)
74        , fSchemaElemNonDeclPool(0)
75        , fPSVIAttrList(0)
76        , fModel(0)
77        , fPSVIElement(0)
78        , fErrorStack(0)
79        , fSchemaInfoList(0)
80        , fCachedSchemaInfoList (0)
81    , fAnySimpleTypeValidator(0)
82{
83        CleanupType cleanup(this, &IGXMLScanner::cleanUp);
84
85        try
86        {
87                commonInit();
88        }
89        catch(const OutOfMemoryException&)
90        {
91                // Don't cleanup when out of memory, since executing the
92                // code can cause problems.
93                cleanup.release();
94
95                throw;
96        }
97
98        cleanup.release();
99}
100
101IGXMLScanner::IGXMLScanner( XMLDocumentHandler* const docHandler
102                                                  , DocTypeHandler* const     docTypeHandler
103                                                  , XMLEntityHandler* const   entityHandler
104                                                  , XMLErrorReporter* const   errHandler
105                                                  , XMLValidator* const       valToAdopt
106                                                  , GrammarResolver* const    grammarResolver
107                                                  , MemoryManager* const      manager) :
108
109        XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, grammarResolver, manager)
110        , fGrammarType(Grammar::UnKnown)
111        , fElemStateSize(16)
112        , fElemState(0)
113        , fElemLoopState(0)
114        , fContent(1023, manager)
115        , fWSNormalizeBuf(1023, manager)
116        , fDTDValidator(0)
117        , fSchemaValidator(0)
118        , fDTDGrammar(0)
119        , fICHandler(0)
120        , fDTDElemNonDeclPool(0)
121        , fSchemaElemNonDeclPool(0)
122        , fPSVIAttrList(0)
123        , fModel(0)
124        , fPSVIElement(0)
125        , fErrorStack(0)
126        , fSchemaInfoList(0)
127        , fCachedSchemaInfoList (0)
128    , fAnySimpleTypeValidator(0)
129{
130        CleanupType cleanup(this, &IGXMLScanner::cleanUp);
131
132        try
133        {
134                commonInit();
135        }
136        catch(const OutOfMemoryException&)
137        {
138                // Don't cleanup when out of memory, since executing the
139                // code can cause problems.
140                cleanup.release();
141
142                throw;
143        }
144
145        cleanup.release();
146}
147
148IGXMLScanner::~IGXMLScanner()
149{
150        cleanUp();
151}
152
153// ---------------------------------------------------------------------------
154//  XMLScanner: Getter methods
155// ---------------------------------------------------------------------------
156NameIdPool<DTDEntityDecl>* IGXMLScanner::getEntityDeclPool()
157{
158        if(!fDTDGrammar)
159                return 0;
160        return fDTDGrammar->getEntityDeclPool();
161}
162
163const NameIdPool<DTDEntityDecl>* IGXMLScanner::getEntityDeclPool() const
164{
165        if(!fDTDGrammar)
166                return 0;
167        return fDTDGrammar->getEntityDeclPool();
168}
169
170// ---------------------------------------------------------------------------
171//  IGXMLScanner: Main entry point to scan a document
172// ---------------------------------------------------------------------------
173void IGXMLScanner::scanDocument( const InputSource & src )
174{
175        //  Bump up the sequence id for this parser instance. This will invalidate
176        //  any previous progressive scan tokens.
177        fSequenceId++;
178        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
179
180        try
181        {
182                //  Reset the scanner and its plugged in stuff for a new run. This
183                //  resets all the data structures, creates the initial reader and
184                //  pushes it on the stack, and sets up the base document path.
185                scanReset(src);
186
187                // If we have a document handler, then call the start document
188                if (fDocHandler)
189                        fDocHandler->startDocument();
190
191                if (fReaderMgr.getCurrentReader()->scanDocument<IGXMLScanner>(this))
192                {
193                        // Do post-parse validation if required
194                        if (fValidate)
195                        {
196                                //  We handle ID reference semantics at this level since
197                                //  its required by XML 1.0.
198                                checkIDRefs();
199                        }
200                }
201
202                // If we have a document handler, then call the end document
203                if (fDocHandler)
204                        fDocHandler->endDocument();
205        }
206        //  NOTE:
207        //
208        //  In all of the error processing below, the emitError() call MUST come
209        //  before the flush of the reader mgr, or it will fail because it tries
210        //  to find out the position in the XML source of the error.
211        catch(const XMLErrs::Codes)
212        {
213                // This is a 'first failure' exception, so fall through
214        }
215        catch(const XMLValid::Codes)
216        {
217                // This is a 'first fatal error' type exit, so fall through
218        }
219        catch(const XMLException& excToCatch)
220        {
221                //  Emit the error and catch any user exception thrown from here. Make
222                //  sure in all cases we flush the reader manager.
223                fInException = true;
224                try
225                {
226                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
227                                emitError
228                                (
229                                        XMLErrs::XMLException_Warning
230                                        , excToCatch.getCode()
231                                        , excToCatch.getMessage()
232                                );
233                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
234                                emitError
235                                (
236                                        XMLErrs::XMLException_Fatal
237                                        , excToCatch.getCode()
238                                        , excToCatch.getMessage()
239                                );
240                        else
241                                emitError
242                                (
243                                        XMLErrs::XMLException_Error
244                                        , excToCatch.getCode()
245                                        , excToCatch.getMessage()
246                                );
247                }
248                catch(const OutOfMemoryException&)
249                {
250                        // This is a special case for out-of-memory
251                        // conditions, because resetting the ReaderMgr
252                        // can be problematic.
253                        resetReaderMgr.release();
254
255                        throw;
256                }
257        }
258        catch(const OutOfMemoryException&)
259        {
260                // This is a special case for out-of-memory
261                // conditions, because resetting the ReaderMgr
262                // can be problematic.
263                resetReaderMgr.release();
264
265                throw;
266        }
267}
268
269void IGXMLScanner::scanFirst()
270{
271    fReaderMgr.getCurrentReader()->scanFirst<IGXMLScanner>(this);
272}
273
274bool IGXMLScanner::scanNext(XMLPScanToken & token)
275{
276        // Make sure this token is still legal
277    if (unlikely(!isLegalToken(token)))
278                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager);
279
280        try
281        {
282                // If we hit the end, then do the miscellaneous part
283        if (likely(fReaderMgr.getCurrentReader()->scanNext<IGXMLScanner>()))
284                {
285            return true;
286        }
287
288        // Do post-parse validation if required
289        if (fValidate)
290        {
291            //  We handle ID reference semantics at this level since
292            //  its required by XML 1.0.
293            checkIDRefs();
294        }
295
296        if (toCheckIdentityConstraint())
297            fICHandler->endDocument();
298
299        if (fDocHandler)
300            fDocHandler->endDocument();
301        }
302        catch(const XMLErrs::Codes)
303        {
304
305        }
306        catch(const XMLValid::Codes)
307        {
308
309        }
310        catch(const XMLException& excToCatch)
311        {
312                //  Emit the error and catch any user exception thrown from here. Make
313                //  sure in all cases we flush the reader manager.
314                fInException = true;
315                try
316                {
317                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
318                                emitError
319                                (
320                                        XMLErrs::XMLException_Warning
321                                        , excToCatch.getCode()
322                                        , excToCatch.getMessage()
323                                );
324                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
325                                emitError
326                                (
327                                        XMLErrs::XMLException_Fatal
328                                        , excToCatch.getCode()
329                                        , excToCatch.getMessage()
330                                );
331                        else
332                                emitError(XMLErrs::XMLException_Error, excToCatch.getCode(), excToCatch.getMessage());
333                }
334                catch(const OutOfMemoryException&)
335                {
336                        throw;
337                }
338        }
339        catch(const OutOfMemoryException&)
340        {
341                throw;
342        }
343
344        fReaderMgr.reset();
345
346        return false;
347}
348
349// ---------------------------------------------------------------------------
350//  IGXMLScanner: Private helper methods. Most of these are implemented in
351//  IGXMLScanner2.Cpp.
352// ---------------------------------------------------------------------------
353
354//  This method handles the common initialization, to avoid having to do
355//  it redundantly in multiple constructors.
356void IGXMLScanner::commonInit()
357{
358
359        //  Create the element state array
360        fElemState = (unsigned int*) fMemoryManager->allocate
361        (
362                fElemStateSize * sizeof(unsigned int)
363        ); //new unsigned int[fElemStateSize];
364        fElemLoopState = (unsigned int*) fMemoryManager->allocate
365        (
366                fElemStateSize * sizeof(unsigned int)
367        ); //new unsigned int[fElemStateSize];
368
369        //  Create the Validator and init them
370        fDTDValidator = new (fMemoryManager) DTDValidator();
371        initValidator(fDTDValidator);
372        fSchemaValidator = new (fMemoryManager) SchemaValidator(0, fMemoryManager);
373        initValidator(fSchemaValidator);
374
375        // Create IdentityConstraint info
376        fICHandler = new (fMemoryManager) IdentityConstraintHandler(this, fMemoryManager);
377
378        // create pools for undeclared elements
379        fDTDElemNonDeclPool = new (fMemoryManager) NameIdPool<DTDElementDecl>(29, 128, fMemoryManager);
380    fSchemaElemNonDeclPool = new (fMemoryManager) RefHash3KeysIdPool<SchemaElementDecl>(29, true, 128, fMemoryManager);
381        fPSVIAttrList = new (fMemoryManager) PSVIAttributeList(fMemoryManager);
382
383        fSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf<SchemaInfo>(29, fMemoryManager);
384        fCachedSchemaInfoList = new (fMemoryManager) RefHash2KeysTableOf<SchemaInfo>(29, fMemoryManager);
385
386    fAnySimpleTypeValidator = 0;
387
388        // use fDTDValidator as the default validator
389        if (!fValidator)
390        {
391                fValidator = fDTDValidator;
392        }
393}
394
395void IGXMLScanner::cleanUp()
396{
397        fMemoryManager->deallocate(fElemState);
398        fMemoryManager->deallocate(fElemLoopState);
399        delete fDTDValidator;
400        delete fSchemaValidator;
401        delete fICHandler;
402        delete fDTDElemNonDeclPool;
403        delete fSchemaElemNonDeclPool;
404        delete fPSVIAttrList;
405        delete fPSVIElement;
406    delete fErrorStack;
407        delete fSchemaInfoList;
408        delete fCachedSchemaInfoList;
409}
410
411// ---------------------------------------------------------------------------
412//  IGXMLScanner: Private Scanning Methods
413// ---------------------------------------------------------------------------
414
415//  This method handles the high level logic of scanning the DOCType
416//  declaration. This calls the DTDScanner and kicks off both the scanning of
417//  the internal subset and the scanning of the external subset, if any.
418//
419//  When we get here the '<!DOCTYPE' part has already been scanned, which is
420//  what told us that we had a doc type decl to parse.
421void IGXMLScanner::scanDocTypeDecl()
422{
423    //  We have a doc type. So, switch the Grammar.
424    switchGrammar(XMLNamespaceResolver::fEmptyUriId, XMLUni::fgDTDEntityString);
425    // setCurrentGrammar(fGrammarResolver->getGrammar(XMLUni::fgDTDEntityString));
426
427    if (fDocTypeHandler)
428        fDocTypeHandler->resetDocType();
429
430    // There must be some space after DOCTYPE
431    bool skippedSomething;
432    fReaderMgr.skipPastSpaces(skippedSomething);
433    if (!skippedSomething)
434    {
435        emitError(XMLErrs::ExpectedWhitespace);
436
437        // Just skip the Doctype declaration and return
438        fReaderMgr.skipPastChar(chCloseAngle);
439        return;
440    }
441
442    // Get a buffer for the root element
443    XMLBufBid bbRootName(&fBufMgr);
444
445    //  Get a name from the input, which should be the name of the root
446    //  element of the upcoming content.
447    int  colonPosition;
448    bool validName = fDoNamespaces ?
449            fReaderMgr.getQName(bbRootName.getBuffer(), &colonPosition) :
450            fReaderMgr.getName(bbRootName.getBuffer());
451
452    if (!validName)
453    {
454        if (bbRootName.isEmpty())
455            emitError(XMLErrs::NoRootElemInDOCTYPE);
456        else
457            emitError(XMLErrs::InvalidRootElemInDOCTYPE, bbRootName.getRawBuffer());
458        fReaderMgr.skipPastChar(chCloseAngle);
459        return;
460    }
461
462    //  Store the root element name for later check
463    setRootElemName(bbRootName.getRawBuffer());
464
465    //  This element obviously is not going to exist in the element decl
466    //  pool yet, but we need to call docTypeDecl. So force it into
467    //  the element decl pool, marked as being there because it was in
468    //  the DOCTYPE. Later, when its declared, the status will be updated.
469    //
470    //  Only do this if we are not reusing the validator! If we are reusing,
471    //  then look it up instead. It has to exist!
472    MemoryManager* const  rootDeclMgr =
473        fUseCachedGrammar ? fMemoryManager : fGrammarPoolMemoryManager;
474
475    DTDElementDecl* rootDecl = new (rootDeclMgr) DTDElementDecl
476    (
477        bbRootName.getRawBuffer()
478        , XMLNamespaceResolver::fEmptyUriId
479        , DTDElementDecl::Any
480        , rootDeclMgr
481    );
482
483    Janitor<DTDElementDecl> rootDeclJanitor(rootDecl);
484    rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
485    rootDecl->setExternalElemDeclaration(true);
486    if (!fUseCachedGrammar)
487    {
488        fGrammar->putElemDecl(rootDecl);
489        rootDeclJanitor.release();
490    }
491    else
492    {
493        // attach this to the undeclared element pool so that it gets deleted
494        XMLElementDecl* elemDecl = fDTDElemNonDeclPool->getByKey(bbRootName.getRawBuffer());
495        if (elemDecl)
496        {
497            rootDecl->setId(elemDecl->getId());
498        }
499        else
500        {
501            rootDecl->setId(fDTDElemNonDeclPool->put((DTDElementDecl*)rootDecl));
502            rootDeclJanitor.release();
503        }
504    }
505
506    // Skip any spaces after the name
507    fReaderMgr.skipPastSpaces();
508
509    //  And now if we are looking at a >, then we are done. It is not
510    //  required to have an internal or external subset, though why you
511    //  would not escapes me.
512    if (fReaderMgr.skippedChar(chCloseAngle))
513    {
514        //  If we have a doc type handler and advanced callbacks are enabled,
515        //  call the doctype event.
516        if (fDocTypeHandler)
517            fDocTypeHandler->doctypeDecl(*rootDecl, 0, 0, false);
518        return;
519    }
520
521    // either internal/external subset
522    if (fValScheme == Val_Auto && !fValidate)
523        fValidate = true;
524
525    bool    hasIntSubset = false;
526    bool    hasExtSubset = false;
527    XMLCh*  sysId = 0;
528    XMLCh*  pubId = 0;
529
530    DTDScanner dtdScanner
531    (
532        (DTDGrammar*) fGrammar
533        , fDocTypeHandler
534        , fGrammarPoolMemoryManager
535        , fMemoryManager
536    );
537
538    dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
539
540    //  If the next character is '[' then we have no external subset cause
541    //  there is no system id, just the opening character of the internal
542    //  subset. Else, has to be an id.
543    //
544    // Just look at the next char, don't eat it.
545    if (fReaderMgr.peekNextChar() == chOpenSquare)
546    {
547        hasIntSubset = true;
548    }
549    else
550    {
551        // Indicate we have an external subset
552        hasExtSubset = true;
553        fHasNoDTD = false;
554
555        // Get buffers for the ids
556        XMLBufBid bbPubId(&fBufMgr);
557        XMLBufBid bbSysId(&fBufMgr);
558
559        // Get the external subset id
560        if (!dtdScanner.scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), DTDScanner::IDType_External))
561        {
562            fReaderMgr.skipPastChar(chCloseAngle);
563            return;
564        }
565
566        // Get copies of the ids we got
567        pubId = XMLString::replicate(bbPubId.getRawBuffer(), fMemoryManager);
568        sysId = XMLString::replicate(bbSysId.getRawBuffer(), fMemoryManager);
569
570        // Skip spaces and check again for the opening of an internal subset
571        fReaderMgr.skipPastSpaces();
572
573        // Just look at the next char, don't eat it.
574        if (fReaderMgr.peekNextChar() == chOpenSquare)
575        {
576            hasIntSubset = true;
577        }
578    }
579
580    // Insure that the ids get cleaned up, if they got allocated
581    ArrayJanitor<XMLCh> janSysId(sysId, fMemoryManager);
582    ArrayJanitor<XMLCh> janPubId(pubId, fMemoryManager);
583
584    //  If we have a doc type handler and advanced callbacks are enabled,
585    //  call the doctype event.
586    if (fDocTypeHandler)
587        fDocTypeHandler->doctypeDecl(*rootDecl, pubId, sysId, hasIntSubset, hasExtSubset);
588
589    //  Ok, if we had an internal subset, we are just past the [ character
590    //  and need to parse that first.
591    if (hasIntSubset)
592    {
593        // Eat the opening square bracket
594        XMLCh openSquareBracket = fReaderMgr.getNextChar();
595        assert (openSquareBracket == chOpenSquare);
596
597        checkInternalDTD(hasExtSubset, sysId, pubId);
598
599        //  And try to scan the internal subset. If we fail, try to recover
600        //  by skipping forward tot he close angle and returning.
601        if (!dtdScanner.scanInternalSubset())
602        {
603            fReaderMgr.skipPastChar(chCloseAngle);
604            return;
605        }
606
607        fHasInternalOrExternalDTD = true;
608
609        //  Do a sanity check that some expanded PE did not propogate out of
610        //  the doctype. This could happen if it was terminated early by bad
611        //  syntax.
612        if (fReaderMgr.getReaderDepth() > 1)
613        {
614            emitError(XMLErrs::PEPropogated);
615
616            // Ask the reader manager to pop back down to the main level
617            fReaderMgr.cleanStackBackTo(1);
618        }
619
620        fReaderMgr.skipPastSpaces();       
621    }
622
623    // And that should leave us at the closing > of the DOCTYPE line
624    if (!fReaderMgr.skippedChar(chCloseAngle))
625    {
626        //  Do a special check for the common scenario of an extra ] char at
627        //  the end. This is easy to recover from.
628        if (fReaderMgr.skippedChar(chCloseSquare) && fReaderMgr.skippedChar(chCloseAngle))
629        {
630            emitError(XMLErrs::ExtraCloseSquare);
631        }
632         else
633        {
634            emitError(XMLErrs::UnterminatedDOCTYPE);
635            fReaderMgr.skipPastChar(chCloseAngle);
636        }
637    }
638
639    //  If we had an external subset, then we need to deal with that one
640    //  next. If we are reusing the validator, then don't scan it.
641    if (hasExtSubset)
642    {
643        InputSource* srcUsed=0;
644        Janitor<InputSource> janSrc(srcUsed);
645        // If we had an internal subset and we're using the cached grammar, it
646        // means that the ignoreCachedDTD is set, so we ignore the cached
647        // grammar
648        if (fUseCachedGrammar && !hasIntSubset)
649        {
650            srcUsed = resolveSystemId(sysId, pubId);
651            if (srcUsed)
652            {
653                janSrc.reset(srcUsed);
654                Grammar* grammar = fGrammarResolver->getGrammar(srcUsed->getSystemId());
655
656                if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType)
657                {
658                    fDTDGrammar = (DTDGrammar*) grammar;
659                    fGrammar = fDTDGrammar;
660                    fValidator->setGrammar(fGrammar);
661                    // If we don't report at least the external subset boundaries,
662                    // an advanced document handler cannot know when the DTD end,
663                    // since we've already sent a doctype decl that indicates there's
664                    // there's an external subset.
665                    if (fDocTypeHandler)
666                    {
667                        fDocTypeHandler->startExtSubset();
668                        fDocTypeHandler->endExtSubset();
669                    }
670
671                    return;
672                }
673            }
674        }
675
676        if (fLoadExternalDTD || fValidate)
677        {
678            // And now create a reader to read this entity
679            XMLReader* reader;
680            if (srcUsed)
681            {
682                reader = fReaderMgr.createReader
683                (
684                    *srcUsed
685                    , false
686                    , XMLReader::RefFrom_NonLiteral
687                    , XMLReader::Type_General
688                    , XMLReader::Source_External
689                    , fCalculateSrcOfs
690                    , fLowWaterMark
691                );
692            }
693            else
694            {
695                reader = fReaderMgr.createReader
696                (
697                    sysId
698                    , pubId
699                    , false
700                    , XMLReader::RefFrom_NonLiteral
701                    , XMLReader::Type_General
702                    , XMLReader::Source_External
703                    , srcUsed
704                    , fCalculateSrcOfs
705                    , fLowWaterMark
706                    , fDisableDefaultEntityResolution
707                );
708                janSrc.reset(srcUsed);
709            }
710            //  If it failed then throw an exception
711            if (!reader)
712                ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed ? srcUsed->getSystemId() : sysId, fMemoryManager);
713
714            if (fToCacheGrammar)
715            {
716                unsigned int stringId = fGrammarResolver->getStringPool()->addOrFind(srcUsed->getSystemId());
717                const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(stringId);
718
719                fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
720                ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr);
721                fGrammarResolver->putGrammar(fGrammar);
722            }
723
724            //  In order to make the processing work consistently, we have to
725            //  make this look like an external entity. So create an entity
726            //  decl and fill it in and push it with the reader, as happens
727            //  with an external entity. Put a janitor on it to insure it gets
728            //  cleaned up. The reader manager does not adopt them.
729            const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
730            DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
731            declDTD->setSystemId(sysId);
732            declDTD->setIsExternal(true);
733            Janitor<DTDEntityDecl> janDecl(declDTD);
734
735            // Mark this one as a throw at end
736            reader->setThrowAtEnd(true);
737
738            // And push it onto the stack, with its pseudo name
739            fReaderMgr.pushReader(reader, declDTD);
740
741            // Tell it its not in an include section
742            dtdScanner.scanExtSubsetDecl(false, true);
743
744            fHasInternalOrExternalDTD = true;
745        }
746    }
747}
748
749// ---------------------------------------------------------------------------
750//  IGXMLScanner: Helper methods
751// ---------------------------------------------------------------------------
752void IGXMLScanner::resizeElemState()
753{
754        unsigned int newSize = fElemStateSize * 2;
755        unsigned int* newElemState = (unsigned int*) fMemoryManager->allocate
756        (
757                newSize * sizeof(unsigned int)
758        ); //new unsigned int[newSize];
759        unsigned int* newElemLoopState = (unsigned int*) fMemoryManager->allocate
760        (
761                newSize * sizeof(unsigned int)
762        ); //new unsigned int[newSize];
763
764        // Copy the existing values
765        unsigned int index = 0;
766        for (; index < fElemStateSize; index++)
767        {
768                newElemState[index] = fElemState[index];
769                newElemLoopState[index] = fElemLoopState[index];
770        }
771
772        for (; index < newSize; index++)
773                newElemLoopState[index] = newElemState[index] = 0;
774
775        // Delete the old array and udpate our members
776        fMemoryManager->deallocate(fElemState); //delete [] fElemState;
777        fMemoryManager->deallocate(fElemLoopState); //delete [] fElemState;
778        fElemState = newElemState;
779        fElemLoopState = newElemLoopState;
780        fElemStateSize = newSize;
781}
782
783// ---------------------------------------------------------------------------
784//  IGXMLScanner: Grammar preparsing
785// ---------------------------------------------------------------------------
786Grammar* IGXMLScanner::loadGrammar(const   InputSource& src
787                                                                   , const short        grammarType
788                                                                   , const bool         toCache)
789{
790        Grammar* loadedGrammar = 0;
791
792        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
793
794        try
795        {
796                fGrammarResolver->cacheGrammarFromParse(false);
797                // if the new grammar has to be cached, better use the already cached
798                // grammars, or the an exception will be thrown when caching an already
799                // cached grammar
800                fGrammarResolver->useCachedGrammarInParse(toCache);
801                fRootGrammar = 0;
802
803                // If fValScheme is set to auto, turn validation on.
804                fValidate = fValidate | (fValScheme == Val_Auto);
805
806                // Reset some status flags
807                fInException = false;
808                fStandalone = false;
809                fErrorCount = 0;
810                fHasNoDTD = true;
811                if (grammarType == Grammar::SchemaGrammarType)
812                {
813                        loadedGrammar = loadXMLSchemaGrammar(src, toCache);
814                }
815                else if (grammarType == Grammar::DTDGrammarType)
816                {
817                        loadedGrammar = loadDTDGrammar(src, toCache);
818                }
819        }
820        //  NOTE:
821        //
822        //  In all of the error processing below, the emitError() call MUST come
823        //  before the flush of the reader mgr, or it will fail because it tries
824        //  to find out the position in the XML source of the error.
825        catch(const XMLErrs::Codes)
826        {
827                // This is a 'first fatal error' type exit, so fall through
828        }
829        catch(const XMLValid::Codes)
830        {
831                // This is a 'first fatal error' type exit, so fall through
832        }
833        catch(const XMLException& excToCatch)
834        {
835                //  Emit the error and catch any user exception thrown from here. Make
836                //  sure in all cases we flush the reader manager.
837                fInException = true;
838                try
839                {
840                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
841                                emitError
842                                (
843                                        XMLErrs::XMLException_Warning
844                                        , excToCatch.getCode()
845                                        , excToCatch.getMessage()
846                                );
847                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
848                                emitError
849                                (
850                                        XMLErrs::XMLException_Fatal
851                                        , excToCatch.getCode()
852                                        , excToCatch.getMessage()
853                                );
854                        else
855                                emitError
856                                (
857                                        XMLErrs::XMLException_Error
858                                        , excToCatch.getCode()
859                                        , excToCatch.getMessage()
860                                );
861                }
862                catch(const OutOfMemoryException&)
863                {
864                        // This is a special case for out-of-memory
865                        // conditions, because resetting the ReaderMgr
866                        // can be problematic.
867                        resetReaderMgr.release();
868
869                        throw;
870                }
871        }
872        catch(const OutOfMemoryException&)
873        {
874                // This is a special case for out-of-memory
875                // conditions, because resetting the ReaderMgr
876                // can be problematic.
877                resetReaderMgr.release();
878
879                throw;
880        }
881
882        return loadedGrammar;
883}
884
885// ---------------------------------------------------------------------------
886//  IGXMLScanner: Grammar preparsing
887// ---------------------------------------------------------------------------
888void IGXMLScanner::resetCachedGrammar ()
889{
890        fCachedSchemaInfoList->removeAll();
891}
892
893// ---------------------------------------------------------------------------
894//  IGXMLScanner: Grammar preparsing
895// ---------------------------------------------------------------------------
896Grammar* IGXMLScanner::loadDTDGrammar( const InputSource& src,
897                                                                           const bool toCache)
898{
899        // Reset the validators
900        fDTDValidator->reset();
901        if (fValidatorFromUser)
902                fValidator->reset();
903
904        if (!fValidator->handlesDTD())
905        {
906                if (fValidatorFromUser && fValidate)
907                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
908                else
909                {
910                        fValidator = fDTDValidator;
911                }
912        }
913
914        fDTDGrammar = (DTDGrammar*) fGrammarResolver->getGrammar(XMLUni::fgDTDEntityString);
915
916        if (fDTDGrammar)
917        {
918                fDTDGrammar->reset();
919        }
920        else
921        {
922                fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager);
923                fGrammarResolver->putGrammar(fDTDGrammar);
924        }
925
926        fGrammar = fDTDGrammar;
927        fGrammarType = fGrammar->getGrammarType();
928        fValidator->setGrammar(fGrammar);
929
930        //  And for all installed handlers, send reset events. This gives them
931        //  a chance to flush any cached data.
932        if (fDocHandler)
933                fDocHandler->resetDocument();
934        if (fEntityHandler)
935                fEntityHandler->resetEntities();
936        if (fErrorReporter)
937                fErrorReporter->resetErrors();
938
939        // Clear out the id reference list
940        resetValidationContext();
941        // and clear out the darned undeclared DTD element pool...
942        fDTDElemNonDeclPool->removeAll();
943
944        if (toCache)
945        {
946                unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId());
947                const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId);
948
949                fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
950                ((XMLDTDDescription*) (fGrammar->getGrammarDescription()))->setSystemId(sysIdStr);
951                fGrammarResolver->putGrammar(fGrammar);
952        }
953
954        //  Handle the creation of the XML reader object for this input source.
955        //  This will provide us with transcoding and basic lexing services.
956        XMLReader* newReader = fReaderMgr.createReader
957        (
958                src
959                , false
960                , XMLReader::RefFrom_NonLiteral
961                , XMLReader::Type_General
962                , XMLReader::Source_External
963                , fCalculateSrcOfs
964                , fLowWaterMark
965        );
966
967        if (!newReader)
968        {
969                if (src.getIssueFatalErrorIfNotFound())
970                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
971                else
972                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
973        }
974
975        //  In order to make the processing work consistently, we have to
976        //  make this look like an external entity. So create an entity
977        //  decl and fill it in and push it with the reader, as happens
978        //  with an external entity. Put a janitor on it to insure it gets
979        //  cleaned up. The reader manager does not adopt them.
980        const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
981        DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
982        declDTD->setSystemId(src.getSystemId());
983        declDTD->setIsExternal(true);
984        Janitor<DTDEntityDecl> janDecl(declDTD);
985
986        // Mark this one as a throw at end
987        newReader->setThrowAtEnd(true);
988
989        // And push it onto the stack, with its pseudo name
990        fReaderMgr.pushReader(newReader, declDTD);
991
992        //  If we have a doc type handler and advanced callbacks are enabled,
993        //  call the doctype event.
994        if (fDocTypeHandler)
995        {
996                // Create a dummy root
997                DTDElementDecl* rootDecl = new (fGrammarPoolMemoryManager) DTDElementDecl
998                (
999                        gDTDStr
1000                        , XMLNamespaceResolver::fEmptyUriId
1001                        , DTDElementDecl::Any
1002                        , fGrammarPoolMemoryManager
1003                );
1004                rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
1005                rootDecl->setExternalElemDeclaration(true);
1006                Janitor<DTDElementDecl> janSrc(rootDecl);
1007
1008                fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false, true);
1009        }
1010
1011        // Create DTDScanner
1012        DTDScanner dtdScanner
1013        (
1014                (DTDGrammar*) fGrammar
1015                , fDocTypeHandler
1016                , fGrammarPoolMemoryManager
1017                , fMemoryManager
1018        );
1019        dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
1020
1021        // Tell it its not in an include section
1022        dtdScanner.scanExtSubsetDecl(false, true);
1023
1024        if (fValidate)
1025        {
1026                //  validate the DTD scan so far
1027                fValidator->preContentValidation(false, true);
1028        }
1029
1030        if (toCache)
1031                fGrammarResolver->cacheGrammars();
1032
1033        return fDTDGrammar;
1034}
1035
1036// ---------------------------------------------------------------------------
1037//  IGXMLScanner: Helper methods
1038// ---------------------------------------------------------------------------
1039
1040bool IGXMLScanner::checkNamespaceAttribute(const XMLSymbol & attribute, const XMLCh * value, bool declared, DatatypeValidator * & attrValidator)
1041{
1042    bool validate = fValidate & declared;
1043    bool tokenize = false;
1044
1045    if (likely(attribute.isXMLNS()))
1046    {
1047        attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
1048        return 1;
1049    }
1050    else // if (isXSI)
1051    {
1052        const gid_t localPartId = attribute.getLocalPartId();
1053
1054        switch (localPartId)
1055        {
1056            case XMLSymbolTable::Type:
1057                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_QNAME);
1058                break;
1059            case XMLSymbolTable::Nil:
1060                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_BOOLEAN);
1061                break;
1062            case XMLSymbolTable::SchemaLocation:
1063                tokenize = true;
1064            case XMLSymbolTable::NoNamespaceSchemaLocation:
1065                attrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYURI);
1066                // these values ought to be validated but the authors of Xerces reported a performance degradation of ~4%?
1067                // they opted to disable validation with the intention of doing a performance assessment of the anyuri datatype.
1068                break;
1069            default:
1070                return 0; // bound to the xsi namespace but is not one of the predefined xsi attributes
1071        }
1072    }
1073
1074    if (validate && attrValidator)
1075    {
1076        ValidationContext* const theContext = getValidationContext();
1077
1078        if (theContext)
1079        {
1080            try
1081            {
1082                if (tokenize)
1083                {
1084                    XMLStringTokenizer tokenizer(value, fMemoryManager);
1085                    while (tokenizer.hasMoreTokens())
1086                    {
1087                        attrValidator->validate
1088                        (
1089                            tokenizer.nextToken(),
1090                            theContext,
1091                            fMemoryManager
1092                        );
1093                    }
1094                }
1095                else
1096                {
1097                    attrValidator->validate
1098                    (
1099                        value,
1100                        theContext,
1101                        fMemoryManager
1102                    );
1103                }
1104            }
1105            catch (const XMLException& idve)
1106            {
1107                fValidator->emitError(XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
1108            }
1109        }
1110    }
1111
1112    return 1;
1113}
1114
1115bool IGXMLScanner::tokenizeAttributeValue
1116(
1117    const XMLCh * const             value
1118    , const XMLSize_t               length
1119    , XMLBuffer &                   toFill
1120)
1121{
1122    DEBUG_GRAMMAR_MESSAGE("tokenizeAttributeValue(" << value << ',' << length << ')')
1123
1124    // TODO: this is a very poor method of handling tokenization. It assumes that the value was improperly tokenized when
1125    // in all likelyhood the document is valid.
1126
1127    toFill.reset();
1128
1129    if (likely(length > 0))
1130    {
1131        // any non-space whitespace characters within the value must have been inserted by character reference expansion.
1132        // only iterate through actual spaces.
1133        XMLChIterator<chSpace> itr(value, length);
1134        // find the very first non-whitespace character.
1135        if (itr.nextc())
1136        {
1137            for (;;)
1138            {
1139                size_t pos = itr.pos();
1140                // are there any whitespace characters after the first whitespace character?
1141                if (!itr.next())
1142                {
1143                    toFill.append(&value[pos], length - pos);
1144                    break;
1145                }
1146                toFill.append(&value[pos], itr.pos() - pos);
1147
1148                // get the position of the next non-whitespace character
1149                if (!itr.nextc())
1150                {
1151                    break;
1152                }
1153                // if there is one, then add a space between the tokens
1154                toFill.append(chSpace);
1155            }
1156        }
1157    }
1158
1159    return (toFill.getLen() != length);
1160}
1161
1162void IGXMLScanner::endElementPSVI(SchemaElementDecl* const elemDecl, DatatypeValidator * const memberDV)
1163{
1164#if 0
1165    PSVIElement::ASSESSMENT_TYPE validationAttempted;
1166        PSVIElement::VALIDITY_STATE validity = PSVIElement::VALIDITY_NOTKNOWN;
1167
1168        if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fFullValidationDepth)
1169    {
1170                validationAttempted = PSVIElement::VALIDATION_FULL;
1171    }
1172        else if (fPSVIElemContext.fElemDepth > fPSVIElemContext.fNoneValidationDepth)
1173    {
1174                validationAttempted = PSVIElement::VALIDATION_NONE;
1175    }
1176        else
1177        {
1178                validationAttempted  = PSVIElement::VALIDATION_PARTIAL;
1179        fPSVIElemContext.fFullValidationDepth = fPSVIElemContext.fNoneValidationDepth = fPSVIElemContext.fElemDepth - 1;
1180        }
1181
1182        if (fValidate && elemDecl->isDeclared())
1183        {
1184        validity = (fPSVIElemContext.fErrorOccurred) ? PSVIElement::VALIDITY_INVALID : PSVIElement::VALIDITY_VALID;
1185        }
1186
1187        XSTypeDefinition* typeDef = 0;
1188        bool isMixed = false;
1189        if (fPSVIElemContext.fCurrentTypeInfo)
1190        {
1191                typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentTypeInfo);
1192                SchemaElementDecl::ModelTypes modelType = (SchemaElementDecl::ModelTypes)fPSVIElemContext.fCurrentTypeInfo->getContentType();
1193        isMixed = (modelType == SchemaElementDecl::Mixed_Simple || modelType == SchemaElementDecl::Mixed_Complex);
1194        }
1195        else if (fPSVIElemContext.fCurrentDV)
1196    {
1197                typeDef = (XSTypeDefinition*) fModel->getXSObject(fPSVIElemContext.fCurrentDV);
1198    }
1199
1200        XMLCh* canonicalValue = 0;
1201    if (fPSVIElemContext.fNormalizedValue && !isMixed && validity == PSVIElement::VALIDITY_VALID)
1202        {
1203                if (memberDV)
1204                        canonicalValue = (XMLCh*) memberDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager);
1205                else if (fPSVIElemContext.fCurrentDV)
1206                        canonicalValue = (XMLCh*) fPSVIElemContext.fCurrentDV->getCanonicalRepresentation(fPSVIElemContext.fNormalizedValue, fMemoryManager);
1207        }
1208
1209        fPSVIElement->reset
1210        (
1211                validity
1212                , validationAttempted
1213                , fRootElemName
1214                , fPSVIElemContext.fIsSpecified
1215        , (elemDecl->isDeclared()) ? (XSElementDeclaration*) fModel->getXSObject(elemDecl) : 0
1216                , typeDef
1217                , (memberDV) ? (XSSimpleTypeDefinition*) fModel->getXSObject(memberDV) : 0
1218                , fModel
1219                , elemDecl->getDefaultValue()
1220                , fPSVIElemContext.fNormalizedValue
1221                , canonicalValue
1222        );
1223
1224        fPSVIHandler->handleElementPSVI
1225        (
1226                elemDecl->getBaseName()
1227                , fUriResolver->getUriForId(elemDecl->getURI())
1228                , fPSVIElement
1229        );
1230
1231        // decrease element depth
1232        fPSVIElemContext.fElemDepth--;
1233#endif
1234}
1235
1236void IGXMLScanner::resetPSVIElemContext()
1237{
1238        fPSVIElemContext.fIsSpecified = false;
1239        fPSVIElemContext.fErrorOccurred = false;
1240        fPSVIElemContext.fElemDepth = -1;
1241        fPSVIElemContext.fFullValidationDepth = -1;
1242        fPSVIElemContext.fNoneValidationDepth = -1;
1243        fPSVIElemContext.fCurrentDV = 0;
1244        fPSVIElemContext.fCurrentTypeInfo = 0;
1245        fPSVIElemContext.fNormalizedValue = 0;
1246}
1247
1248bool IGXMLScanner::expandEntityReference
1249(
1250    const XMLCh *                   entityReference
1251    , const XMLSize_t               /* length */
1252    , const bool                    inAttributeValue
1253    , XMLBuffer &                   toFill
1254    , bool      &                   isPredefined
1255    , bool      &                   isExternal
1256    , XMLFileLoc &                  line
1257    , XMLFileLoc &                  column
1258)
1259{
1260    // here's where we need to check if there's a SecurityManager,
1261        // how many entity references we've had
1262    if (fSecurityManager && ++fEntityExpansionCount > fEntityExpansionLimit)
1263        {
1264                XMLCh expLimStr[32];
1265                XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
1266                emitError
1267                (
1268                        XMLErrs::EntityExpansionLimitExceeded
1269                        , expLimStr
1270                );
1271                // there seems nothing  better to be done than to reset the entity expansion counter
1272                fEntityExpansionCount = 0;
1273        }
1274
1275        // Look up the name in the general entity pool
1276    XMLEntityDecl * decl = fDTDGrammar->getEntityDecl(entityReference);
1277        InputSource * srcUsed;
1278
1279        // If it does not exist, then obviously an error
1280        if (unlikely(!decl))
1281        {
1282                // XML 1.0 Section 4.1
1283                // Well-formedness Constraint for entity not found:
1284        //   In a document without any DTD, a document with only an internal DTD subset that contains no parameter entity references,
1285                //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
1286                //      or a parameter entity
1287                //
1288                // Else it's Validity Constraint
1289                if (fStandalone || fHasNoDTD)
1290                {
1291            emitError(XMLErrs::EntityNotFound, entityReference);
1292                }
1293                else if (fValidate)
1294                {
1295            fValidator->emitError(XMLValid::VC_EntityNotFound, entityReference);
1296                }
1297                return 0;
1298        }
1299
1300        // XML 1.0 Section 4.1
1301        //  If we are a standalone document, then it has to have been declared
1302        //  in the internal subset.
1303        if (unlikely(fStandalone && !decl->getDeclaredInIntSubset()))
1304        {
1305        emitError(XMLErrs::IllegalRefInStandalone, entityReference);
1306        }
1307
1308        XMLReader * reader;
1309
1310        if (unlikely(decl->isExternal()))
1311        {
1312        if (unlikely(inAttributeValue))
1313        {
1314            emitError(XMLErrs::NoExtRefsInAttValue);
1315            return 0;
1316        }
1317
1318                // If its unparsed, then its not valid here
1319                if (unlikely(decl->isUnparsed()))
1320                {
1321            emitError(XMLErrs::NoUnparsedEntityRefs, entityReference);
1322                        return 0;
1323                }
1324
1325                // And now create a reader to read this entity
1326                reader = fReaderMgr.createReader
1327                (
1328                        decl->getBaseURI()
1329                        , decl->getSystemId()
1330                        , decl->getPublicId()
1331                        , false
1332                        , XMLReader::RefFrom_NonLiteral
1333                        , XMLReader::Type_General
1334                        , XMLReader::Source_External
1335                        , srcUsed
1336                        , fCalculateSrcOfs
1337                        , fLowWaterMark
1338                        , fDisableDefaultEntityResolution
1339                );
1340
1341                // Put a janitor on the source so it gets cleaned up on exit
1342                Janitor<InputSource> janSrc(srcUsed);
1343
1344                //  If the creation failed, and its not because the source was empty,
1345                //  then emit an error and return.
1346                if (!reader)
1347                {
1348                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed ? srcUsed->getSystemId() : decl->getSystemId(), fMemoryManager);
1349                }
1350
1351        fReaderMgr.pushReader(reader, decl);
1352
1353        // If it starts with the XML string, then parse a text decl
1354        if (checkXMLDecl(true))
1355        {
1356            scanXMLDecl(Decl_Text);
1357        }
1358
1359        reader = fReaderMgr.getCurrentReader();
1360        // get the line, column and version information from the Reader; one of these will likely
1361        // differ from the source document.
1362        line = reader->getLineNumber();
1363        column = reader->getColumnNumber();
1364        isExternal = true;
1365        // now obtain the entire the value
1366        reader->fill(toFill);
1367        }
1368        else // internal entity
1369        {
1370                //  If its a predefined entity reference...
1371                if (decl->getIsSpecialChar())
1372                {
1373            toFill.set(decl->getValue()[0]);
1374            isPredefined = 1;
1375                }
1376        else
1377        {
1378            // line  = 0;
1379            // column = 0;
1380            toFill.set(decl->getValue(), decl->getValueLen());
1381        }
1382        }
1383        return 1;
1384}
1385
1386
1387
1388void IGXMLScanner::reportRequiredAttribute(const DTDAttDef & attDef)
1389{
1390    XMLBufBid bbAttName(&fBufMgr);
1391    XMLBuffer & bAttName = bbAttName.getBuffer();
1392    const XMLCh * fullName = attDef.getFullName();
1393    if (fDoNamespaces)
1394    {
1395        int colonInd = -1;
1396        const XMLCh * uri = getURIForQName(fullName, colonInd);
1397        if (uri)
1398        {
1399            bAttName.set(chOpenCurly);
1400            bAttName.append(uri);
1401            bAttName.append(chCloseCurly);
1402            bAttName.append(&fullName[colonInd + 1]);
1403            fullName = bAttName.getRawBuffer();
1404        }
1405    }
1406    fDTDValidator->emitError(XMLValid::RequiredAttrNotProvided, fullName);
1407}
1408
1409void IGXMLScanner::reportAttributeNotDefinedForElement(const DTDElementDecl & elemDecl, const XMLCh * attributeName)
1410{
1411    XMLBufBid bbAttName(&fBufMgr);
1412    XMLBuffer & bAttName = bbAttName.getBuffer();
1413    if (fDoNamespaces)
1414    {
1415        int colonInd = -1;
1416        const XMLCh * uri = getURIForQName(attributeName, colonInd);
1417        if (uri)
1418        {
1419            bAttName.set(chOpenCurly);
1420            bAttName.append(uri);
1421            bAttName.append(chCloseCurly);
1422            bAttName.append(&attributeName[colonInd + 1]);
1423            attributeName = bAttName.getRawBuffer();
1424        }
1425    }
1426    fDTDValidator->emitError(XMLValid::AttNotDefinedForElement, attributeName, elemDecl.getFullName());
1427}
1428
1429void IGXMLScanner::reportRequiredAttribute(const SchemaAttDef & attDef)
1430{
1431    XMLBufBid bbAttName(&fBufMgr);
1432    XMLBuffer & bAttName = bbAttName.getBuffer();
1433    const XMLCh * fullName = attDef.getFullName();
1434    if (fDoNamespaces)
1435    {
1436        int colonInd = -1;
1437        const XMLCh * uri = getURIForQName(fullName, colonInd);
1438        if (uri)
1439        {
1440            bAttName.set(chOpenCurly);
1441            bAttName.append(uri);
1442            bAttName.append(chCloseCurly);
1443            bAttName.append(&fullName[colonInd + 1]);
1444            fullName = bAttName.getRawBuffer();
1445        }
1446    }
1447    fSchemaValidator->emitError(XMLValid::RequiredAttrNotProvided, fullName);
1448}
1449
1450XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.