source: icXML/icXML-devel/src/icxercesc/internal/IGXMLScanner2.cpp @ 2720

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

Initial check-in of icXML 0.8 source files

File size: 35.7 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: IGXMLScanner2.cpp 925236 2010-03-19 14:29:47Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  This file holds some of the grunt work methods of IGXMLScanner.cpp to keep
24//  it a little more readable.
25// ---------------------------------------------------------------------------
26
27// ---------------------------------------------------------------------------
28//  Includes
29// ---------------------------------------------------------------------------
30#include <xercesc/internal/IGXMLScanner.hpp>
31#include <xercesc/internal/EndOfEntityException.hpp>
32#include <xercesc/util/UnexpectedEOFException.hpp>
33#include <xercesc/util/XMLUri.hpp>
34#include <xercesc/framework/LocalFileInputSource.hpp>
35#include <xercesc/framework/URLInputSource.hpp>
36#include <xercesc/framework/XMLDocumentHandler.hpp>
37#include <xercesc/framework/XMLEntityHandler.hpp>
38#include <xercesc/framework/XMLPScanToken.hpp>
39#include <xercesc/framework/XMLRefInfo.hpp>
40#include <xercesc/framework/XMLGrammarPool.hpp>
41#include <xercesc/framework/psvi/XSAnnotation.hpp>
42#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
43#include <xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp>
44#include <xercesc/validators/datatype/DatatypeValidator.hpp>
45#include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp>
46#include <xercesc/validators/schema/TraverseSchema.hpp>
47#include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
48#include <xercesc/validators/schema/XSDDOMParser.hpp>
49#include <xercesc/validators/schema/identity/IdentityConstraintHandler.hpp>
50#include <xercesc/validators/schema/identity/ValueStore.hpp>
51#include <icxmlc/XMLParallelTokenizer.hpp>
52
53XERCES_CPP_NAMESPACE_BEGIN
54
55//  This method will reset the scanner data structures, and related plugged
56//  in stuff, for a new scan session. We get the input source for the primary
57//  XML entity, create the reader for it, and push it on the stack so that
58//  upon successful return from here we are ready to go.
59void IGXMLScanner::scanReset(const InputSource& src)
60{
61        //  This call implicitly tells us that we are going to reuse the scanner
62        //  if it was previously used. So tell the validator to reset itself.
63        //
64        //  But, if the fUseCacheGrammar flag is set, then don't reset it.
65        //
66        //  NOTE:   The ReaderMgr is flushed on the way out, because that is
67        //          required to insure that files are closed.
68        fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar);
69        fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar);
70
71        // Clear transient schema info list.
72        //
73        fSchemaInfoList->removeAll();
74
75        // fModel may need updating, as fGrammarResolver could have cleaned it
76        if (fModel && getPSVIHandler())
77        {
78                fModel = fGrammarResolver->getXSModel();
79        }
80
81        do
82        {
83                XMLDTDDescriptionImpl theDTDDescription(XMLUni::fgDTDEntityString, fMemoryManager);
84                fDTDGrammar = (DTDGrammar*) fGrammarResolver->getGrammar(&theDTDDescription);
85        } while (0);
86
87        if (!fDTDGrammar)
88        {
89                fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager);
90                fGrammarResolver->putGrammar(fDTDGrammar);
91        }
92        else
93        {
94                fDTDGrammar->reset();
95        }
96        fGrammar = fDTDGrammar;
97        fGrammarType = fGrammar->getGrammarType();
98        fRootGrammar = 0;
99
100        if (fValidatorFromUser)
101        {
102                if (fValidator->handlesDTD())
103                {
104                        fValidator->setGrammar(fGrammar);
105                }
106                else if (fValidator->handlesSchema())
107                {
108                        fSchemaValidator->setErrorReporter(fErrorReporter);
109                        fSchemaValidator->setGrammarResolver(fGrammarResolver);
110                        fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
111                }
112        }
113        else
114        {
115                // set fValidator as fDTDValidator
116                fValidator = fDTDValidator;
117                fValidator->setGrammar(fGrammar);
118        }
119
120        // Reset validation
121        fValidate = (fValScheme == Val_Always) ? true : false;
122
123        // Ignore skipDTDValidation flag if no schema processing is taking place */
124        fSkipDTDValidation = fSkipDTDValidation && fDoSchema;
125
126        //  And for all installed handlers, send reset events. This gives them
127        //  a chance to flush any cached data.
128        if (fDocHandler)
129                fDocHandler->resetDocument();
130        if (fEntityHandler)
131                fEntityHandler->resetEntities();
132        if (fErrorReporter)
133                fErrorReporter->resetErrors();
134
135        // Clear out the id reference list
136        resetValidationContext();
137
138        // Reset the Root Element Name
139        fRootElemName = 0;
140
141        // Reset IdentityConstraints
142        if (fICHandler)
143                fICHandler->reset();
144
145        // Reset some status flags
146        fInException = false;
147        fStandalone = false;
148        fErrorCount = 0;
149        fHasNoDTD = true;
150
151        // Reset PSVI context
152        // note that we always need this around for DOMTypeInfo
153        if (!fPSVIElement)
154                fPSVIElement = new (fMemoryManager) PSVIElement(fMemoryManager);
155
156        if (!fErrorStack)
157        {
158                fErrorStack = new (fMemoryManager) ValueStackOf<bool>(8, fMemoryManager);
159        }
160        else
161        {
162                fErrorStack->removeAllElements();
163        }
164
165        resetPSVIElemContext();
166
167        // Reset the validators
168        fDTDValidator->reset();
169        fDTDValidator->setErrorReporter(fErrorReporter);
170        fSchemaValidator->reset();
171        fSchemaValidator->setErrorReporter(fErrorReporter);
172        fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
173        fSchemaValidator->setGrammarResolver(fGrammarResolver);
174        if (fValidatorFromUser)
175                fValidator->reset();
176
177        //  Handle the creation of the XML reader object for this input source.
178        //  This will provide us with transcoding and basic lexing services.
179        XMLReader* newReader = fReaderMgr.createReader
180        (
181                src
182                , true
183                , XMLReader::RefFrom_NonLiteral
184                , XMLReader::Type_General
185                , XMLReader::Source_External
186                , fCalculateSrcOfs
187                , fLowWaterMark
188        );
189
190        if (!newReader)
191        {
192                if (src.getIssueFatalErrorIfNotFound())
193                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
194                else
195                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
196        }
197
198        // Push this read onto the reader manager
199        fReaderMgr.pushReader(newReader, 0);
200
201        // and reset security-related things if necessary:
202        if(fSecurityManager != 0)
203        {
204                fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit();
205                fEntityExpansionCount = 0;
206        }
207        fDTDElemNonDeclPool->removeAll();
208}
209
210void IGXMLScanner::parseSchemaLocation
211(
212        const XMLCh* const schemaLocationStr
213        , const XMLSize_t schemaLocationStrLen
214        , bool ignoreLoadSchema
215)
216{
217        XMLCh * locStr = XMLString::replicate(schemaLocationStr, schemaLocationStrLen, fMemoryManager);
218        ArrayJanitor<XMLCh> janLoc(locStr, fMemoryManager);
219        XMLParallelTokenizer locationPairs(locStr, schemaLocationStrLen);
220        locationPairs.scanWhitespace();
221        const XMLSize_t size = locationPairs.size();
222
223        if ((size & 1) == 0)
224        {
225                // We need a buffer to normalize the attribute value into
226                for(XMLSize_t i = 0; i < size; i += 2)
227                {
228                        resolveSchemaGrammar
229                        (
230                                locationPairs[i + 1]
231                                , locationPairs[i]
232                                , ignoreLoadSchema
233                        );
234                }
235        }
236        else
237        {
238                emitError(XMLErrs::BadSchemaLocation);
239        }
240}
241
242void IGXMLScanner::resolveSchemaGrammar
243(
244        const XMLCh* const loc
245        , const XMLCh* const uri
246        , bool ignoreLoadSchema
247)
248{
249        Grammar* grammar = 0;
250
251        DEBUG_GRAMMAR_MESSAGE("IGXMLScanner::resolveSchemaGrammar(" << loc << ',' << uri << ',' << ignoreLoadSchema << ')');
252
253        XMLSchemaDescriptionImpl theSchemaDescription(uri, fMemoryManager);
254        theSchemaDescription.setLocationHints(loc);
255        grammar = fGrammarResolver->getGrammar(&theSchemaDescription);
256
257        // If multi-import is enabled, make sure the existing grammar came
258        // from the import directive. Otherwise we may end up reloading
259        // the same schema that came from the external grammar pool. Ideally,
260        // we would move fSchemaInfoList to XMLGrammarPool so that it survives
261        // the destruction of the scanner in which case we could rely on the
262        // same logic we use to weed out duplicate schemas below.
263        //
264        if (!grammar ||
265                 grammar->getGrammarType() == Grammar::DTDGrammarType ||
266                 (getHandleMultipleImports() &&
267                 ((XMLSchemaDescription*)grammar->getGrammarDescription())->getContextType() == XMLSchemaDescription::CONTEXT_IMPORT))
268        {
269                if (fLoadSchema || ignoreLoadSchema)
270                {
271                        XSDDOMParser parser(0, fMemoryManager, 0);
272                        parser.getScanner()->setUriResolver(getUriResolver());
273                        parser.setValidationScheme(XercesDOMParser::Val_Never);
274                        parser.setDoNamespaces(true);
275                        parser.setUserEntityHandler(fEntityHandler);
276                        parser.setUserErrorReporter(fErrorReporter);
277
278                        const XMLCh* normalizedURI = loc;
279
280                        // Create a buffer for expanding the system id
281                        XMLBufBid bbSys(&fBufMgr);
282                        XMLBuffer& expSysId = bbSys.getBuffer();
283
284                        //  Allow the entity handler to expand the system id if they choose
285                        //  to do so.
286                        InputSource* srcToFill = 0;
287                        if (fEntityHandler)
288                        {
289                                if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
290                                {
291                                        expSysId.set(normalizedURI);
292                                }
293
294                                ReaderMgr::LastExtEntityInfo lastInfo;
295                                fReaderMgr.getLastExtEntityInfo(lastInfo);
296                                XMLResourceIdentifier resourceIdentifier
297                                (
298                                        XMLResourceIdentifier::SchemaGrammar
299                                        , expSysId.getRawBuffer()
300                                        , uri
301                                        , XMLUni::fgZeroLenString
302                                        , lastInfo.systemId
303                                        , &fReaderMgr
304                                );
305                                srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
306                        }
307                        else
308                        {
309                                expSysId.set(normalizedURI);
310                        }
311
312                        //  If they didn't create a source via the entity handler, then we
313                        //  have to create one on our own.
314                        if (!srcToFill)
315                        {
316                                if (fDisableDefaultEntityResolution)
317                                        return;
318
319                                ReaderMgr::LastExtEntityInfo lastInfo;
320                                fReaderMgr.getLastExtEntityInfo(lastInfo);
321
322                                XMLURL urlTmp(fMemoryManager);
323                                if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) || urlTmp.isRelative())
324                                {
325                                        if (!fStandardUriConformant)
326                                        {
327                                                XMLBufBid  ddSys(&fBufMgr);
328                                                XMLBuffer& resolvedSysId = ddSys.getBuffer();
329                                                XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
330
331                                                srcToFill = new (fMemoryManager) LocalFileInputSource
332                                                (
333                                                        lastInfo.systemId
334                                                        , resolvedSysId.getRawBuffer()
335                                                        , fMemoryManager
336                                                );
337                                        }
338                                        else
339                                        {
340                                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
341                                        }
342                                }
343                                else
344                                {
345                                        if (fStandardUriConformant && urlTmp.hasInvalidChar())
346                                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
347                                        srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
348                                }
349                        }
350
351                        // Put a janitor on the input source
352                        Janitor<InputSource> janSrc(srcToFill);
353
354                        // Check if this exact schema has already been seen.
355                        //
356                        const XMLCh* sysId = srcToFill->getSystemId();
357                        unsigned int uriId = fUriResolver->resolveUriId(uri);
358                        SchemaInfo* importSchemaInfo = 0;
359
360                        if (fUseCachedGrammar)
361                                importSchemaInfo = fCachedSchemaInfoList->get(sysId, uriId);
362
363                        if (!importSchemaInfo && !fToCacheGrammar)
364                                importSchemaInfo = fSchemaInfoList->get(sysId, uriId);
365
366                        if (importSchemaInfo)
367                        {
368                                // We haven't added any new grammars so it is safe to just
369                                // return.
370                                return;
371                        }
372
373                        // Should just issue warning if the schema is not found
374                        bool flag = srcToFill->getIssueFatalErrorIfNotFound();
375                        srcToFill->setIssueFatalErrorIfNotFound(false);
376
377                        parser.parse(*srcToFill);
378
379                        // Reset the InputSource
380                        srcToFill->setIssueFatalErrorIfNotFound(flag);
381
382                        if (parser.getSawFatal() && fExitOnFirstFatal)
383                                emitError(XMLErrs::SchemaScanFatalError);
384
385                        DOMDocument* document = parser.getDocument(); //Our Grammar
386
387                        if (document)
388                        {
389                                DOMElement * root = document->getDocumentElement(); // This is what we pass to TraverserSchema
390
391                                if (root)
392                                {
393                                        const XMLCh* newUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
394                                        bool newGrammar = false;
395
396                                        if (!XMLString::equals(newUri, uri))
397                                        {
398                                                if (fValidate || fValScheme == Val_Auto)
399                                                {
400                                                        fValidator->emitError(XMLValid::WrongTargetNamespace, loc, uri);
401                                                }
402
403                                                grammar = fGrammarResolver->getGrammar(newUri);
404                                                newGrammar = true;
405                                        }
406
407                                        if (!grammar ||
408                                                grammar->getGrammarType() == Grammar::DTDGrammarType ||
409                                                (getHandleMultipleImports() &&
410                                                 ((XMLSchemaDescription*)grammar->getGrammarDescription())->
411                                                 getContextType () == XMLSchemaDescription::CONTEXT_IMPORT))
412                                        {
413
414                                                // If we switched namespace URI, recheck the schema info.
415                                                //
416                                                if (newGrammar)
417                                                {
418                                                        unsigned int newUriId =
419                                                                fUriResolver->resolveUriId(newUri);
420
421                                                        if (fUseCachedGrammar)
422                                                        {
423                                                                importSchemaInfo = fCachedSchemaInfoList->get(sysId, newUriId);
424                                                        }
425                                                        if (!importSchemaInfo && !fToCacheGrammar)
426                                                                importSchemaInfo = fSchemaInfoList->get(sysId, newUriId);
427
428                                                        if (importSchemaInfo)
429                                                                return;
430                                                }
431
432                                                //  Since we have seen a grammar, set our validation flag
433                                                //  at this point if the validation scheme is auto
434                                                if (fValScheme == Val_Auto && !fValidate)
435                                                {
436                                                        fValidate = true;
437                                                        #ifdef __GNUC__
438                                                        #warning "This should probably call fElemStack.setValidationFlag(true) but we will not be at the correct element in the stack"
439                                                        #endif
440                                                }
441
442
443                                                // we have seen a schema, so set up the fValidator as fSchemaValidator
444                                                if (!fValidator->handlesSchema())
445                                                {
446                                                        if (fValidatorFromUser)
447                                                        {
448                                                                // the fValidator is from user
449                                                                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
450                                                        }
451                                                        else
452                                                        {
453                                                                fValidator = fSchemaValidator;
454                                                        }
455                                                }
456
457                                                const bool grammarFound =
458                                                         grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType;
459
460                                                SchemaGrammar * schemaGrammar;
461
462                                                if (grammarFound)
463                                                {
464                                                        schemaGrammar = (SchemaGrammar*)grammar;
465                                                }
466                                                else
467                                                {
468                                                        assert (fGrammarPoolMemoryManager != NULL);
469                                                        schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
470                                                }
471
472                                                XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription();
473
474                                                gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE);
475                                                gramDesc->setLocationHints(sysId);
476
477
478                                                TraverseSchema traverseSchema
479                                                (
480                                                        root
481                                                        , NULL
482                                                        , schemaGrammar
483                                                        , fGrammarResolver
484                                                        , fUseCachedGrammar ? fCachedSchemaInfoList : fSchemaInfoList
485                                                        , fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList
486                                                        , this
487                                                        , sysId
488                                                        , fEntityHandler
489                                                        , fErrorReporter
490                                                        , fMemoryManager
491                                                        , grammarFound
492                                                );
493
494                                                // Reset the now invalid schema roots in the collected
495                                                // schema info entries.
496                                                RefHash2KeysTableOfEnumerator<SchemaInfo> i
497                                                (
498                                                        fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList
499                                                );
500
501                                                while (i.hasMoreElements())
502                                                {
503                                                        i.nextElement().resetRoot();
504                                                }
505
506                                                if (fGrammarType == Grammar::DTDGrammarType)
507                                                {
508                                                        fGrammar = schemaGrammar;
509                                                        fGrammarType = Grammar::SchemaGrammarType;
510                                                        fValidator->setGrammar(fGrammar);
511                                                }
512
513                                                if (fValidate)
514                                                {
515                                                        // validate the Schema scan so far
516                                                        fValidator->preContentValidation(false);
517                                                }
518                                        }
519                                }
520                        }
521                }
522        }
523        else
524        {
525                //  Since we have seen a grammar, set our validation flag
526                //  at this point if the validation scheme is auto
527                if (fValScheme == Val_Auto && !fValidate)
528                {
529                        fValidate = true;
530                        #ifdef __GNUC__
531                        #warning "This should probably call fElemStack.setValidationFlag(true) but we will not be at the correct element in the stack"
532                        #endif
533                }
534
535                // we have seen a schema, so set up the fValidator as fSchemaValidator
536                if (!fValidator->handlesSchema())
537                {
538                        if (fValidatorFromUser)
539                        {
540                                // the fValidator is from user
541                                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
542                        }
543                        else
544                        {
545                                fValidator = fSchemaValidator;
546                                DEBUG_GRAMMAR_MESSAGE("fValidator=" << (size_t)(fValidator) << "@" << __FILE__ << '.' << __LINE__);
547                        }
548                }
549
550                if (fGrammarType == Grammar::DTDGrammarType)
551                {
552                        fGrammar = grammar;
553                        fGrammarType = Grammar::SchemaGrammarType;
554                        fValidator->setGrammar(fGrammar);
555                }
556        }
557
558        // fModel may need updating:
559        if (getPSVIHandler())
560        {
561                fModel = fGrammarResolver->getXSModel();
562        }
563}
564
565InputSource* IGXMLScanner::resolveSystemId(const XMLCh* const sysId
566                                                                                  ,const XMLCh* const pubId)
567{
568        DEBUG_GRAMMAR_MESSAGE("IGXMLScanner::resolveSystemId(" << sysId << ',' << pubId << ')');
569
570        //Normalize sysId
571        XMLBufBid nnSys(&fBufMgr);
572        XMLBuffer& normalizedSysId = nnSys.getBuffer();
573        XMLString::removeChar(sysId, 0xFFFF, normalizedSysId);
574        const XMLCh* normalizedURI = normalizedSysId.getRawBuffer();
575
576        // Create a buffer for expanding the system id
577        XMLBufBid bbSys(&fBufMgr);
578        XMLBuffer& expSysId = bbSys.getBuffer();
579
580        //  Allow the entity handler to expand the system id if they choose
581        //  to do so.
582        InputSource* srcToFill = 0;
583        if (fEntityHandler)
584        {
585                if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
586                        expSysId.set(normalizedURI);
587
588                ReaderMgr::LastExtEntityInfo lastInfo;
589                fReaderMgr.getLastExtEntityInfo(lastInfo);
590                XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity,
591                                                          expSysId.getRawBuffer(), 0, pubId, lastInfo.systemId,
592                                                          &fReaderMgr);
593                srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
594        }
595        else
596        {
597                expSysId.set(normalizedURI);
598        }
599
600        //  If they didn't create a source via the entity handler, then we
601        //  have to create one on our own.
602        if (!srcToFill)
603        {
604                if (fDisableDefaultEntityResolution)
605                        return srcToFill;
606
607                ReaderMgr::LastExtEntityInfo lastInfo;
608                fReaderMgr.getLastExtEntityInfo(lastInfo);
609
610                XMLURL urlTmp(fMemoryManager);
611                if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) ||
612                        (urlTmp.isRelative()))
613                {
614                        if (!fStandardUriConformant)
615                        {
616                                XMLBufBid  ddSys(&fBufMgr);
617                                XMLBuffer& resolvedSysId = ddSys.getBuffer();
618                                XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
619
620                                srcToFill = new (fMemoryManager) LocalFileInputSource
621                                (
622                                        lastInfo.systemId
623                                        , resolvedSysId.getRawBuffer()
624                                        , fMemoryManager
625                                );
626                        }
627                        else
628                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
629                }
630                else
631                {
632                        if (fStandardUriConformant && urlTmp.hasInvalidChar())
633                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
634                        srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
635                }
636        }
637
638        return srcToFill;
639}
640
641
642// ---------------------------------------------------------------------------
643//  IGXMLScanner: Private grammar preparsing methods
644// ---------------------------------------------------------------------------
645Grammar* IGXMLScanner::loadXMLSchemaGrammar(const InputSource& src,
646                                                                                        const bool toCache)
647{
648        // Reset the validators
649        fSchemaValidator->reset();
650        fSchemaValidator->setErrorReporter(fErrorReporter);
651        fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
652        fSchemaValidator->setGrammarResolver(fGrammarResolver);
653
654        if (fValidatorFromUser)
655                fValidator->reset();
656
657        if (!fValidator->handlesSchema())
658        {
659                if (fValidatorFromUser && fValidate)
660                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
661                else
662                {
663                        fValidator = fSchemaValidator;
664                        DEBUG_GRAMMAR_MESSAGE("fValidator=" << (size_t)(fValidator) << "@" << __FILE__ << '.' << __LINE__);
665                }
666        }
667
668        XSDDOMParser parser(0, fMemoryManager, 0);
669
670        parser.setValidationScheme(XercesDOMParser::Val_Never);
671        parser.setDoNamespaces(true);
672        parser.setUserEntityHandler(fEntityHandler);
673        parser.setUserErrorReporter(fErrorReporter);
674
675        // Should just issue warning if the schema is not found
676        bool flag = src.getIssueFatalErrorIfNotFound();
677        ((InputSource&) src).setIssueFatalErrorIfNotFound(false);
678
679        parser.parse(src);
680
681        // Reset the InputSource
682        ((InputSource&) src).setIssueFatalErrorIfNotFound(flag);
683
684        if (parser.getSawFatal() && fExitOnFirstFatal)
685                emitError(XMLErrs::SchemaScanFatalError);
686
687        DOMDocument* document = parser.getDocument(); //Our Grammar
688
689        if (document != 0)
690        {
691                DOMElement* root = document->getDocumentElement(); // This is what we pass to TraverserSchema
692                if (root != 0)
693                {
694                        const XMLCh* nsUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
695                        Grammar* grammar = fGrammarResolver->getGrammar(nsUri);
696
697                        // Check if this exact schema has already been seen.
698                        //
699                        const XMLCh* sysId = src.getSystemId();
700                        SchemaInfo* importSchemaInfo = 0;
701
702                        if (grammar)
703                        {
704                                if (nsUri && *nsUri)
705                                        importSchemaInfo = fCachedSchemaInfoList->get(sysId, fUriResolver->resolveUriId(nsUri));
706                                else
707                                        importSchemaInfo = fCachedSchemaInfoList->get(sysId, fUriResolver->getEmptyUriId());
708                        }
709
710                        if (!importSchemaInfo)
711                        {
712                                bool grammarFound = grammar &&
713                                                                        grammar->getGrammarType() == Grammar::SchemaGrammarType &&
714                                                                        getHandleMultipleImports();
715
716                                SchemaGrammar* schemaGrammar;
717
718                                if (grammarFound)
719                                        schemaGrammar = (SchemaGrammar*) grammar;
720                                else
721                                        schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
722
723                                XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription();
724                                gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE);
725                                gramDesc->setLocationHints(sysId);
726
727                                TraverseSchema traverseSchema
728                                (
729                                        root
730                                        , NULL
731                                        , schemaGrammar
732                                        , fGrammarResolver
733                                        , fCachedSchemaInfoList
734                                        , toCache ? fCachedSchemaInfoList : fSchemaInfoList
735                                        , this
736                                        , sysId
737                                        , fEntityHandler
738                                        , fErrorReporter
739                                        , fMemoryManager
740                                        , grammarFound
741                                );
742
743                                grammar = schemaGrammar;
744
745                                // Reset the now invalid schema roots in the collected
746                                // schema info entries.
747                                //
748                                RefHash2KeysTableOfEnumerator<SchemaInfo> i
749                                (
750                                                toCache ? fCachedSchemaInfoList : fSchemaInfoList
751                                );
752
753                                while (i.hasMoreElements ())
754                                {
755                                        i.nextElement().resetRoot ();
756                                }
757                        }
758
759                        if (fValidate)
760                        {
761                                //  validate the Schema scan so far
762                                fValidator->setGrammar(grammar);
763                                fValidator->preContentValidation(false);
764                        }
765
766                        if (toCache)
767                        {
768                                fGrammarResolver->cacheGrammars();
769                        }
770
771                        if (getPSVIHandler())
772                        {
773                                fModel = fGrammarResolver->getXSModel();
774                        }
775                        return grammar;
776                }
777        }
778
779        return 0;
780}
781
782
783
784// ---------------------------------------------------------------------------
785//  IGXMLScanner: Private parsing methods
786// ---------------------------------------------------------------------------
787
788// check if we should skip or lax the validation of the element
789// if skip - no validation
790// if lax - validate only if the element if found
791bool IGXMLScanner::laxElementValidation(const QName* element, const ContentLeafNameTypeVector* cv,
792                                                                                const XMLContentModel* const cm,
793                                                                                const XMLSize_t parentElemDepth)
794{
795        bool skipThisOne = false;
796        bool laxThisOne = false;
797        unsigned int elementURI = element->getURI();
798        unsigned int currState = fElemState[parentElemDepth];
799        unsigned int currLoop = fElemLoopState[parentElemDepth];
800
801        if (currState == XMLContentModel::gInvalidTrans)
802        {
803                return laxThisOne;
804        }
805
806        SubstitutionGroupComparator comparator(fGrammarResolver, fUriResolver);
807
808        if (cv)
809        {
810                XMLSize_t i = 0;
811                XMLSize_t leafCount = cv->getLeafCount();
812                unsigned int nextState = 0;
813
814                for (; i < leafCount; i++)
815                {
816                        QName* fElemMap = cv->getLeafNameAt(i);
817                        unsigned int uri = fElemMap->getURI();
818                        ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i);
819
820                        if (type == ContentSpecNode::Leaf)
821                        {
822                                if (((uri == elementURI)
823                                          && XMLString::equals(fElemMap->getLocalPart(), element->getLocalPart()))
824                                        || comparator.isEquivalentTo(element, fElemMap))
825                                {
826
827                                        nextState = cm->getNextState(currState, i);
828                                        if (nextState != XMLContentModel::gInvalidTrans)
829                                                break;
830                                }
831                        }
832                        else if ((type & 0x0f) == ContentSpecNode::Any)
833                        {
834                                nextState = cm->getNextState(currState, i);
835                                if (nextState != XMLContentModel::gInvalidTrans)
836                                        break;
837                        }
838                        else if ((type & 0x0f) == ContentSpecNode::Any_Other)
839                        {
840                                if (uri != elementURI && elementURI != XMLNamespaceResolver::fEmptyUriId)
841                                {
842                                        nextState = cm->getNextState(currState, i);
843                                        if (nextState != XMLContentModel::gInvalidTrans)
844                                                break;
845                                }
846                        }
847                        else if ((type & 0x0f) == ContentSpecNode::Any_NS)
848                        {
849                                if (uri == elementURI)
850                                {
851                                        nextState = cm->getNextState(currState, i);
852                                        if (nextState != XMLContentModel::gInvalidTrans)
853                                                break;
854                                }
855                        }
856                } // for
857
858                if (i == leafCount) // no match
859                {
860                        fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans;
861                        fElemLoopState[parentElemDepth] = 0;
862                        return laxThisOne;
863                }
864
865                unsigned int nextLoop = 0;
866                if (!cm->handleRepetitions(element, currState, currLoop, nextState, nextLoop, i, &comparator))
867                {
868                        fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans;
869                        fElemLoopState[parentElemDepth] = 0;
870                        return laxThisOne;
871                }
872
873                ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i);
874                if ((type & 0x0f) == ContentSpecNode::Any ||
875                        (type & 0x0f) == ContentSpecNode::Any_Other ||
876                        (type & 0x0f) == ContentSpecNode::Any_NS)
877                {
878                        if (type == ContentSpecNode::Any_Skip ||
879                                type == ContentSpecNode::Any_NS_Skip ||
880                                type == ContentSpecNode::Any_Other_Skip)
881                        {
882                                skipThisOne = true;
883                        }
884                        else if (type == ContentSpecNode::Any_Lax ||
885                                         type == ContentSpecNode::Any_NS_Lax ||
886                                         type == ContentSpecNode::Any_Other_Lax)
887                        {
888                                laxThisOne = true;
889                        }
890                }
891                fElemState[parentElemDepth] = nextState;
892                fElemLoopState[parentElemDepth] = nextLoop;
893        } // if
894
895        fValidate &= !skipThisOne;
896
897        return laxThisOne;
898}
899
900// check if there is an AnyAttribute, and if so, see if we should lax or skip
901// if skip - no validation
902// if lax - validate only if the attribute if found
903bool IGXMLScanner::anyAttributeValidation(SchemaAttDef* attWildCard, unsigned int uriId, bool & skipThisOne, bool & laxThisOne)
904{
905        XMLAttDef::AttTypes wildCardType = attWildCard->getType();
906        bool anyEncountered = false;
907        skipThisOne = false;
908        laxThisOne = false;
909        if (wildCardType == XMLAttDef::Any_Any)
910        {
911                anyEncountered = true;
912        }
913        else if (wildCardType == XMLAttDef::Any_Other)
914        {
915                anyEncountered = (attWildCard->getAttName()->getURI() != uriId) && (uriId != XMLNamespaceResolver::fEmptyUriId);
916        }
917        else if (wildCardType == XMLAttDef::Any_List)
918        {
919                ValueVectorOf<unsigned int>* nameURIList = attWildCard->getNamespaceList();
920                if (nameURIList)
921                {
922                        for (XMLSize_t i=0; i < nameURIList->size(); i++)
923                        {
924                                if (nameURIList->elementAt(i) == uriId)
925                                {
926                                        anyEncountered = true;
927                                        break;
928                                }
929                        }
930                }
931        }
932
933        if (anyEncountered)
934        {
935                XMLAttDef::DefAttTypes   defType   = attWildCard->getDefaultType();
936                if (defType == XMLAttDef::ProcessContents_Skip)
937                {
938                        // attribute should just be bypassed,
939                        skipThisOne = true;
940                }
941                else if (defType == XMLAttDef::ProcessContents_Lax)
942                {
943                        laxThisOne = true;
944                }
945        }
946
947        return anyEncountered;
948}
949
950IGXMLScanner::EntityExpRes
951IGXMLScanner::scanEntityRef( const   bool   /* inAttVal */
952                                                        ,       XMLCh&  firstCh
953                                                        ,       XMLCh&  secondCh
954                                                        ,       bool&   escaped)
955{
956        // Assume no escape
957        secondCh = 0;
958        escaped = false;
959
960        // We have to insure that its all in one entity
961        const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum();
962
963        //  If the next char is a pound, then its a character reference and we
964        //  need to expand it always.
965        if (fReaderMgr.skippedChar(chPound))
966        {
967                //  Its a character reference, so scan it and get back the numeric
968                //  value it represents.
969                if (!scanCharRef(firstCh, secondCh))
970                        return EntityExp_Failed;
971
972                escaped = true;
973
974                if (curReader != fReaderMgr.getCurrentReaderNum())
975                        emitError(XMLErrs::PartialMarkupInEntity);
976
977                return EntityExp_Returned;
978        }
979
980        // Expand it since its a normal entity ref
981        XMLBufBid bbName(&fBufMgr);
982        int  colonPosition;
983        bool validName = fDoNamespaces ? fReaderMgr.getQName(bbName.getBuffer(), &colonPosition) :
984                                                                         fReaderMgr.getName(bbName.getBuffer());
985        if (!validName)
986        {
987                if (bbName.isEmpty())
988                        emitError(XMLErrs::ExpectedEntityRefName);
989                else
990                        emitError(XMLErrs::InvalidEntityRefName, bbName.getRawBuffer());
991                return EntityExp_Failed;
992        }
993
994        //  Next char must be a semi-colon. But if its not, just emit
995        //  an error and try to continue.
996        if (!fReaderMgr.skippedChar(chSemiColon))
997                emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer());
998
999        // Make sure we ended up on the same entity reader as the & char
1000        if (curReader != fReaderMgr.getCurrentReaderNum())
1001                emitError(XMLErrs::PartialMarkupInEntity);
1002
1003        // Look up the name in the general entity pool
1004        XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(bbName.getRawBuffer());
1005
1006        // If it does not exist, then obviously an error
1007        if (!decl)
1008        {
1009                // XML 1.0 Section 4.1
1010                // Well-formedness Constraint for entity not found:
1011                //   In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references,
1012                //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
1013                //      or a parameter entity
1014                //
1015                // Else it's Validity Constraint
1016                if (fStandalone || fHasNoDTD)
1017                        emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer());
1018                else {
1019                        if (fValidate)
1020                                fValidator->emitError(XMLValid::VC_EntityNotFound, bbName.getRawBuffer());
1021                }
1022
1023                return EntityExp_Failed;
1024        }
1025
1026        // XML 1.0 Section 4.1
1027        //  If we are a standalone document, then it has to have been declared
1028        //  in the internal subset.
1029        if (fStandalone && !decl->getDeclaredInIntSubset())
1030                emitError(XMLErrs::IllegalRefInStandalone, bbName.getRawBuffer());
1031
1032        if (decl->isExternal())
1033        {
1034                // If its unparsed, then its not valid here
1035                if (decl->isUnparsed())
1036                {
1037                        emitError(XMLErrs::NoUnparsedEntityRefs, bbName.getRawBuffer());
1038                        return EntityExp_Failed;
1039                }
1040
1041//              // If we are in an attribute value, then not valid but keep going
1042//              if (inAttVal)
1043//                      emitError(XMLErrs::NoExtRefsInAttValue);
1044
1045                // And now create a reader to read this entity
1046                InputSource* srcUsed;
1047                XMLReader* reader = fReaderMgr.createReader
1048                (
1049                        decl->getBaseURI()
1050                        , decl->getSystemId()
1051                        , decl->getPublicId()
1052                        , false
1053                        , XMLReader::RefFrom_NonLiteral
1054                        , XMLReader::Type_General
1055                        , XMLReader::Source_External
1056                        , srcUsed
1057                        , fCalculateSrcOfs
1058                        , fLowWaterMark
1059                        , fDisableDefaultEntityResolution
1060                );
1061
1062                // Put a janitor on the source so it gets cleaned up on exit
1063                Janitor<InputSource> janSrc(srcUsed);
1064
1065                //  If the creation failed, and its not because the source was empty,
1066                //  then emit an error and return.
1067                if (!reader)
1068                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed ? srcUsed->getSystemId() : decl->getSystemId(), fMemoryManager);
1069
1070                //  Push the reader. If its a recursive expansion, then emit an error
1071                //  and return an failure.
1072                if (!fReaderMgr.pushReader(reader, decl))
1073                {
1074                        emitError(XMLErrs::RecursiveEntity, decl->getName());
1075                        return EntityExp_Failed;
1076                }
1077
1078                // here's where we need to check if there's a SecurityManager,
1079                // how many entity references we've had
1080                if (fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit)
1081                {
1082                        XMLCh expLimStr[32];
1083                        XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
1084                        emitError
1085                        (
1086                                XMLErrs::EntityExpansionLimitExceeded
1087                                , expLimStr
1088                        );
1089                        // there seems nothing  better to be done than to reset the entity expansion counter
1090                        fEntityExpansionCount = 0;
1091                }
1092
1093                // If it starts with the XML string, then parse a text decl
1094                if (checkXMLDecl(true))
1095                        scanXMLDecl(Decl_Text);
1096        }
1097        else
1098        {
1099                //  If its one of the special char references, then we can return
1100                //  it as a character, and its considered escaped.
1101                if (decl->getIsSpecialChar())
1102                {
1103                        firstCh = decl->getValue()[0];
1104                        escaped = true;
1105                        return EntityExp_Returned;
1106                }
1107
1108                //  Create a reader over a memory stream over the entity value
1109                //  We force it to assume UTF-16 by passing in an encoding
1110                //  string. This way it won't both trying to predecode the
1111                //  first line, looking for an XML/TextDecl.
1112                XMLReader* valueReader = fReaderMgr.createIntEntReader
1113                (
1114                        decl->getName()
1115                        , XMLReader::RefFrom_NonLiteral
1116                        , XMLReader::Type_General
1117                        , decl->getValue()
1118                        , decl->getValueLen()
1119                        , false
1120                );
1121
1122                //  Try to push the entity reader onto the reader manager stack,
1123                //  where it will become the subsequent input. If it fails, that
1124                //  means the entity is recursive, so issue an error. The reader
1125                //  will have just been discarded, but we just keep going.
1126                if (!fReaderMgr.pushReader(valueReader, decl))
1127                {
1128                        emitError(XMLErrs::RecursiveEntity, decl->getName());
1129                }
1130
1131                // here's where we need to check if there's a SecurityManager,
1132                // how many entity references we've had
1133                if (fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit)
1134                {
1135                        XMLCh expLimStr[32];
1136                        XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
1137                        emitError
1138                        (
1139                                XMLErrs::EntityExpansionLimitExceeded
1140                                , expLimStr
1141                        );
1142                }
1143
1144                // If it starts with the XML string, then it's an error
1145                if (checkXMLDecl(true))
1146                {
1147                        emitError(XMLErrs::TextDeclNotLegalHere);
1148                        fReaderMgr.skipPastChar(chCloseAngle);
1149                }
1150        }
1151        return EntityExp_Pushed;
1152}
1153
1154// ----------------------------------------------------------------------------------------------------
1155// DEPRECATED FUNCTIONS KEPT FOR DLL COMPATIBILITY
1156// ----------------------------------------------------------------------------------------------------
1157
1158void IGXMLScanner::updateNSMap( const QName* const, const XMLCh* const )
1159{
1160        DEPRECATED_FEATURE_IN_ICXML;
1161}
1162
1163void IGXMLScanner::updateNSMap( const XMLCh* const, const XMLCh* const, const int)
1164{
1165        DEPRECATED_FEATURE_IN_ICXML;
1166}
1167
1168void IGXMLScanner::processSchemaLocation(XMLCh* const )
1169{
1170        DEPRECATED_FEATURE_IN_ICXML;
1171}
1172
1173void IGXMLScanner::scanCDSection()
1174{
1175        DEPRECATED_FEATURE_IN_ICXML;
1176}
1177
1178void IGXMLScanner::sendCharData(XMLBuffer& toSend)
1179{
1180        DEPRECATED_FEATURE_IN_ICXML;
1181}
1182
1183void IGXMLScanner::scanCharData(XMLBuffer& toUse)
1184{
1185        DEPRECATED_FEATURE_IN_ICXML;
1186}
1187
1188bool IGXMLScanner::basicAttrValueScan(const XMLCh* const , XMLBuffer& )
1189{
1190        DEPRECATED_FEATURE_IN_ICXML;
1191}
1192
1193XMLSize_t IGXMLScanner::rawAttrScan(const  XMLCh* const, RefVectorOf<KVStringPair>&, bool& )
1194{
1195        DEPRECATED_FEATURE_IN_ICXML;
1196}
1197
1198bool IGXMLScanner::scanAttValue( const XMLAttDef* const
1199                                                           , const XMLCh* const
1200                                                           ,       XMLBuffer& )
1201{
1202        DEPRECATED_FEATURE_IN_ICXML;
1203}
1204
1205XMLSize_t IGXMLScanner::buildAttList( const RefVectorOf<KVStringPair>&, const XMLSize_t, XMLElementDecl*, RefVectorOf<XMLAttr>& )
1206{
1207        DEPRECATED_FEATURE_IN_ICXML;
1208}
1209
1210void IGXMLScanner::updateNSMap(const   XMLCh* const, const XMLCh* const)
1211{
1212        DEPRECATED_FEATURE_IN_ICXML;
1213}
1214
1215bool IGXMLScanner::normalizeAttValue
1216(
1217        const   XMLAttDef* const
1218        , const XMLCh* const
1219        , const XMLCh* const
1220        ,       XMLBuffer&
1221)
1222{
1223        DEPRECATED_FEATURE_IN_ICXML;
1224}
1225
1226bool IGXMLScanner::normalizeAttRawValue
1227(
1228        const   XMLCh* const
1229        , const XMLCh* const
1230        ,       XMLBuffer&
1231)
1232{
1233        DEPRECATED_FEATURE_IN_ICXML;
1234}
1235
1236void IGXMLScanner::resizeRawAttrColonList()
1237{
1238        DEPRECATED_FEATURE_IN_ICXML;
1239}
1240
1241void IGXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t)
1242{
1243        DEPRECATED_FEATURE_IN_ICXML;
1244}
1245
1246void IGXMLScanner::parseSchemaLocation(const XMLCh* const, bool)
1247{
1248        DEPRECATED_FEATURE_IN_ICXML;
1249}
1250
1251void IGXMLScanner::scanEndTag(bool &)
1252{
1253        DEPRECATED_FEATURE_IN_ICXML;
1254}
1255
1256bool IGXMLScanner::scanStartTag(bool&)
1257{
1258        DEPRECATED_FEATURE_IN_ICXML;
1259}
1260
1261bool IGXMLScanner::scanStartTagNS(bool&)
1262{
1263        DEPRECATED_FEATURE_IN_ICXML;
1264}
1265
1266bool IGXMLScanner::scanContent()
1267{
1268        DEPRECATED_FEATURE_IN_ICXML;
1269}
1270
1271//bool IGXMLScanner::laxElementValidation(QName*, ContentLeafNameTypeVector*, const XMLContentModel* const, const XMLSize_t)
1272//{
1273//      DEPRECATED_FEATURE_IN_ICXML;
1274//}
1275
1276XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.