source: icXML/icXML-devel/src/icxercesc/internal/IGXMLScanner.hpp @ 2720

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

Initial check-in of icXML 0.8 source files

File size: 20.2 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.hpp 882548 2009-11-20 13:44:14Z borisk $
20 */
21
22#if !defined(XERCESC_INCLUDE_GUARD_IGXMLSCANNER_HPP)
23#define XERCESC_INCLUDE_GUARD_IGXMLSCANNER_HPP
24
25#include <xercesc/internal/XMLScanner.hpp>
26#include <xercesc/util/KVStringPair.hpp>
27#include <xercesc/util/NameIdPool.hpp>
28#include <xercesc/util/RefHash2KeysTableOf.hpp>
29#include <xercesc/util/RefHash3KeysIdPool.hpp>
30#include <xercesc/util/Hash2KeysSetOf.hpp>
31#include <xercesc/validators/common/Grammar.hpp>
32#include <xercesc/validators/schema/SchemaInfo.hpp>
33#include <xercesc/validators/schema/SchemaElementDecl.hpp>
34
35#include <xercesc/validators/DTD/DTDGrammar.hpp>
36#include <xercesc/validators/DTD/DTDValidator.hpp>
37#include <xercesc/validators/schema/SchemaGrammar.hpp>
38#include <xercesc/validators/schema/SchemaValidator.hpp>
39
40#include <xercesc/framework/psvi/PSVIAttributeList.hpp>
41#include <xercesc/framework/psvi/PSVIElement.hpp>
42
43#include <xercesc/util/XMLStringTokenizer.hpp>
44
45#include <icxmlc/XMLGrammarResolver.hpp>
46
47XERCES_CPP_NAMESPACE_BEGIN
48
49class DTDElementDecl;
50class DTDGrammar;
51class DTDValidator;
52class SchemaValidator;
53class IdentityConstraintHandler;
54class IdentityConstraint;
55class ContentLeafNameTypeVector;
56class SchemaAttDef;
57class XMLContentModel;
58class XSModel;
59class PSVIAttributeList;
60class PSVIElement;
61
62// TODO: remove fValidator from this class; use ONLY fSchemaValidator or fDTDValidator directly
63// depending on fGrammarType
64
65#define SELECT_DTD_VALIDATOR fDTDValidator // (DTDValidator*)fValidator
66
67//  This is an integrated scanner class, which does DTD/XML Schema grammar
68//  processing.
69class XMLPARSER_EXPORT IGXMLScanner : public XMLScanner
70{
71        template<class IGXMLScanner> friend class XMLParserImpl;
72
73public :
74        // -----------------------------------------------------------------------
75        //  Constructors and Destructor
76        // -----------------------------------------------------------------------
77        IGXMLScanner
78        (
79                XMLValidator* const valToAdopt
80                , GrammarResolver* const grammarResolver
81                , MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager
82        );
83        IGXMLScanner
84        (
85                  XMLDocumentHandler* const docHandler
86                , DocTypeHandler* const     docTypeHandler
87                , XMLEntityHandler* const   entityHandler
88                , XMLErrorReporter* const   errReporter
89                , XMLValidator* const       valToAdopt
90                , GrammarResolver* const    grammarResolver
91                , MemoryManager* const      manager = XMLPlatformUtils::fgMemoryManager
92        );
93        virtual ~IGXMLScanner();
94
95        // -----------------------------------------------------------------------
96        //  XMLScanner public virtual methods
97        // -----------------------------------------------------------------------
98        virtual const XMLCh* getName() const;
99        virtual NameIdPool<DTDEntityDecl>* getEntityDeclPool();
100        virtual const NameIdPool<DTDEntityDecl>* getEntityDeclPool() const;
101        virtual void scanDocument
102        (
103                const   InputSource&    src
104        );
105        virtual bool scanNext(XMLPScanToken& toFill);
106        virtual Grammar* loadGrammar
107        (
108                const   InputSource&    src
109                , const short           grammarType
110                , const bool            toCache = false
111        );
112
113        virtual void resetCachedGrammar ();
114        virtual Grammar::GrammarType getCurrentGrammarType() const;
115
116        // -----------------------------------------------------------------------
117        //  XMLScanner parabix virtual methods
118        // -----------------------------------------------------------------------
119        virtual void handleCDATA
120        (
121                const XMLCh       * cdata
122                , const XMLSize_t   cdataLength
123        );
124
125        virtual void handleContent
126        (
127                  const XMLCh     *       content
128                , const XMLSize_t         contentLength
129        );
130
131        virtual XMLElementDecl * handleStartTag
132        (
133                  const XMLSymbol * const               element
134                , const XMLAttributeList &              attributeList
135                , XMLSize_t                                             attributeCount
136                , const bool                                    isRoot
137                , const bool                                    isEmpty
138                , const XMLSize_t                               readerNum
139        );
140
141        virtual void handleEndTag
142        (
143                  XMLElementDecl * const                element
144                , const unsigned int                    uriId
145                , const XMLSize_t                               readerNum
146                , const bool                                    isRoot
147                , XMLElementDecl **                             children
148                , const XMLSize_t                               childCount
149        );
150
151        void setXsiType
152        (
153                const XMLCh *                           value
154                , const XMLSize_t                       length
155        );
156
157        void setXsiNil
158        (
159                const XMLCh *                           value
160                , const XMLSize_t                       length
161        );
162
163        virtual bool expandEntityRef
164        (
165                const XMLCh *           entityRef
166                , const bool            inAttVal
167                , XMLBuffer &           toFill
168        );
169
170        virtual const DTDGrammar * getDTDGrammar() const
171        {
172                return fDTDGrammar;
173        }
174
175
176protected:
177
178        virtual void scanFirst();
179
180private :
181        // -----------------------------------------------------------------------
182        //  Unimplemented constructors and operators
183        // -----------------------------------------------------------------------
184        IGXMLScanner();
185        IGXMLScanner(const IGXMLScanner&);
186        IGXMLScanner& operator=(const IGXMLScanner&);
187
188        // -----------------------------------------------------------------------
189        //  XMLScanner virtual methods
190        // -----------------------------------------------------------------------
191        virtual void scanCDSection();
192        virtual void scanCharData(XMLBuffer& toToUse);
193        virtual EntityExpRes scanEntityRef
194        (
195                const   bool    inAttVal
196                ,       XMLCh&  firstCh
197                ,       XMLCh&  secondCh
198                ,       bool&   escaped
199        );
200        virtual void scanDocTypeDecl();
201        virtual void scanReset(const InputSource& src);
202        virtual void sendCharData(XMLBuffer& toSend);
203        virtual InputSource* resolveSystemId(const XMLCh* const sysId
204                                                                                ,const XMLCh* const pubId);
205
206        inline
207        XMLAttDefList & getAttDefList( bool              isSchemaGrammar
208                                                                 , ComplexTypeInfo*  currType
209                                                                 , XMLElementDecl*   elemDecl );
210
211        // -----------------------------------------------------------------------
212        //  Private helper methods
213        // -----------------------------------------------------------------------
214        void commonInit();
215        void cleanUp();
216
217        inline bool switchGrammar(const unsigned int uriId);
218
219        inline bool switchGrammar(const unsigned int uriId, const XMLCh* const newGrammarNameSpace);
220
221        void updateNSMap
222        (
223                const   XMLCh* const    attrName
224                , const XMLCh* const    attrValue
225                , const int             colonPosition
226        );
227
228        void updateNSMap
229        (
230                const   QName* const   attrName
231                , const XMLCh* const   attrValue
232        );
233
234        void parseSchemaLocation(const XMLCh* const schemaLocationStr, const XMLSize_t schemaLocationStrLen, bool ignoreLoadSchema = false);
235
236        void resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri, bool ignoreLoadSchema = false);
237
238        inline bool switchGrammar(const XMLCh* const newGrammarNameSpace);
239
240        inline bool setCurrentGrammar(Grammar * tempGrammar);
241
242//      /// @@ DEPRECATED @@
243//      bool laxElementValidation(QName* element, ContentLeafNameTypeVector* cv,
244//                                                        const XMLContentModel* const cm,
245//                                                        const XMLSize_t parentElemDepth);
246
247        bool laxElementValidation(const QName* element, const ContentLeafNameTypeVector* cv,
248                                                          const XMLContentModel* const cm,
249                                                          const XMLSize_t parentElemDepth);
250
251        bool anyAttributeValidation(SchemaAttDef* attWildCard,
252                                                                unsigned int uriId,
253                                                                bool& skipThisOne,
254                                                                bool& laxThisOne);
255
256        void resizeElemState();
257
258        IDISA_ALWAYS_INLINE
259        const XMLCh * normalizeByAttDef(SchemaAttDef* attDef, const XMLCh * value, const bool writeValue);
260
261    IDISA_ALWAYS_INLINE
262    void validateAttValue(XMLElementDecl * elemDecl, XMLAttDef * attDef, const XMLCh * value, DatatypeValidator *& validator, PSVIItem::VALIDITY_STATE & attrValid, XMLAttDef::AttTypes & attType);
263
264    IDISA_ALWAYS_INLINE
265    DatatypeValidator * getAnySimpleTypeValidator();
266
267        // -----------------------------------------------------------------------
268        //  Private scanning methods
269        // -----------------------------------------------------------------------
270
271        bool scanContent();
272        void scanEndTag(bool& gotData);
273        bool scanStartTag(bool& gotData);
274        bool scanStartTagNS(bool& gotData);
275
276        // -----------------------------------------------------------------------
277        //  IdentityConstraints Activation methods
278        // -----------------------------------------------------------------------
279        inline bool toCheckIdentityConstraint()  const;
280
281        // -----------------------------------------------------------------------
282        //  Grammar preparsing methods
283        // -----------------------------------------------------------------------
284        Grammar* loadXMLSchemaGrammar(const InputSource& src, const bool toCache = false);
285        Grammar* loadDTDGrammar(const InputSource& src, const bool toCache = false);
286
287        // -----------------------------------------------------------------------
288        //  PSVI handling methods
289        // -----------------------------------------------------------------------
290        void endElementPSVI(SchemaElementDecl* const elemDecl,
291                                                DatatypeValidator* const memberDV);
292        void resetPSVIElemContext();
293
294        // -----------------------------------------------------------------------
295        //  DEPRECATED PRIVATE METHODS; KEPT FOR DLL COMPATIBILITY
296        // -----------------------------------------------------------------------
297        bool basicAttrValueScan
298        (
299                const   XMLCh* const    attrName
300                ,       XMLBuffer&      toFill
301        );
302        XMLSize_t rawAttrScan
303        (
304                const   XMLCh* const                elemName
305                ,       RefVectorOf<KVStringPair>&  toFill
306                ,       bool&                       isEmpty
307        );
308        bool scanAttValue
309        (
310                const   XMLAttDef* const    attDef
311                , const   XMLCh* const      attrName
312                ,       XMLBuffer&          toFill
313        );
314
315        XMLSize_t buildAttList
316        (
317                const   RefVectorOf<KVStringPair>&  providedAttrs
318                , const XMLSize_t                   attCount
319                ,       XMLElementDecl*             elemDecl
320                ,       RefVectorOf<XMLAttr>&       toFill
321        );
322
323        void updateNSMap
324        (
325                const   XMLCh* const    attrName
326                , const XMLCh* const    attrValue
327        );
328
329        bool normalizeAttValue
330        (
331                const   XMLAttDef* const    attDef
332                , const XMLCh* const       name
333                , const XMLCh* const        value
334                ,       XMLBuffer&          toFill
335        );
336
337        bool normalizeAttRawValue
338        (
339                const   XMLCh* const        attrName
340                , const XMLCh* const        value
341                ,       XMLBuffer&          toFill
342        );
343
344        void parseSchemaLocation(const XMLCh* const schemaLocationStr, bool ignoreLoadSchema = false);
345
346        void processSchemaLocation(XMLCh* const schemaLoc);
347
348        void resizeRawAttrColonList();
349
350        void scanRawAttrListforNameSpaces(XMLSize_t attCount);
351
352        // -----------------------------------------------------------------------
353        //  Data members
354        //
355        //  fRawAttrList
356        //      During the initial scan of the attributes we can only do a raw
357        //      scan for key/value pairs. So this vector is used to store them
358        //      until they can be processed (and put into fAttrList.)
359        //
360        //  fDTDValidator
361        //      The DTD validator instance.
362        //
363        //  fSchemaValidator
364        //      The Schema validator instance.
365        //
366        //  fSeeXsi
367        //      This flag indicates a schema has been seen.
368        //
369        //  fElemState
370        //  fElemLoopState
371        //  fElemStateSize
372        //      Stores an element next state from DFA content model - used for
373        //      wildcard validation
374        //
375        // fDTDElemNonDeclPool
376        //      registry of "faulted-in" DTD element decls
377        // fSchemaElemNonDeclPool
378        //      registry for elements without decls in the grammar
379        // fElemCount
380        //      count of the number of start tags seen so far (starts at 1).
381        //      Used for duplicate attribute detection/processing of required/defaulted attributes
382        // fPSVIAttrList
383        //      PSVI attribute list implementation that needs to be
384        //      filled when a PSVIHandler is registered
385        // fSchemaInfoList
386        //      Transient schema info list that is passed to TraverseSchema instances.
387        // fCachedSchemaInfoList
388        //      Cached Schema info list that is passed to TraverseSchema instances.
389        //
390        // -----------------------------------------------------------------------
391
392        Grammar::GrammarType                    fGrammarType;
393        unsigned int                            fElemStateSize;
394        unsigned int*                           fElemState;
395        unsigned int*                           fElemLoopState;
396        XMLBuffer                               fContent;
397        XMLBuffer                               fWSNormalizeBuf;
398        DTDValidator*                           fDTDValidator;
399        SchemaValidator*                        fSchemaValidator;
400        DTDGrammar*                             fDTDGrammar;
401        IdentityConstraintHandler*              fICHandler;
402        NameIdPool<DTDElementDecl>*             fDTDElemNonDeclPool;
403        RefHash3KeysIdPool<SchemaElementDecl>*  fSchemaElemNonDeclPool;
404        PSVIAttributeList *                     fPSVIAttrList;
405        XSModel*                                fModel;
406        PSVIElement*                            fPSVIElement;
407        ValueStackOf<bool>*                     fErrorStack;
408        PSVIElemContext                         fPSVIElemContext;
409        RefHash2KeysTableOf<SchemaInfo>*        fSchemaInfoList;
410        RefHash2KeysTableOf<SchemaInfo>*        fCachedSchemaInfoList;
411        XMLGrammerResolver                      fGrammarList;
412    DatatypeValidator *                     fAnySimpleTypeValidator;
413        XMLParserImpl<IGXMLScanner>*            fProgressiveParser;
414};
415
416inline const XMLCh* IGXMLScanner::getName() const
417{
418        return XMLUni::fgIGXMLScanner;
419}
420
421inline bool IGXMLScanner::toCheckIdentityConstraint()  const
422{
423        return fValidate && fIdentityConstraintChecking && fICHandler;
424}
425
426inline Grammar::GrammarType IGXMLScanner::getCurrentGrammarType() const
427{
428        return fGrammarType;
429}
430
431DatatypeValidator * IGXMLScanner::getAnySimpleTypeValidator()
432{
433    if (unlikely(fAnySimpleTypeValidator == 0))
434    {
435        fAnySimpleTypeValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
436        assert (fAnySimpleTypeValidator != 0);
437    }
438    return fAnySimpleTypeValidator;
439}
440
441// ---------------------------------------------------------------------------
442//  IGXMLScanner: Private helper methods
443// ---------------------------------------------------------------------------
444
445XMLAttDefList &
446IGXMLScanner::getAttDefList( bool              isSchemaGrammar
447                                                   , ComplexTypeInfo*  currType
448                                                   , XMLElementDecl*   elemDecl)
449{
450        if (isSchemaGrammar && currType)
451                return currType->getAttDefList();
452        else
453                return elemDecl->getAttDefList();
454}
455
456bool IGXMLScanner::switchGrammar(const unsigned int uriId)
457{
458        Grammar * grammar = fGrammarList.getGrammar(uriId);
459        if (unlikely(grammar == NULL))
460        {
461                const XMLCh * const grammarNameSpace = (*fUriResolver)[uriId];
462                grammar = fGrammarResolver->getGrammar(grammarNameSpace);
463                if (!grammar && !fSkipDTDValidation)
464                {
465                        // This is a case where namespaces is on with a DTD grammar.
466                        grammar = fDTDGrammar;
467                }
468                fGrammarList.setGrammar(uriId, grammar);
469        }
470        DEBUG_GRAMMAR_MESSAGE("switchGrammar(" << uriId << ")=" << grammar);
471        return setCurrentGrammar(grammar);
472}
473
474bool IGXMLScanner::switchGrammar(const unsigned int uriId, const XMLCh* const newGrammarNameSpace)
475{
476        Grammar * grammar = fGrammarList.getGrammar(uriId);
477        if (unlikely(grammar == NULL))
478        {
479                grammar = fGrammarResolver->getGrammar(newGrammarNameSpace);
480                if (!grammar && !fSkipDTDValidation)
481                {
482                        // This is a case where namespaces is on with a DTD grammar.
483                        grammar = fDTDGrammar;
484                }
485                fGrammarList.setGrammar(uriId, grammar);
486        }
487        DEBUG_GRAMMAR_MESSAGE("switchGrammar(" << uriId << ',' << newGrammarNameSpace << ")=" << grammar)
488        return setCurrentGrammar(grammar);
489}
490
491bool IGXMLScanner::switchGrammar(const XMLCh* const newGrammarNameSpace)
492{
493        const bool switched = switchGrammar(fUriResolver->resolveUriId(newGrammarNameSpace), newGrammarNameSpace);
494        DEBUG_GRAMMAR_MESSAGE("switchGrammar(" << newGrammarNameSpace << ")=" << switched);
495        return switched;
496}
497
498bool IGXMLScanner::setCurrentGrammar(Grammar * grammar)
499{
500        if (unlikely(grammar == 0))
501        {
502                return false;
503        }
504        else if (grammar != fGrammar)
505        {
506                Grammar::GrammarType grammarType = grammar->getGrammarType();
507
508                DEBUG_GRAMMAR_MESSAGE("grammarType=" << grammarType)
509
510                if (grammarType == Grammar::SchemaGrammarType)
511                {
512                        fValidator = fSchemaValidator;
513
514                        if (unlikely(!fValidator->handlesSchema()))
515                        {
516                                if (fValidatorFromUser)
517                                {
518                                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
519                                }
520                        }
521                }
522                else if (grammarType == Grammar::DTDGrammarType)
523                {
524                        if (fSkipDTDValidation)
525                        {
526                                return false;
527                        }
528
529                        fValidator = fDTDValidator;
530
531                        if (unlikely(!fValidator->handlesDTD()))
532                        {
533                                if (fValidatorFromUser)
534                                {
535                                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoDTDValidator, fMemoryManager);
536                                }
537                        }
538                }
539
540                fGrammarType = grammarType;
541                fGrammar = grammar;
542                fValidator->setGrammar(grammar);
543        }
544        return true;
545}
546
547void
548IGXMLScanner::validateAttValue
549(
550    XMLElementDecl * elemDecl
551    , XMLAttDef * attDef
552    , const XMLCh * value
553    , DatatypeValidator *& validator
554    , PSVIItem::VALIDITY_STATE & attrValid
555    , XMLAttDef::AttTypes & attType
556)
557{
558    if (fValidate)
559    {
560        if (fGrammarType == Grammar::SchemaGrammarType)
561        {
562            SchemaAttDef * schemaAttDef = reinterpret_cast<SchemaAttDef*>(attDef);
563
564            //  Normalize the raw value since we have the attribute type. We
565            //  don't care about the return status here. If it failed, an error
566            //  will be issued, which is all we care about.
567
568            const XMLCh * xsNormalized = normalizeByAttDef(schemaAttDef, value, fNormalizeData && fValidate);
569
570            fSchemaValidator->validateAttrValue(schemaAttDef, xsNormalized, false, elemDecl);
571
572            validator = fSchemaValidator->getMostRecentAttrValidator();
573
574            if (unlikely(fSchemaValidator->getErrorOccurred()))
575            {
576                fPSVIElemContext.fErrorOccurred = true;
577                if (getPSVIHandler())
578                {
579                    attrValid = PSVIItem::VALIDITY_INVALID;
580                }
581            }
582
583            attType = schemaAttDef->getType();
584        }
585        else // if (fGrammarType == Grammar::DTDGrammarType)
586        {
587            DTDAttDef * dtdAttDef = reinterpret_cast<DTDAttDef*>(attDef);
588
589            fDTDValidator->validateAttrValue(dtdAttDef, value, false, elemDecl);
590
591            attType = dtdAttDef->getType();
592        }
593    }
594    else
595    {   // no decl; default DOMTypeInfo to anySimpleType
596        validator = getAnySimpleTypeValidator();
597    }   
598}
599
600const XMLCh * IGXMLScanner::normalizeByAttDef(SchemaAttDef* attDef, const XMLCh * value, const bool writeValue)
601{
602        DatatypeValidator* tempDV = attDef->getDatatypeValidator();
603        if (tempDV && tempDV->getWSFacet() != DatatypeValidator::PRESERVE)
604        {
605                // normalize the attribute according to schema whitespace facet
606                fSchemaValidator->normalizeWhiteSpace
607                (
608                        tempDV, value, fWSNormalizeBuf, true
609                );
610                if (writeValue)
611                {
612                        XMLString::copyNString
613                        (
614                                const_cast<XMLCh*>(value), fWSNormalizeBuf.getRawBuffer(), fWSNormalizeBuf.getLen()
615                        );
616                        return value;
617                }
618                return fWSNormalizeBuf.getRawBuffer();
619        }
620        return value;
621}
622
623// ----------------------------------------------------------------------------------------------
624
625inline void IGXMLScanner::setXsiType
626(
627        const XMLCh *                           value
628        , const XMLSize_t                       length
629)
630{
631
632        if (fSchemaValidator)
633        {
634                const int colonPos = XMLStringU::indexOf<chColon>(value, length);
635
636                if (unlikely(colonPos == -1))
637                {
638                        fSchemaValidator->setXsiType
639                        (
640                                XMLUni::fgZeroLenString, value, XMLNamespaceResolver::fEmptyUriId
641                        );
642                }
643                else
644                {
645                        XMLCh * xsiTypeColon = const_cast<XMLCh*>(&value[colonPos]);
646                        *xsiTypeColon = chNull;
647                        fSchemaValidator->setXsiType
648                        (
649                                value, xsiTypeColon + 1, fUriResolver->getUriIdForPrefix(value, getContextId())
650                        );
651                        *xsiTypeColon = chColon;
652                }
653        }
654
655}
656
657inline void IGXMLScanner::setXsiNil
658(
659        const XMLCh *                           value
660        , const XMLSize_t                       length
661)
662{
663
664        if (fSchemaValidator)
665        {
666                if (XMLString::equals(value, SchemaSymbols::fgATTVAL_TRUE))
667                {
668                        fSchemaValidator->setNillable(true);
669                }
670                else if (XMLString::equals(value, SchemaSymbols::fgATTVAL_FALSE))
671                {
672                        fSchemaValidator->setNillable(false);
673                }
674                else
675                {
676                        emitError(XMLErrs::InvalidAttValue, value, value);
677                }
678        }
679}
680
681XERCES_CPP_NAMESPACE_END
682
683#endif
Note: See TracBrowser for help on using the repository browser.