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: SchemaValidator.cpp 806488 2009-08-21 10:36:58Z amassari $
20 */
21
22 // ---------------------------------------------------------------------------
23 // Includes
24 // ---------------------------------------------------------------------------
25 #include <xercesc/util/Janitor.hpp>
26 #include <xercesc/framework/XMLDocumentHandler.hpp>
27 #include <xercesc/framework/XMLSchemaDescription.hpp>
28 #include <xercesc/framework/psvi/XSAnnotation.hpp>
29 #include <xercesc/internal/XMLReader.hpp>
30 #include <xercesc/internal/XMLScanner.hpp>
31 #include <xercesc/internal/ElemStack.hpp>
32 #include <xercesc/validators/datatype/DatatypeValidatorFactory.hpp>
33 #include <xercesc/validators/datatype/ListDatatypeValidator.hpp>
34 #include <xercesc/validators/datatype/UnionDatatypeValidator.hpp>
35 #include <xercesc/validators/datatype/ENTITYDatatypeValidator.hpp>
36 #include <xercesc/validators/datatype/IDDatatypeValidator.hpp>
37 #include <xercesc/validators/datatype/IDREFDatatypeValidator.hpp>
38 #include <xercesc/validators/schema/SchemaSymbols.hpp>
39 #include <xercesc/validators/schema/SchemaValidator.hpp>
40 #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
41 #include <xercesc/validators/schema/XercesGroupInfo.hpp>
42 #include <xercesc/validators/schema/XSDLocator.hpp>
43 #include <xercesc/util/OutOfMemoryException.hpp>
44
45 XERCES_CPP_NAMESPACE_BEGIN
46
47 // ---------------------------------------------------------------------------
48 // SchemaValidator: Constructors and Destructor
49 // ---------------------------------------------------------------------------
SchemaValidator(XMLErrorReporter * const errReporter,MemoryManager * const manager)50 SchemaValidator::SchemaValidator( XMLErrorReporter* const errReporter
51 , MemoryManager* const manager) :
52
53 XMLValidator(errReporter)
54 , fMemoryManager(manager)
55 , fSchemaGrammar(0)
56 , fGrammarResolver(0)
57 , fXsiType(0)
58 , fNil(false)
59 , fNilFound(false)
60 , fCurrentDatatypeValidator(0)
61 , fNotationBuf(0)
62 , fDatatypeBuffer(1023, manager)
63 , fTrailing(false)
64 , fSeenNonWhiteSpace(false)
65 , fSeenId(false)
66 , fTypeStack(0)
67 , fMostRecentAttrValidator(0)
68 , fErrorOccurred(false)
69 , fElemIsSpecified(false)
70 {
71 fTypeStack = new (fMemoryManager) ValueStackOf<ComplexTypeInfo*>(8, fMemoryManager);
72 }
73
~SchemaValidator()74 SchemaValidator::~SchemaValidator()
75 {
76 delete fXsiType;
77 delete fTypeStack;
78
79 if (fNotationBuf)
80 delete fNotationBuf;
81 }
82
83 // ---------------------------------------------------------------------------
84 // SchemaValidator: Implementation of the XMLValidator interface
85 // ---------------------------------------------------------------------------
checkContent(XMLElementDecl * const elemDecl,QName ** const children,XMLSize_t childCount,XMLSize_t * indexFailingChild)86 bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl
87 , QName** const children
88 , XMLSize_t childCount
89 , XMLSize_t* indexFailingChild)
90 {
91 fErrorOccurred = false;
92 fElemIsSpecified = false;
93
94 //
95 // Look up the element id in our element decl pool. This will get us
96 // the element decl in our own way of looking at them.
97 //
98 if (!elemDecl)
99 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_InvalidElemId, fMemoryManager);
100
101 //
102 // Get the content spec type of this element. This will tell us what
103 // to do to validate it.
104 //
105 // the top of the type stack always knows best...
106 ComplexTypeInfo* currType = fTypeStack->pop();
107
108 const SchemaElementDecl::ModelTypes modelType = (currType)
109 ? (SchemaElementDecl::ModelTypes)(currType->getContentType())
110 : ((SchemaElementDecl*)elemDecl)->getModelType();
111
112 if (modelType == SchemaElementDecl::Empty ||
113 modelType == SchemaElementDecl::ElementOnlyEmpty)
114 {
115 //
116 // We can do this one here. It cannot have any children. If it does
117 // we return 0 as the index of the first bad child.
118 //
119 if (childCount) {
120 fErrorOccurred = true;
121 *indexFailingChild=0;
122 return false;
123 }
124 }
125 else if ((modelType == SchemaElementDecl::Mixed_Simple)
126 || (modelType == SchemaElementDecl::Mixed_Complex)
127 || (modelType == SchemaElementDecl::Children))
128 {
129 // if nillable, it's an error to have value
130 // XML Schema REC: Validation Rule: Element Locally Valid (Element)
131 // 3.2.1 The element information item must have no
132 // character or element information item [children].
133 //
134 if (fNil) {
135 if (childCount > 0 || !XMLString::equals(fDatatypeBuffer.getRawBuffer(), XMLUni::fgZeroLenString)) {
136 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
137 fErrorOccurred = true;
138 }
139 }
140 else {
141 // Get the element's content model or fault it in
142 XMLContentModel* elemCM = (currType)
143 ? currType->getContentModel()
144 : ((SchemaElementDecl*)elemDecl)->getContentModel();
145
146 // Ask it to validate and return its return
147 unsigned int emptyNS = getScanner()->getEmptyNamespaceId();
148 bool result = elemCM->validateContent(children, childCount, emptyNS, indexFailingChild, getScanner()->getMemoryManager());
149 if (!result) {
150 result = elemCM->validateContentSpecial(children
151 , childCount
152 , emptyNS
153 , fGrammarResolver
154 , fGrammarResolver->getStringPool()
155 , indexFailingChild
156 , getScanner()->getMemoryManager());
157 }
158
159 if(!result) {
160 fErrorOccurred = true;
161 }
162
163 return result;
164 }
165 }
166 else if (modelType == SchemaElementDecl::Simple || modelType == SchemaElementDecl::Any)
167 {
168 // Normally for SchemaElementDecl::Any, We pass no judgement on it and anything goes
169 // but if there is a fXsiTypeValidator, we need to use it for validation
170 if (modelType == SchemaElementDecl::Simple && childCount > 0) {
171 emitError(XMLValid::SimpleTypeHasChild, elemDecl->getFullName());
172 fErrorOccurred = true;
173 }
174 else
175 {
176 XMLCh* value = fDatatypeBuffer.getRawBuffer();
177 XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue();
178
179 if (fNil)
180 {
181 if ((!XMLString::equals(value, XMLUni::fgZeroLenString))
182 || elemDefaultValue)
183 {
184 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
185 fErrorOccurred = true;
186 }
187 }
188 else if (fCurrentDatatypeValidator)
189 {
190 DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType();
191 bool validateCanonical = false;
192 if (eleDefDVType == DatatypeValidator::NOTATION)
193 {
194 // if notation, need to bind URI to notation first
195 if (!fNotationBuf)
196 fNotationBuf = new (fMemoryManager) XMLBuffer(1023, fMemoryManager);
197
198 // Make sure that this value maps to one of the
199 // notation values in the enumList parameter. We don't have to
200 // look it up in the notation pool (if a notation) because we
201 // will look up the enumerated values themselves. If they are in
202 // the notation pool (after the Grammar is parsed), then obviously
203 // this value will be legal since it matches one of them.
204 int colonPos = -1;
205 unsigned int uriId = getScanner()->resolveQName(value, *fNotationBuf, ElemStack::Mode_Element, colonPos);
206
207 const XMLCh* uriText = getScanner()->getURIText(uriId);
208 if (uriText && *uriText) {
209 fNotationBuf->set(uriText);
210 fNotationBuf->append(chColon);
211 fNotationBuf->append(&value[colonPos + 1]);
212 value = fNotationBuf->getRawBuffer();
213 }
214 }
215
216 if (elemDefaultValue)
217 {
218 if (XMLString::equals(value, XMLUni::fgZeroLenString))
219 {
220 fElemIsSpecified = true;
221 // if this element didn't specified any value
222 // use default value
223 if (getScanner()->getDocHandler())
224 getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
225
226 // Normally for default value, it has been validated already during TraverseSchema
227 // But if there was a xsi:type and this validator is fXsiTypeValidator,
228 // need to validate again
229 // we determine this if the current content dataype validator
230 // is neither the one in the element nor the one in the current
231 // complex type (if any)
232 if ((fCurrentDatatypeValidator != ((SchemaElementDecl*)elemDecl)->getDatatypeValidator())
233 && (!fTypeStack->peek() || (fCurrentDatatypeValidator != fTypeStack->peek()->getDatatypeValidator()))) {
234 value = elemDefaultValue;
235 validateCanonical = true;
236 }
237 else
238 value = 0;
239 }
240 else
241 {
242 // this element has specified some value
243 // if the flag is FIXED, then this value must be same as default value
244 if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_FIXED) != 0)
245 {
246 if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 )
247 {
248 emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName());
249 fErrorOccurred = true;
250 }
251 }
252 }
253 }
254
255 if ((!fErrorOccurred) && value)
256 {
257 try {
258 fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager);
259 if (validateCanonical) {
260 XMLCh* canonical = (XMLCh*) fCurrentDatatypeValidator->getCanonicalRepresentation(value, fMemoryManager);
261 ArrayJanitor<XMLCh> tempCanonical(canonical, fMemoryManager);
262 fCurrentDatatypeValidator->validate(canonical, getScanner()->getValidationContext(), fMemoryManager);
263 }
264 }
265 catch (XMLException& idve)
266 {
267 emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
268 fErrorOccurred = true;
269 }
270 catch(const OutOfMemoryException&) {
271 throw;
272 }
273 catch (...)
274 {
275 emitError(XMLValid::GenericError);
276 throw;
277 }
278 }
279 }
280 else if (modelType == SchemaElementDecl::Simple)
281 {
282 emitError(XMLValid::NoDatatypeValidatorForSimpleType, elemDecl->getFullName());
283 fErrorOccurred = true;
284 }
285 // modelType is any
286 else if (elemDefaultValue)
287 {
288 if (XMLString::equals(value, XMLUni::fgZeroLenString))
289 {
290 fElemIsSpecified = true;
291 // if this element didn't specified any value
292 // use default value
293 if (getScanner()->getDocHandler()) {
294 getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
295 }
296 }
297 }
298 }
299 }
300 else
301 {
302 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, fMemoryManager);
303 }
304
305 // must rely on scanner to clear fDatatypeBuffer
306 // since it may need to query its contents after this method completes
307 fNil = false;
308 fNilFound = false;
309 fTrailing=false;
310 fSeenNonWhiteSpace = false;
311 fCurrentDatatypeValidator = 0;
312
313 // Went ok, so return success
314 return true;
315 }
316
faultInAttr(XMLAttr & toFill,const XMLAttDef & attDef) const317 void SchemaValidator::faultInAttr (XMLAttr& toFill, const XMLAttDef& attDef) const
318 {
319 //
320 // At this level, we cannot set the URI id. So we just set it to zero
321 // and leave it at that. The scanner, who called us, will look at the
322 // prefix we stored (if any), resolve it, and store the URL id if any.
323 //
324 SchemaAttDef* schemaAttDef = (SchemaAttDef*) &attDef;
325 QName* attName = schemaAttDef->getAttName();
326
327 toFill.set
328 (
329 attName->getURI()
330 , attName->getLocalPart()
331 , attName->getPrefix()
332 , schemaAttDef->getValue()
333 , schemaAttDef->getType()
334 );
335 }
336
reset()337 void SchemaValidator::reset()
338 {
339 fTrailing = false;
340 fSeenNonWhiteSpace = false;
341 fSeenId = false;
342 fTypeStack->removeAllElements();
343 delete fXsiType;
344 fXsiType = 0;
345 fCurrentDatatypeValidator = 0;
346 fNil = false;
347 fNilFound = false;
348 fDatatypeBuffer.reset();
349 fErrorOccurred = false;
350 }
351
requiresNamespaces() const352 bool SchemaValidator::requiresNamespaces() const
353 {
354 return true;
355 }
356
validateAttrValue(const XMLAttDef * attDef,const XMLCh * const attrValue,bool preValidation,const XMLElementDecl * elemDecl)357 void SchemaValidator::validateAttrValue (const XMLAttDef* attDef
358 , const XMLCh* const attrValue
359 , bool preValidation
360 , const XMLElementDecl* elemDecl)
361 {
362 fErrorOccurred = false;
363
364 //turn on IdRefList checking
365 getScanner()->getValidationContext()->toCheckIdRefList(true);
366
367 //
368 // Get quick refs to lot of the stuff in the passed objects in
369 // order to simplify the code below, which will reference them very
370 // often.
371 //
372 XMLAttDef::AttTypes type = attDef->getType();
373 const XMLAttDef::DefAttTypes defType = attDef->getDefaultType();
374
375 //
376 // If the default type is fixed, then make sure the passed value maps
377 // to the fixed value.
378 //
379 // If during preContentValidation, the value we are validating is the fixed value itself
380 // so no need to compare.
381 // Only need to do this for regular attribute value validation
382 //
383 if ((defType == XMLAttDef::Fixed || defType == XMLAttDef::Required_And_Fixed) && !preValidation)
384 {
385 const XMLCh* const valueText = attDef->getValue();
386 if (!XMLString::equals(attrValue, valueText)) {
387 emitError(XMLValid::NotSameAsFixedValue, attDef->getFullName(), attrValue, valueText);
388 fErrorOccurred = true;
389 }
390 }
391
392 // An empty string cannot be valid for non_CDATA any of the other types
393 if (!attrValue[0] && type != XMLAttDef::Simple)
394 {
395 emitError(XMLValid::InvalidEmptyAttValue, attDef->getFullName());
396 // accords with original DOMTypeInfo implementation, but this does not feel right.
397 fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
398 fErrorOccurred = true;
399 return;
400 }
401
402 DatatypeValidator* attDefDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();
403 if (!attDefDV) {
404 emitError(XMLValid::NoDatatypeValidatorForAttribute, attDef->getFullName());
405 fErrorOccurred = true;
406 }
407 else {
408 DatatypeValidator::ValidatorType attDefDVType = attDefDV->getType();
409 ValidationContext *context = getScanner()->getValidationContext();
410 try {
411
412 // first, if notation, need to bind URI to notation first
413 if (attDefDVType == DatatypeValidator::NOTATION)
414 {
415 //
416 // Make sure that this value maps to one of the
417 // notation values in the enumList parameter. We don't have to
418 // look it up in the notation pool (if a notation) because we
419 // will look up the enumerated values themselves. If they are in
420 // the notation pool (after the Grammar is parsed), then obviously
421 // this value will be legal since it matches one of them.
422 //
423 XMLBuffer notationBuf(1023, fMemoryManager);
424 int colonPos = -1;
425 unsigned int uriId = getScanner()->resolveQName(attrValue, notationBuf, ElemStack::Mode_Element, colonPos);
426 const XMLCh* uriText = getScanner()->getURIText(uriId);
427 if (uriText && *uriText) {
428 notationBuf.set(uriText);
429 notationBuf.append(chColon);
430 notationBuf.append(&attrValue[colonPos + 1]);
431 }
432 else {
433 notationBuf.set(attrValue);
434 }
435
436 attDefDV->validate(notationBuf.getRawBuffer()
437 , context
438 , fMemoryManager);
439 }
440 else {
441 attDefDV->validate(attrValue
442 , context
443 , fMemoryManager);
444 }
445
446 }
447 catch (XMLException& idve) {
448 fErrorOccurred = true;
449 emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
450 }
451 catch(const OutOfMemoryException&)
452 {
453 throw;
454 }
455 catch (...) {
456 emitError(XMLValid::GenericError);
457 fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
458 fErrorOccurred = true;
459 throw;
460 }
461 fMostRecentAttrValidator = attDefDV;
462 // now we can look for ID's, entities, ...
463
464 // set up the entitydeclpool in ENTITYDatatypeValidator
465 // and the idreflist in ID/IDREFDatatypeValidator
466
467 // indicate if this attribute is of type ID
468 bool thisIsAnId = false;
469
470 if (attDefDVType == DatatypeValidator::List) {
471 DatatypeValidator* itemDTV = ((ListDatatypeValidator*)attDefDV)->getItemTypeDTV();
472 DatatypeValidator::ValidatorType itemDTVType = itemDTV->getType();
473 if (itemDTVType == DatatypeValidator::ID) {
474 thisIsAnId = true;
475 }
476 else if (itemDTVType == DatatypeValidator::IDREF) {
477 // if in prevalidatoin, do not add attDef to IDREFList
478 if (preValidation)
479 //todo: when to setIdRefList back to non-null
480 getScanner()->getValidationContext()->toCheckIdRefList(false);
481 }
482 }
483 else if (attDefDVType == DatatypeValidator::Union) {
484 DatatypeValidator *memberDTV = context->getValidatingMemberType();
485 // actual type for DOMTypeInfo is memberDTV
486 fMostRecentAttrValidator = memberDTV;
487 // no member datatype validator if there was an error
488 if(memberDTV)
489 {
490 DatatypeValidator::ValidatorType memberDTVType = memberDTV->getType();
491 if (memberDTVType == DatatypeValidator::ID) {
492 thisIsAnId = true;
493 }
494 else if (memberDTVType == DatatypeValidator::IDREF) {
495 // if in prevalidatoin, do not add attDef to IDREFList
496 if (preValidation)
497 getScanner()->getValidationContext()->toCheckIdRefList(false);
498 }
499 }
500 }
501 else if (attDefDVType == DatatypeValidator::ID) {
502 thisIsAnId = true;
503 }
504 else if (attDefDVType == DatatypeValidator::IDREF) {
505 // if in prevalidation, do not add attDef to IDREFList
506 if (preValidation)
507 getScanner()->getValidationContext()->toCheckIdRefList(false);
508 }
509 if (thisIsAnId) {
510 if (fSeenId) {
511 emitError
512 (
513 XMLValid::MultipleIdAttrs
514 , elemDecl->getFullName()
515 );
516 fErrorOccurred = true;
517 }
518 else
519 fSeenId = true;
520 }
521
522 }
523
524 if(fErrorOccurred) {
525 fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
526 }
527 fTrailing = false;
528 fSeenNonWhiteSpace = false;
529 }
530
validateElement(const XMLElementDecl * elemDef)531 void SchemaValidator::validateElement(const XMLElementDecl* elemDef)
532 {
533 ComplexTypeInfo* elemTypeInfo = ((SchemaElementDecl*)elemDef)->getComplexTypeInfo();
534 fTypeStack->push(elemTypeInfo);
535 fCurrentDatatypeValidator = (elemTypeInfo)
536 ? elemTypeInfo->getDatatypeValidator()
537 : ((SchemaElementDecl*)elemDef)->getDatatypeValidator();
538
539 fErrorOccurred = false;
540
541 if (fXsiType) {
542 // handle "xsi:type" right here
543 DatatypeValidator *xsiTypeDV = 0;
544 unsigned int uri = fXsiType->getURI();
545 const XMLCh* localPart = fXsiType->getLocalPart();
546
547 if (uri != XMLElementDecl::fgInvalidElemId &&
548 uri != XMLElementDecl::fgPCDataElemId &&
549 uri != XMLContentModel::gEpsilonFakeId &&
550 uri != XMLContentModel::gEOCFakeId) {
551
552 // retrieve Grammar for the uri
553 const XMLCh* uriStr = getScanner()->getURIText(uri);
554 SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uriStr);
555 if (!sGrammar) {
556
557 // Check built-in simple types
558 if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
559
560 xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart);
561
562 if (!xsiTypeDV) {
563 emitError(XMLValid::BadXsiType, fXsiType->getRawName());
564 fErrorOccurred = true;
565 }
566 else {
567 if (elemTypeInfo || (fCurrentDatatypeValidator
568 && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV))) {
569 // the type is not derived from ancestor
570 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
571 fErrorOccurred = true;
572 }
573 else if(fCurrentDatatypeValidator != xsiTypeDV)
574 {
575 // the type is derived from ancestor
576 if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) {
577 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
578 fErrorOccurred = true;
579 }
580 if (elemDef->hasAttDefs()) {
581 // if we have an attribute but xsi:type's type is simple, we have a problem...
582 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
583 fErrorOccurred = true;
584 }
585 }
586 fCurrentDatatypeValidator = xsiTypeDV;
587 }
588 }
589 else {
590 // Grammar not found
591 emitError(XMLValid::GrammarNotFound, uriStr);
592 fErrorOccurred = true;
593 }
594 }
595 else if (sGrammar->getGrammarType() != Grammar::SchemaGrammarType) {
596 emitError(XMLValid::GrammarNotFound, uriStr);
597 fErrorOccurred = true;
598 }
599 else {
600 // retrieve complexType registry and DatatypeValidator registry
601 RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar->getComplexTypeRegistry();
602 if (!complexTypeRegistry) {
603 emitError(XMLValid::BadXsiType, fXsiType->getRawName());
604 fErrorOccurred = true;
605 }
606 else {
607
608 // retrieve the typeInfo specified in xsi:type
609 XMLBuffer aBuffer(1023, fMemoryManager);
610 aBuffer.set(uriStr);
611 aBuffer.append(chComma);
612 aBuffer.append(localPart);
613 ComplexTypeInfo* typeInfo = complexTypeRegistry->get(aBuffer.getRawBuffer());
614
615 if (typeInfo) {
616 // typeInfo is found
617 if (typeInfo->getAbstract()) {
618 emitError(XMLValid::NoAbstractInXsiType, aBuffer.getRawBuffer());
619 fErrorOccurred = true;
620 }
621 else
622 {
623 if (elemTypeInfo)
624 {
625 ComplexTypeInfo* tempType = typeInfo;
626 while (tempType) {
627 if (tempType == elemTypeInfo)
628 break;
629 tempType = tempType->getBaseComplexTypeInfo();
630 }
631
632 if (!tempType) {
633 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
634 fErrorOccurred = true;
635 }
636 else if(elemTypeInfo != typeInfo) {
637 // perform the check on the entire inheritance chain
638 ComplexTypeInfo* tempType = typeInfo;
639 while (tempType) {
640 if (tempType == elemTypeInfo)
641 break;
642 int derivationMethod = tempType->getDerivedBy();
643 if ((((SchemaElementDecl*)elemDef)->getBlockSet() & derivationMethod) != 0) {
644 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
645 fErrorOccurred = true;
646 }
647 if ((elemTypeInfo->getBlockSet() & derivationMethod) != 0) {
648 emitError(XMLValid::TypeNoSubforBlock, elemTypeInfo->getTypeName());
649 fErrorOccurred = true;
650 }
651 tempType = tempType->getBaseComplexTypeInfo();
652 }
653 }
654 }
655 else
656 {
657 // if the original type is a simple type, check derivation ok.
658 if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(typeInfo->getDatatypeValidator())) {
659 // the type is not derived from ancestor
660 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
661 fErrorOccurred = true;
662 }
663 }
664
665 if (!fErrorOccurred)
666 {
667 fTypeStack->pop();
668 fTypeStack->push(typeInfo);
669 fCurrentDatatypeValidator = typeInfo->getDatatypeValidator();
670 }
671 }
672 }
673 else
674 {
675 // typeInfo not found
676 xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart);
677
678 if (!xsiTypeDV) {
679 emitError(XMLValid::BadXsiType, fXsiType->getRawName());
680 fErrorOccurred = true;
681 }
682 else {
683 if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV)) {
684 // the type is not derived from ancestor
685 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
686 fErrorOccurred = true;
687 }
688 else if(fCurrentDatatypeValidator != xsiTypeDV)
689 {
690 DatatypeValidator::ValidatorType derivedType=xsiTypeDV->getType();
691 if((derivedType == DatatypeValidator::List || derivedType == DatatypeValidator::Union) && fCurrentDatatypeValidator==0)
692 {
693 // the substitution is always allowed if the type is list or union and the base type was xs:anySimpleType
694 }
695 else
696 {
697 // the type is derived from ancestor
698 if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) {
699 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
700 fErrorOccurred = true;
701 }
702 if (elemDef->hasAttDefs()) {
703 // if we have an attribute but xsi:type's type is simple, we have a problem...
704 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
705 fErrorOccurred = true;
706 }
707 }
708 }
709
710 fCurrentDatatypeValidator = xsiTypeDV;
711 }
712 }
713 }
714 }
715 }
716
717 delete fXsiType;
718 fXsiType = 0;
719 }
720 else {
721 //
722 // xsi:type was not specified...
723 // If the corresponding type is abstract, detect an error
724 //
725 if (elemTypeInfo && elemTypeInfo->getAbstract()) {
726 emitError(XMLValid::NoUseAbstractType, elemDef->getFullName());
727 fErrorOccurred = true;
728 }
729 }
730
731 //
732 // Check whether this element is abstract. If so, an error
733 //
734 int miscFlags = ((SchemaElementDecl*)elemDef)->getMiscFlags();
735 if ((miscFlags & SchemaSymbols::XSD_ABSTRACT) != 0) {
736 emitError(XMLValid::NoDirectUseAbstractElement, elemDef->getFullName());
737 fErrorOccurred = true;
738 }
739
740 //
741 // Check whether this element allows Nillable
742 //
743 if (fNilFound && (miscFlags & SchemaSymbols::XSD_NILLABLE) == 0 ) {
744 fNil = false;
745 fNilFound = false;
746 emitError(XMLValid::NillNotAllowed, elemDef->getFullName());
747 fErrorOccurred = true;
748 }
749
750 fDatatypeBuffer.reset();
751 fTrailing = false;
752 fSeenNonWhiteSpace = false;
753 fSeenId = false;
754 }
755
preContentValidation(bool,bool validateDefAttr)756 void SchemaValidator::preContentValidation(bool,
757 bool validateDefAttr)
758 {
759 // Lets go through all the grammar in the GrammarResolver
760 // and validate those that has not been validated yet
761 //
762 // Lets enumerate all of the elements in the element decl pool
763 // and put out an error for any that did not get declared.
764 // We also check all of the attributes as well.
765 //
766 // And enumerate all the complextype info in the grammar
767 // and do Unique Particle Attribution Checking
768
769 RefHashTableOfEnumerator<Grammar> grammarEnum = fGrammarResolver->getGrammarEnumerator();
770 while (grammarEnum.hasMoreElements())
771 {
772 SchemaGrammar& sGrammar = (SchemaGrammar&) grammarEnum.nextElement();
773 if (sGrammar.getGrammarType() != Grammar::SchemaGrammarType || sGrammar.getValidated())
774 continue;
775
776 sGrammar.setValidated(true);
777
778 RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = sGrammar.getElemEnumerator();
779
780 while (elemEnum.hasMoreElements())
781 {
782 SchemaElementDecl& curElem = elemEnum.nextElement();
783
784 // First check if declared or not
785 //
786 // See if this element decl was ever marked as declared. If
787 // not, then put out an error. In some cases its just
788 // a warning, such as being referenced in a content model.
789 //
790 const SchemaElementDecl::CreateReasons reason = curElem.getCreateReason();
791
792 if (reason != XMLElementDecl::Declared)
793 {
794 if (reason == XMLElementDecl::AttList)
795 {
796 getScanner()->emitError
797 (
798 XMLErrs::UndeclaredElemInAttList
799 , curElem.getFullName()
800 );
801 }
802 else if (reason == XMLElementDecl::AsRootElem)
803 {
804 emitError
805 (
806 XMLValid::UndeclaredElemInDocType
807 , curElem.getFullName()
808 );
809 }
810 else if (reason == XMLElementDecl::InContentModel)
811 {
812 getScanner()->emitError
813 (
814 XMLErrs::UndeclaredElemInCM
815 , curElem.getFullName()
816 );
817 }
818 else
819 {
820 }
821 }
822
823 //
824 // Then check all of the attributes of the current element.
825 // We check for:
826 //
827 // 1) Multiple ID attributes
828 // 2) That all of the default values of attributes are
829 // valid for their type.
830 // 3) That for any notation types, that their lists
831 // of possible values refer to declared notations.
832 //
833 if (curElem.hasAttDefs()) {
834 XMLAttDefList& attDefList = curElem.getAttDefList();
835 bool seenId = false;
836
837 for(XMLSize_t i=0; i<attDefList.getAttDefCount(); i++)
838 {
839 const XMLAttDef& curAttDef = attDefList.getAttDef(i);
840
841 if (curAttDef.getType() == XMLAttDef::ID)
842 {
843 if (seenId)
844 {
845 emitError
846 (
847 XMLValid::MultipleIdAttrs
848 , curElem.getFullName()
849 );
850 break;
851 }
852
853 seenId = true;
854 }
855 else if (curAttDef.getType() == XMLAttDef::Notation && curAttDef.getEnumeration())
856 {
857 //
858 // We need to verify that all of its possible values
859 // (in the enum list) refer to valid notations.
860 //
861 XMLCh* list = XMLString::replicate(curAttDef.getEnumeration(), fMemoryManager);
862 ArrayJanitor<XMLCh> janList(list, fMemoryManager);
863
864 //
865 // Search forward for a space or a null. If a null,
866 // we are done. If a space, cap it and look it up.
867 //
868 bool breakFlag = false;
869 XMLCh* listPtr = list;
870 XMLCh* lastPtr = listPtr;
871 while (true)
872 {
873 while (*listPtr && (*listPtr != chSpace))
874 listPtr++;
875
876 //
877 // If at the end, indicate we need to break after
878 // this one. Else, cap it off here.
879 //
880 if (!*listPtr)
881 breakFlag = true;
882 else
883 *listPtr = chNull;
884
885 if (!sGrammar.getNotationDecl(lastPtr))
886 {
887 emitError
888 (
889 XMLValid::UnknownNotRefAttr
890 , curAttDef.getFullName()
891 , lastPtr
892 );
893 }
894
895 // Break out if we hit the end last time
896 if (breakFlag)
897 break;
898
899 // Else move upwards and try again
900 listPtr++;
901 lastPtr = listPtr;
902 }
903 }
904
905 // If it has a default/fixed value, then validate it
906 if (validateDefAttr && curAttDef.getValue())
907 {
908 validateAttrValue
909 (
910 &curAttDef
911 , curAttDef.getValue()
912 , true
913 , &curElem
914 );
915 }
916 }
917 }
918 }
919
920 // For each complex type info, check the Unique Particle Attribution
921 if (getScanner()->getValidationSchemaFullChecking()) {
922 RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar.getComplexTypeRegistry();
923
924 RefHashTableOfEnumerator<ComplexTypeInfo> complexTypeEnum(complexTypeRegistry, false, fMemoryManager);
925 while (complexTypeEnum.hasMoreElements())
926 {
927 ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement();
928 curTypeInfo.checkUniqueParticleAttribution(&sGrammar, fGrammarResolver, fGrammarResolver->getStringPool(), this);
929 checkParticleDerivation(&sGrammar, &curTypeInfo);
930 checkRefElementConsistency(&sGrammar, &curTypeInfo);
931 }
932
933 RefHashTableOf<XercesGroupInfo>* groupInfoRegistry = sGrammar.getGroupInfoRegistry();
934 RefHashTableOfEnumerator<XercesGroupInfo> groupEnum(groupInfoRegistry, false, fMemoryManager);
935
936 while (groupEnum.hasMoreElements()) {
937
938 XercesGroupInfo& curGroup = groupEnum.nextElement();
939 XercesGroupInfo* baseGroup = curGroup.getBaseGroup();
940
941 if (baseGroup) {
942 try {
943 checkParticleDerivationOk(&sGrammar, curGroup.getContentSpec(), curGroup.getScope(),
944 baseGroup->getContentSpec(), baseGroup->getScope());
945 }
946 catch (const XMLException& excep) {
947 fSchemaErrorReporter.emitError(excep, curGroup.getLocator());
948 }
949 }
950
951 if (curGroup.getCheckElementConsistency())
952 checkRefElementConsistency(&sGrammar, 0, &curGroup);
953 }
954 }
955 }
956 }
957
postParseValidation()958 void SchemaValidator::postParseValidation()
959 {
960 //
961 // At this time, there is nothing to do here. The scanner itself handles
962 // ID/IDREF validation, since that is the same no matter what kind of
963 // validator.
964 //
965 }
966
967 // ---------------------------------------------------------------------------
968 // SchemaValidator: Validator method
969 // ---------------------------------------------------------------------------
970 // Do Schema Normalization depends on the WhiteSpace Facet
971 // preserve : No normalization is done
972 // replace : All occurrences of #x9 (tab), #xA (linefeed) and #xD (carriage return)
973 // are replaced with #x20 (space).
974 // collapse : Subsequent to the replacements specified above under replace,
975 // contiguous sequences of #x20s are collapsed to a single #x20,
976 // and initial and/or final #x20s are deleted.
977 //
normalizeWhiteSpace(DatatypeValidator * dV,const XMLCh * const value,XMLBuffer & toFill,bool bStandalone)978 void SchemaValidator::normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill, bool bStandalone /*= false*/)
979 {
980 toFill.reset();
981
982 //empty string
983 if (!*value)
984 return;
985
986 if(bStandalone)
987 fTrailing = fSeenNonWhiteSpace = false;
988
989 short wsFacet = dV->getWSFacet();
990
991 // Loop through the chars of the source value and normalize it
992 // according to the whitespace facet
993 XMLCh nextCh;
994 const XMLCh* srcPtr = value;
995 XMLReader* fCurReader = getReaderMgr()->getCurrentReader();
996
997 if (wsFacet == DatatypeValidator::REPLACE)
998 {
999 while (*srcPtr)
1000 {
1001 nextCh = *srcPtr++;
1002 if (fCurReader->isWhitespace(nextCh))
1003 nextCh = chSpace;
1004 // Add this char to the target buffer
1005 toFill.append(nextCh);
1006 }
1007 }
1008 else // COLLAPSE
1009 {
1010 enum States
1011 {
1012 InWhitespace
1013 , InContent
1014 };
1015
1016 States curState = fTrailing ? InWhitespace : InContent;
1017 while (*srcPtr)
1018 {
1019 nextCh = *srcPtr++;
1020 if (curState == InContent)
1021 {
1022 if (fCurReader->isWhitespace(nextCh))
1023 {
1024 curState = InWhitespace;
1025 continue;
1026 }
1027 fSeenNonWhiteSpace = true;
1028 }
1029 else if (curState == InWhitespace)
1030 {
1031 if (fCurReader->isWhitespace(nextCh))
1032 continue;
1033 if (fSeenNonWhiteSpace)
1034 toFill.append(chSpace);
1035 curState = InContent;
1036 fSeenNonWhiteSpace = true;
1037 }
1038 // Add this char to the target buffer
1039 toFill.append(nextCh);
1040 }
1041
1042 if (fCurReader->isWhitespace(*(srcPtr-1)))
1043 fTrailing = true;
1044 else
1045 fTrailing = false;
1046 }
1047 if(bStandalone)
1048 fTrailing = fSeenNonWhiteSpace = false;
1049 }
1050
1051
1052 // ---------------------------------------------------------------------------
1053 // SchemaValidator: Particle Derivation Checking
1054 // ---------------------------------------------------------------------------
checkRefElementConsistency(SchemaGrammar * const currentGrammar,const ComplexTypeInfo * const curTypeInfo,const XercesGroupInfo * const curGroup)1055 void SchemaValidator::checkRefElementConsistency(SchemaGrammar* const currentGrammar,
1056 const ComplexTypeInfo* const curTypeInfo,
1057 const XercesGroupInfo* const curGroup) {
1058
1059 XMLSize_t elemCount = (curTypeInfo) ? curTypeInfo->elementCount() : curGroup->elementCount();
1060 int elemScope = (curTypeInfo) ? curTypeInfo->getScopeDefined() : curGroup->getScope();
1061 XSDLocator* typeInfoLocator = (curTypeInfo) ? curTypeInfo->getLocator() : curGroup->getLocator();
1062
1063 for (XMLSize_t i=0; i < elemCount; i++) {
1064
1065 const SchemaElementDecl* elemDecl = (curTypeInfo) ? curTypeInfo->elementAt(i) : curGroup->elementAt(i);
1066
1067 if (elemDecl->isGlobalDecl()) {
1068
1069 unsigned int elemURI = elemDecl->getURI();
1070 const XMLCh* elemName = elemDecl->getBaseName();
1071 const SchemaElementDecl* other = (SchemaElementDecl*)
1072 currentGrammar->getElemDecl(elemURI, elemName, 0, elemScope);
1073
1074 if (other
1075 && (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() ||
1076 elemDecl->getDatatypeValidator() != other->getDatatypeValidator())) {
1077 fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration,
1078 XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager);
1079 continue;
1080 }
1081
1082 RefHash2KeysTableOf<ElemVector>* validSubsGroups = currentGrammar->getValidSubstitutionGroups();
1083 ValueVectorOf<SchemaElementDecl*>* subsElements = validSubsGroups->get(elemName, elemURI);
1084
1085 if (subsElements) {
1086
1087 XMLSize_t subsElemSize = subsElements->size();
1088
1089 for (XMLSize_t j=0; j < subsElemSize; j++) {
1090
1091 SchemaElementDecl* subsElem = subsElements->elementAt(j);
1092 const XMLCh* subsElemName = subsElem->getBaseName();
1093 other = (SchemaElementDecl*)
1094 currentGrammar->getElemDecl(subsElem->getURI(), subsElemName, 0, elemScope);
1095
1096 if (other
1097 && (subsElem->getComplexTypeInfo() != other->getComplexTypeInfo()
1098 || subsElem->getDatatypeValidator() != other->getDatatypeValidator())) {
1099 fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration,
1100 XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager);
1101 }
1102 }
1103 }
1104 }
1105 }
1106 }
1107
1108 // ---------------------------------------------------------------------------
1109 // SchemaValidator: Particle Derivation Checking
1110 // ---------------------------------------------------------------------------
checkParticleDerivation(SchemaGrammar * const currentGrammar,const ComplexTypeInfo * const curTypeInfo)1111 void SchemaValidator::checkParticleDerivation(SchemaGrammar* const currentGrammar,
1112 const ComplexTypeInfo* const curTypeInfo) {
1113
1114 ComplexTypeInfo* baseTypeInfo = 0;
1115 ContentSpecNode* curSpecNode = 0;
1116
1117 if (curTypeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION
1118 && ((baseTypeInfo = curTypeInfo->getBaseComplexTypeInfo()) != 0)
1119 && ((curSpecNode = curTypeInfo->getContentSpec()) != 0)) {
1120
1121 try {
1122 checkParticleDerivationOk(currentGrammar, curSpecNode,
1123 curTypeInfo->getScopeDefined(),
1124 baseTypeInfo->getContentSpec(),
1125 baseTypeInfo->getScopeDefined(), baseTypeInfo);
1126 }
1127 catch (const XMLException& excep) {
1128 fSchemaErrorReporter.emitError(excep, curTypeInfo->getLocator());
1129 }
1130 }
1131 }
1132
getNonUnaryGroup(ContentSpecNode * const pNode)1133 ContentSpecNode* SchemaValidator::getNonUnaryGroup(ContentSpecNode* const pNode) {
1134
1135 int pNodeType = (pNode->getType() & 0x0f);
1136 if (pNodeType == ContentSpecNode::Leaf
1137 || pNodeType == ContentSpecNode::Any
1138 || pNodeType == ContentSpecNode::Any_Other
1139 || pNodeType == ContentSpecNode::Any_NS)
1140 return pNode;
1141
1142 if (pNode->getMinOccurs() == 1 && pNode->getMaxOccurs() == 1
1143 && pNode->getFirst() && !pNode->getSecond())
1144 return getNonUnaryGroup(pNode->getFirst());
1145
1146 return pNode;
1147 }
1148
checkParticleDerivationOk(SchemaGrammar * const aGrammar,ContentSpecNode * const curNode,const int derivedScope,ContentSpecNode * const baseNode,const int baseScope,const ComplexTypeInfo * const baseInfo,const bool toCheckOccurence)1149 void SchemaValidator::checkParticleDerivationOk(SchemaGrammar* const aGrammar,
1150 ContentSpecNode* const curNode,
1151 const int derivedScope,
1152 ContentSpecNode* const baseNode,
1153 const int baseScope,
1154 const ComplexTypeInfo* const baseInfo,
1155 const bool toCheckOccurence) {
1156
1157 // Check for pointless occurrences of all, choice, sequence. The result is
1158 // the contentspec which is not pointless. If the result is a non-pointless
1159 // group, Vector is filled in with the children of interest
1160 if (curNode && !baseNode)
1161 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_EmptyBase, fMemoryManager);
1162
1163 if (!curNode)
1164 return;
1165
1166 ContentSpecNode* curSpecNode = getNonUnaryGroup(curNode);
1167 ContentSpecNode* baseSpecNode = getNonUnaryGroup(baseNode);
1168 ValueVectorOf<ContentSpecNode*> curVector(8, fMemoryManager);
1169 ValueVectorOf<ContentSpecNode*> baseVector(8, fMemoryManager);
1170 ContentSpecNode::NodeTypes curNodeType = curSpecNode->getType();
1171 ContentSpecNode::NodeTypes baseNodeType = baseSpecNode->getType();
1172
1173 if ((curNodeType & 0x0f) == ContentSpecNode::Sequence ||
1174 (curNodeType & 0x0f) == ContentSpecNode::Choice ||
1175 curNodeType == ContentSpecNode::All) {
1176 curSpecNode = checkForPointlessOccurrences(curSpecNode, curNodeType, &curVector);
1177 }
1178
1179 if ((baseNodeType & 0x0f) == ContentSpecNode::Sequence ||
1180 (baseNodeType & 0x0f) == ContentSpecNode::Choice ||
1181 baseNodeType == ContentSpecNode::All) {
1182 baseSpecNode = checkForPointlessOccurrences(baseSpecNode, baseNodeType, &baseVector);
1183 }
1184
1185 curNodeType = curSpecNode->getType();
1186 baseNodeType = baseSpecNode->getType();
1187
1188 switch (curNodeType & 0x0f) {
1189 case ContentSpecNode::Leaf:
1190 {
1191 switch (baseNodeType & 0x0f) {
1192 case ContentSpecNode::Leaf:
1193 {
1194 checkNameAndTypeOK(aGrammar, curSpecNode, derivedScope, baseSpecNode, baseScope, baseInfo);
1195 return;
1196 }
1197 case ContentSpecNode::Any:
1198 case ContentSpecNode::Any_Other:
1199 case ContentSpecNode::Any_NS:
1200 {
1201 checkNSCompat(curSpecNode, baseSpecNode, toCheckOccurence);
1202 return;
1203 }
1204 case ContentSpecNode::Choice:
1205 case ContentSpecNode::Sequence:
1206 case ContentSpecNode::All:
1207 {
1208 checkRecurseAsIfGroup(aGrammar, curSpecNode, derivedScope,
1209 baseSpecNode, baseScope, &baseVector, baseInfo);
1210 return;
1211 }
1212 default:
1213 {
1214 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1215 }
1216 }
1217 }
1218 case ContentSpecNode::Any:
1219 case ContentSpecNode::Any_Other:
1220 case ContentSpecNode::Any_NS:
1221 {
1222 switch (baseNodeType & 0x0f) {
1223 case ContentSpecNode::Any:
1224 case ContentSpecNode::Any_Other:
1225 case ContentSpecNode::Any_NS:
1226 {
1227 checkNSSubset(curSpecNode, baseSpecNode);
1228 return;
1229 }
1230 case ContentSpecNode::Choice:
1231 case ContentSpecNode::Sequence:
1232 case ContentSpecNode::All:
1233 case ContentSpecNode::Leaf:
1234 {
1235 if (baseNodeType == ContentSpecNode::Any_NS_Choice) {
1236 if (checkNSSubsetChoiceRoot(curSpecNode, baseSpecNode)) {
1237 return;
1238 }
1239 }
1240
1241 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes1, fMemoryManager);
1242 }
1243 default:
1244 {
1245 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1246 }
1247 }
1248 }
1249 case ContentSpecNode::All:
1250 {
1251 switch (baseNodeType & 0x0f) {
1252 case ContentSpecNode::Any:
1253 case ContentSpecNode::Any_Other:
1254 case ContentSpecNode::Any_NS:
1255 {
1256 checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
1257 return;
1258 }
1259 case ContentSpecNode::All:
1260 {
1261 checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
1262 baseSpecNode, baseScope, &baseVector, baseInfo);
1263 return;
1264 }
1265 case ContentSpecNode::Choice:
1266 case ContentSpecNode::Sequence:
1267 case ContentSpecNode::Leaf:
1268 {
1269 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes2, fMemoryManager);
1270 }
1271 default:
1272 {
1273 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1274 }
1275 }
1276 }
1277 case ContentSpecNode::Choice:
1278 {
1279 switch (baseNodeType & 0x0f) {
1280 case ContentSpecNode::Any:
1281 case ContentSpecNode::Any_Other:
1282 case ContentSpecNode::Any_NS:
1283 {
1284 checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
1285 return;
1286 }
1287 case ContentSpecNode::Choice:
1288 {
1289 checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
1290 baseSpecNode, baseScope, &baseVector, baseInfo, true);
1291 return;
1292 }
1293 case ContentSpecNode::All:
1294 case ContentSpecNode::Sequence:
1295 case ContentSpecNode::Leaf:
1296 {
1297 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes3, fMemoryManager);
1298 }
1299 default:
1300 {
1301 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1302 }
1303 }
1304 }
1305 case ContentSpecNode::Sequence:
1306 {
1307 switch (baseNodeType & 0x0f) {
1308 case ContentSpecNode::Any:
1309 case ContentSpecNode::Any_Other:
1310 case ContentSpecNode::Any_NS:
1311 {
1312 checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
1313 return;
1314 }
1315 case ContentSpecNode::All:
1316 {
1317 checkRecurseUnordered(aGrammar, curSpecNode, &curVector, derivedScope,
1318 baseSpecNode, &baseVector, baseScope, baseInfo);
1319 return;
1320 }
1321 case ContentSpecNode::Sequence:
1322 {
1323 checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
1324 baseSpecNode, baseScope, &baseVector, baseInfo);
1325 return;
1326 }
1327 case ContentSpecNode::Choice:
1328 {
1329 checkMapAndSum(aGrammar, curSpecNode, &curVector, derivedScope,
1330 baseSpecNode, &baseVector, baseScope, baseInfo);
1331 return;
1332 }
1333 case ContentSpecNode::Leaf:
1334 {
1335 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes4, fMemoryManager);
1336 }
1337 default:
1338 {
1339 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1340 }
1341 }
1342 }
1343 }
1344 }
1345
1346 ContentSpecNode*
checkForPointlessOccurrences(ContentSpecNode * const specNode,const ContentSpecNode::NodeTypes nodeType,ValueVectorOf<ContentSpecNode * > * const nodes)1347 SchemaValidator::checkForPointlessOccurrences(ContentSpecNode* const specNode,
1348 const ContentSpecNode::NodeTypes nodeType,
1349 ValueVectorOf<ContentSpecNode*>* const nodes) {
1350
1351 ContentSpecNode* rightNode = specNode->getSecond();
1352 int min = specNode->getMinOccurs();
1353 int max = specNode->getMaxOccurs();
1354
1355 if (!rightNode) {
1356
1357 gatherChildren(nodeType, specNode->getFirst(), nodes);
1358
1359 if (nodes->size() == 1 && min == 1 && max == 1) {
1360 return nodes->elementAt(0);
1361 }
1362
1363 return specNode;
1364 }
1365
1366 gatherChildren(nodeType, specNode->getFirst(), nodes);
1367 gatherChildren(nodeType, rightNode, nodes);
1368
1369 return specNode;
1370 }
1371
gatherChildren(const ContentSpecNode::NodeTypes parentNodeType,ContentSpecNode * const specNode,ValueVectorOf<ContentSpecNode * > * const nodes)1372 void SchemaValidator::gatherChildren(const ContentSpecNode::NodeTypes parentNodeType,
1373 ContentSpecNode* const specNode,
1374 ValueVectorOf<ContentSpecNode*>* const nodes) {
1375
1376 if (!specNode) {
1377 return;
1378 }
1379
1380 int min = specNode->getMinOccurs();
1381 int max = specNode->getMaxOccurs();
1382 ContentSpecNode::NodeTypes nodeType = specNode->getType();
1383 ContentSpecNode* rightNode = specNode->getSecond();
1384
1385 if (nodeType == ContentSpecNode::Leaf ||
1386 (nodeType & 0x0f) == ContentSpecNode::Any ||
1387 (nodeType & 0x0f) == ContentSpecNode::Any_NS ||
1388 (nodeType & 0x0f) == ContentSpecNode::Any_Other) {
1389 nodes->addElement(specNode);
1390 }
1391 else if (min !=1 || max != 1) {
1392 nodes->addElement(specNode);
1393 }
1394 else if (!rightNode) {
1395 gatherChildren(nodeType, specNode->getFirst(), nodes);
1396 }
1397 else if ((parentNodeType & 0x0f) == (nodeType & 0x0f)) {
1398
1399 gatherChildren(nodeType, specNode->getFirst(), nodes);
1400 gatherChildren(nodeType, rightNode, nodes);
1401 }
1402 else {
1403 nodes->addElement(specNode);
1404 }
1405 }
1406
1407 void
checkNSCompat(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode,const bool toCheckOccurence)1408 SchemaValidator::checkNSCompat(const ContentSpecNode* const derivedSpecNode,
1409 const ContentSpecNode* const baseSpecNode,
1410 const bool toCheckOccurence) {
1411
1412 // check Occurrence ranges
1413 if (toCheckOccurence &&
1414 !isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1415 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1416 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE,
1417 derivedSpecNode->getElement()->getLocalPart(), fMemoryManager);
1418 }
1419
1420 // check wildcard subset
1421 if (!wildcardEltAllowsNamespace(baseSpecNode, derivedSpecNode->getElement()->getURI())) {
1422 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NSCompat1,
1423 derivedSpecNode->getElement()->getLocalPart(), fMemoryManager);
1424 }
1425 }
1426
1427 bool
wildcardEltAllowsNamespace(const ContentSpecNode * const baseSpecNode,const unsigned int derivedURI)1428 SchemaValidator::wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode,
1429 const unsigned int derivedURI) {
1430
1431 ContentSpecNode::NodeTypes nodeType = baseSpecNode->getType();
1432
1433 if ((nodeType & 0x0f) == ContentSpecNode::Any) {
1434 return true;
1435 }
1436
1437 unsigned int baseURI = baseSpecNode->getElement()->getURI();
1438
1439 if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) {
1440 if (derivedURI == baseURI) {
1441 return true;
1442 }
1443 }
1444 else { // must be ANY_OTHER
1445 if (derivedURI != baseURI && derivedURI != getScanner()->getEmptyNamespaceId()) {
1446 return true;
1447 }
1448 }
1449
1450 return false;
1451 }
1452
1453 void
checkNameAndTypeOK(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,const int derivedScope,const ContentSpecNode * const baseSpecNode,const int baseScope,const ComplexTypeInfo * const baseInfo)1454 SchemaValidator::checkNameAndTypeOK(SchemaGrammar* const currentGrammar,
1455 const ContentSpecNode* const derivedSpecNode,
1456 const int derivedScope,
1457 const ContentSpecNode* const baseSpecNode,
1458 const int baseScope,
1459 const ComplexTypeInfo* const baseInfo) {
1460
1461 if (derivedSpecNode->getMaxOccurs() == 0)
1462 return;
1463
1464 unsigned int derivedURI = derivedSpecNode->getElement()->getURI();
1465
1466 // case of mixed complex types with attributes only
1467 if (derivedURI == XMLElementDecl::fgPCDataElemId) {
1468 return;
1469 }
1470
1471 SchemaGrammar* dGrammar = currentGrammar;
1472
1473 if (derivedURI != getScanner()->getEmptyNamespaceId())
1474 {
1475 const XMLCh* dURI = fGrammarResolver->getStringPool()->getValueForId(derivedURI);
1476 dGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(dURI);
1477 }
1478
1479 if (!dGrammar) { //something is wrong
1480 return;
1481 }
1482
1483 const XMLCh* derivedName = derivedSpecNode->getElement()->getLocalPart();
1484
1485 SchemaElementDecl* derivedElemDecl = findElement(derivedScope, derivedURI, derivedName, dGrammar);
1486
1487 if (!derivedElemDecl) {
1488 return;
1489 }
1490
1491 const XMLCh* baseName = baseSpecNode->getElement()->getLocalPart();
1492 unsigned int baseURI = baseSpecNode->getElement()->getURI();
1493 bool subsGroup = false;
1494
1495 if (!XMLString::equals(derivedName, baseName) || derivedURI != baseURI) {
1496 // Check if derived is substitutable for base.
1497 //
1498 SchemaElementDecl* e = derivedElemDecl->getSubstitutionGroupElem ();
1499
1500 for (; e != 0; e = e->getSubstitutionGroupElem ()) {
1501 if (XMLString::equals(e->getBaseName (), baseName) && e->getURI () == baseURI) {
1502 break;
1503 }
1504 }
1505
1506 if (e == 0) {
1507 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NameTypeOK1, fMemoryManager);
1508 }
1509
1510 subsGroup = true;
1511 }
1512
1513 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1514 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1515 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE, derivedName, fMemoryManager);
1516 }
1517
1518 // Find the schema grammar for the base element using the base type as
1519 // a reference if it is available (it is unavailable if we are checking
1520 // element group restriction which happens in redefine).
1521 //
1522 SchemaGrammar* bGrammar = dGrammar;
1523
1524 if (baseInfo)
1525 {
1526 const XMLCh* baseTypeURI = baseInfo->getTypeUri ();
1527
1528 if (baseTypeURI != 0 && *baseTypeURI != 0) // Non-empty namespace.
1529 bGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(baseTypeURI);
1530
1531 if (!bGrammar) { //something is wrong
1532 return;
1533 }
1534 }
1535
1536 SchemaElementDecl* baseElemDecl =
1537 findElement(baseScope, baseURI, baseName, bGrammar, baseInfo);
1538
1539 if (!baseElemDecl) {
1540 return;
1541 }
1542
1543 int derivedFlags = derivedElemDecl->getMiscFlags();
1544 int baseFlags = baseElemDecl->getMiscFlags();
1545
1546 if (((baseFlags & SchemaSymbols::XSD_NILLABLE) == 0) &&
1547 ((derivedFlags & SchemaSymbols::XSD_NILLABLE) != 0)) {
1548 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK2, derivedName, fMemoryManager);
1549 }
1550
1551 const XMLCh* derivedDefVal = derivedElemDecl->getDefaultValue();
1552 const XMLCh* baseDefVal = baseElemDecl->getDefaultValue();
1553
1554 if (baseDefVal && (baseFlags & SchemaSymbols::XSD_FIXED) != 0 &&
1555 ((derivedFlags & SchemaSymbols::XSD_FIXED) == 0 ||
1556 !XMLString::equals(derivedDefVal, baseDefVal))) {
1557 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK3, derivedName, fMemoryManager);
1558 }
1559
1560 int derivedBlockSet = derivedElemDecl->getBlockSet();
1561 int baseBlockSet = baseElemDecl->getBlockSet();
1562
1563 if ((derivedBlockSet & baseBlockSet) != baseBlockSet) {
1564 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK4, derivedName, fMemoryManager);
1565 }
1566
1567 // check identity constraints
1568 checkICRestriction(derivedElemDecl, baseElemDecl, derivedName, baseName);
1569
1570 // check that the derived element's type is derived from the base's.
1571 if (!subsGroup)
1572 checkTypesOK(derivedElemDecl, baseElemDecl, derivedName);
1573 }
1574
1575 SchemaElementDecl*
findElement(const int scope,const unsigned int uriIndex,const XMLCh * const name,SchemaGrammar * const grammar,const ComplexTypeInfo * const typeInfo)1576 SchemaValidator::findElement(const int scope, const unsigned int uriIndex,
1577 const XMLCh* const name,
1578 SchemaGrammar* const grammar,
1579 const ComplexTypeInfo* const typeInfo) {
1580
1581 // check for element at given scope first
1582 SchemaElementDecl* elemDecl = (SchemaElementDecl*) grammar->getElemDecl(uriIndex, name, 0, scope);
1583
1584 // if not found, check at global scope
1585 if (!elemDecl) {
1586
1587 elemDecl = (SchemaElementDecl*)
1588 grammar->getElemDecl(uriIndex, name, 0, Grammar::TOP_LEVEL_SCOPE);
1589
1590 // if still not found, and base is specified, look it up there
1591 if (!elemDecl && typeInfo) {
1592
1593 const ComplexTypeInfo* baseInfo = typeInfo;
1594
1595 while (baseInfo) {
1596
1597 elemDecl = (SchemaElementDecl*)
1598 grammar->getElemDecl(uriIndex, name, 0, baseInfo->getScopeDefined());
1599
1600 if (elemDecl) {
1601 break;
1602 }
1603
1604 baseInfo = baseInfo->getBaseComplexTypeInfo();
1605 }
1606 }
1607 }
1608
1609 return elemDecl;
1610 }
1611
1612 void
checkICRestriction(const SchemaElementDecl * const derivedElemDecl,const SchemaElementDecl * const baseElemDecl,const XMLCh * const derivedElemName,const XMLCh * const baseElemName)1613 SchemaValidator::checkICRestriction(const SchemaElementDecl* const derivedElemDecl,
1614 const SchemaElementDecl* const baseElemDecl,
1615 const XMLCh* const derivedElemName,
1616 const XMLCh* const baseElemName) {
1617
1618 // REVIST - need to get more clarification
1619 XMLSize_t derivedICCount = derivedElemDecl->getIdentityConstraintCount();
1620 XMLSize_t baseICCount = baseElemDecl->getIdentityConstraintCount();
1621
1622 if (derivedICCount > baseICCount) {
1623 ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK6, derivedElemName, baseElemName, fMemoryManager);
1624 }
1625
1626 for (XMLSize_t i=0; i < derivedICCount; i++) {
1627
1628 bool found = false;
1629 IdentityConstraint* ic= derivedElemDecl->getIdentityConstraintAt(i);
1630
1631 for (XMLSize_t j=0; j < baseICCount; j++) {
1632 if (*ic == *(baseElemDecl->getIdentityConstraintAt(j))) {
1633
1634 found = true;
1635 break;
1636 }
1637 }
1638
1639 if (!found) {
1640 ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK7, derivedElemName, baseElemName, fMemoryManager);
1641 }
1642 }
1643 }
1644
1645 void
checkTypesOK(const SchemaElementDecl * const derivedElemDecl,const SchemaElementDecl * const baseElemDecl,const XMLCh * const derivedElemName)1646 SchemaValidator::checkTypesOK(const SchemaElementDecl* const derivedElemDecl,
1647 const SchemaElementDecl* const baseElemDecl,
1648 const XMLCh* const derivedElemName) {
1649
1650 SchemaElementDecl::ModelTypes baseType = baseElemDecl->getModelType();
1651
1652 if (baseType == SchemaElementDecl::Any) {
1653 return;
1654 }
1655
1656 ComplexTypeInfo* rInfo = derivedElemDecl->getComplexTypeInfo();
1657 ComplexTypeInfo* bInfo = baseElemDecl->getComplexTypeInfo();
1658
1659 if (derivedElemDecl->getModelType() == SchemaElementDecl::Simple) {
1660
1661 if (baseType != SchemaElementDecl::Simple) {
1662 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
1663 }
1664
1665 if (!rInfo) {
1666
1667 DatatypeValidator* bDV = baseElemDecl->getDatatypeValidator();
1668
1669 if (bInfo || bDV == 0 ||
1670 !bDV->isSubstitutableBy(derivedElemDecl->getDatatypeValidator())) {
1671 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
1672 }
1673
1674 return;
1675 }
1676 }
1677
1678 if (rInfo == bInfo)
1679 return;
1680
1681 for (; rInfo && rInfo != bInfo; rInfo = rInfo->getBaseComplexTypeInfo()) {
1682 if (rInfo->getDerivedBy() != SchemaSymbols::XSD_RESTRICTION) {
1683
1684 rInfo = 0;
1685 break;
1686 }
1687 }
1688
1689 if (!rInfo) {
1690 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
1691 }
1692 }
1693
1694 void
checkRecurseAsIfGroup(SchemaGrammar * const currentGrammar,ContentSpecNode * const derivedSpecNodeIn,const int derivedScope,const ContentSpecNode * const baseSpecNode,const int baseScope,ValueVectorOf<ContentSpecNode * > * const baseNodes,const ComplexTypeInfo * const baseInfo)1695 SchemaValidator::checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar,
1696 ContentSpecNode* const derivedSpecNodeIn,
1697 const int derivedScope,
1698 const ContentSpecNode* const baseSpecNode,
1699 const int baseScope,
1700 ValueVectorOf<ContentSpecNode*>* const baseNodes,
1701 const ComplexTypeInfo* const baseInfo) {
1702
1703 ContentSpecNode::NodeTypes baseType = baseSpecNode->getType();
1704 bool toLax = false;
1705
1706 //Treat the element as if it were in a group of the same variety as base
1707 ContentSpecNode derivedGroupNode(baseType, derivedSpecNodeIn, 0, false, true, fMemoryManager);
1708 const ContentSpecNode* const derivedSpecNode = &derivedGroupNode;
1709
1710 if ((baseSpecNode->getType() & 0x0f) == ContentSpecNode::Choice) {
1711 toLax = true;
1712 }
1713
1714 // Instead of calling this routine, inline it
1715 // checkRecurse(currentGrammar, &derivedGroupNode, derivedScope, &derivedNodes,
1716 // baseSpecNode, baseScope, baseNodes, baseInfo, toLax);
1717
1718 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1719 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1720 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
1721 }
1722
1723 // check for mapping of children
1724 XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
1725 XMLSize_t count2= baseNodes->size();
1726 XMLSize_t current = 0;
1727
1728 {
1729 bool matched = false;
1730
1731 for (XMLSize_t j = current; j < count2; j++) {
1732
1733 ContentSpecNode* baseNode = baseNodes->elementAt(j);
1734 current++;
1735
1736 bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch'
1737 try {
1738
1739 checkParticleDerivationOk(currentGrammar, derivedSpecNodeIn,
1740 derivedScope, baseNode, baseScope, baseInfo);
1741 matched = true;
1742 break;
1743 }
1744 catch(const XMLException&) {
1745 if (!toLax && baseNode->getMinTotalRange()) {
1746 bDoBreak=true;
1747 }
1748 }
1749 if(bDoBreak)
1750 break;
1751 }
1752
1753 // did not find a match
1754 if (!matched) {
1755 codeToThrow = XMLExcepts::PD_Recurse2;
1756 }
1757 }
1758
1759 // Now, see if there are some elements in the base we didn't match up
1760 // in case of Sequence or All
1761 if (!toLax && codeToThrow == XMLExcepts::NoError) {
1762 for (XMLSize_t j = current; j < count2; j++) {
1763 if (baseNodes->elementAt(j)->getMinTotalRange() * baseSpecNode->getMinOccurs()) { //!emptiable
1764 codeToThrow = XMLExcepts::PD_Recurse2;
1765 break;
1766 }
1767 }
1768 }
1769
1770 if (codeToThrow != XMLExcepts::NoError) {
1771 ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
1772 }
1773 }
1774
1775 void
checkRecurse(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,const int derivedScope,ValueVectorOf<ContentSpecNode * > * const derivedNodes,const ContentSpecNode * const baseSpecNode,const int baseScope,ValueVectorOf<ContentSpecNode * > * const baseNodes,const ComplexTypeInfo * const baseInfo,const bool toLax)1776 SchemaValidator::checkRecurse(SchemaGrammar* const currentGrammar,
1777 const ContentSpecNode* const derivedSpecNode,
1778 const int derivedScope,
1779 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
1780 const ContentSpecNode* const baseSpecNode,
1781 const int baseScope,
1782 ValueVectorOf<ContentSpecNode*>* const baseNodes,
1783 const ComplexTypeInfo* const baseInfo,
1784 const bool toLax) {
1785
1786 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1787 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1788 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
1789 }
1790
1791 // check for mapping of children
1792 XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
1793 XMLSize_t count1= derivedNodes->size();
1794 XMLSize_t count2= baseNodes->size();
1795 XMLSize_t current = 0;
1796
1797 for (XMLSize_t i=0; i<count1; i++) {
1798
1799 bool matched = false;
1800
1801 for (XMLSize_t j = current; j < count2; j++) {
1802
1803 ContentSpecNode* baseNode = baseNodes->elementAt(j);
1804 current++;
1805
1806 bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch'
1807 try {
1808
1809 checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i),
1810 derivedScope, baseNode, baseScope, baseInfo);
1811 matched = true;
1812 break;
1813 }
1814 catch(const XMLException&) {
1815 if (!toLax && baseNode->getMinTotalRange()) {
1816 bDoBreak=true;
1817 }
1818 }
1819 if(bDoBreak)
1820 break;
1821 }
1822
1823 // did not find a match
1824 if (!matched) {
1825
1826 codeToThrow = XMLExcepts::PD_Recurse2;
1827 break;
1828 }
1829 }
1830
1831 // Now, see if there are some elements in the base we didn't match up
1832 // in case of Sequence or All
1833 if (!toLax && codeToThrow == XMLExcepts::NoError) {
1834 for (XMLSize_t j = current; j < count2; j++) {
1835 if (baseNodes->elementAt(j)->getMinTotalRange()) { //!emptiable
1836 codeToThrow = XMLExcepts::PD_Recurse2;
1837 break;
1838 }
1839 }
1840 }
1841
1842 if (codeToThrow != XMLExcepts::NoError) {
1843 ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
1844 }
1845 }
1846
checkNSSubset(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode)1847 void SchemaValidator::checkNSSubset(const ContentSpecNode* const derivedSpecNode,
1848 const ContentSpecNode* const baseSpecNode) {
1849
1850 // check Occurrence ranges
1851 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1852 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1853 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset1, fMemoryManager);
1854 }
1855
1856 if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) {
1857 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset2, fMemoryManager);
1858 }
1859 }
1860
checkNSSubsetChoiceRoot(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode)1861 bool SchemaValidator::checkNSSubsetChoiceRoot(const ContentSpecNode* const derivedSpecNode,
1862 const ContentSpecNode* const baseSpecNode) {
1863 bool found = false;
1864
1865 if (baseSpecNode->getType() == ContentSpecNode::Any_NS_Choice) {
1866 const ContentSpecNode* first = baseSpecNode->getFirst();
1867 const ContentSpecNode* second = baseSpecNode->getSecond();
1868
1869 if (first) {
1870 found = checkNSSubsetChoiceRoot(derivedSpecNode, first);
1871 if (found) return true;
1872 }
1873 if (second) {
1874 found = checkNSSubsetChoiceRoot(derivedSpecNode, second);
1875 if (found) return true;
1876 }
1877 }
1878 else { // should be Any_NS
1879 found = checkNSSubsetChoice(derivedSpecNode, baseSpecNode);
1880 }
1881
1882 return found;
1883 }
1884
checkNSSubsetChoice(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode)1885 bool SchemaValidator::checkNSSubsetChoice(const ContentSpecNode* const derivedSpecNode,
1886 const ContentSpecNode* const baseSpecNode) {
1887
1888 // check Occurrence ranges
1889 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1890 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1891 return false;
1892 }
1893
1894 if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) {
1895 return false;
1896 }
1897 return true;
1898 }
1899
1900 bool
isWildCardEltSubset(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode)1901 SchemaValidator::isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode,
1902 const ContentSpecNode* const baseSpecNode) {
1903
1904 ContentSpecNode::NodeTypes baseType = baseSpecNode->getType();
1905
1906 if ((baseType & 0x0f) == ContentSpecNode::Any) {
1907 return true;
1908 }
1909
1910 ContentSpecNode::NodeTypes derivedType = derivedSpecNode->getType();
1911 unsigned int baseURI = baseSpecNode->getElement()->getURI();
1912 unsigned int derivedURI = derivedSpecNode->getElement()->getURI();
1913
1914 // Below we assume that empty string has id 1.
1915 //
1916 if (((derivedType & 0x0f) == ContentSpecNode::Any_Other) &&
1917 ((baseType & 0x0f) == ContentSpecNode::Any_Other) &&
1918 (baseURI == derivedURI || baseURI == 1)) {
1919 return true;
1920 }
1921
1922 if ((derivedType & 0x0f) == ContentSpecNode::Any_NS) {
1923
1924 if (((baseType & 0x0f) == ContentSpecNode::Any_NS) &&
1925 baseURI == derivedURI) {
1926 return true;
1927 }
1928
1929 if (((baseType & 0x0f) == ContentSpecNode::Any_Other) &&
1930 (derivedURI == 1 || baseURI != derivedURI)) {
1931 return true;
1932 }
1933 }
1934
1935 return false;
1936 }
1937
1938 void
checkNSRecurseCheckCardinality(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,ValueVectorOf<ContentSpecNode * > * const derivedNodes,const int derivedScope,ContentSpecNode * const baseSpecNode,const bool toCheckOccurence)1939 SchemaValidator::checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar,
1940 const ContentSpecNode* const derivedSpecNode,
1941 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
1942 const int derivedScope,
1943 ContentSpecNode* const baseSpecNode,
1944 const bool toCheckOccurence) {
1945
1946 // Implement total range check
1947 int derivedMin = derivedSpecNode->getMinTotalRange();
1948 int derivedMax = derivedSpecNode->getMaxTotalRange();
1949
1950 // check Occurrence ranges
1951 if (toCheckOccurence &&
1952 !isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(),
1953 baseSpecNode->getMaxOccurs())) {
1954 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSRecurseCheckCardinality1, fMemoryManager);
1955 }
1956
1957 // Check that each member of the group is a valid restriction of the wildcard
1958 XMLSize_t nodesCount = derivedNodes->size();
1959
1960 for (XMLSize_t i = 0; i < nodesCount; i++) {
1961 checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), derivedScope, baseSpecNode, -1, 0, false);
1962 }
1963 }
1964
1965 void
checkRecurseUnordered(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,ValueVectorOf<ContentSpecNode * > * const derivedNodes,const int derivedScope,ContentSpecNode * const baseSpecNode,ValueVectorOf<ContentSpecNode * > * const baseNodes,const int baseScope,const ComplexTypeInfo * const baseInfo)1966 SchemaValidator::checkRecurseUnordered(SchemaGrammar* const currentGrammar,
1967 const ContentSpecNode* const derivedSpecNode,
1968 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
1969 const int derivedScope,
1970 ContentSpecNode* const baseSpecNode,
1971 ValueVectorOf<ContentSpecNode*>* const baseNodes,
1972 const int baseScope,
1973 const ComplexTypeInfo* const baseInfo) {
1974
1975 // check Occurrence ranges
1976 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1977 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1978 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
1979 }
1980
1981 XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
1982 XMLSize_t derivedCount= derivedNodes->size();
1983 XMLSize_t baseCount = baseNodes->size();
1984 bool* foundIt = (bool*) fMemoryManager->allocate
1985 (
1986 baseCount * sizeof(bool)
1987 );//new bool[baseCount];
1988 ArrayJanitor<bool> janFoundIt(foundIt, fMemoryManager);
1989
1990 for (XMLSize_t k=0; k < baseCount; k++) {
1991 foundIt[k] = false;
1992 }
1993
1994 // check for mapping of children
1995 for (XMLSize_t i = 0; i < derivedCount; i++) {
1996
1997 ContentSpecNode* derivedNode = derivedNodes->elementAt(i);
1998 bool matched = false;
1999
2000 for (XMLSize_t j = 0; j < baseCount; j++) {
2001
2002 try {
2003
2004 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope,
2005 baseNodes->elementAt(j), baseScope, baseInfo);
2006
2007 if (foundIt[j]) {
2008 break;
2009 }
2010
2011 foundIt[j] = true;
2012 matched = true;
2013 break;
2014 }
2015 catch (const XMLException&) {
2016 }
2017 }
2018
2019 // didn't find a match.
2020 if (!matched) {
2021
2022 codeToThrow = XMLExcepts::PD_RecurseUnordered;
2023 break;
2024 }
2025 }
2026
2027 // For all unmapped particles in base, check to see it it's emptiable or not
2028 if (codeToThrow == XMLExcepts::NoError) {
2029 for (XMLSize_t j=0; j < baseCount; j++) {
2030 if (!foundIt[j] && baseNodes->elementAt(j)->getMinTotalRange()) {
2031
2032 codeToThrow = XMLExcepts::PD_RecurseUnordered;
2033 break;
2034 }
2035 }
2036 }
2037
2038 if (codeToThrow != XMLExcepts::NoError) {
2039 ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
2040 }
2041 }
2042
2043 void
checkMapAndSum(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,ValueVectorOf<ContentSpecNode * > * const derivedNodes,const int derivedScope,ContentSpecNode * const baseSpecNode,ValueVectorOf<ContentSpecNode * > * const baseNodes,const int baseScope,const ComplexTypeInfo * const baseInfo)2044 SchemaValidator::checkMapAndSum(SchemaGrammar* const currentGrammar,
2045 const ContentSpecNode* const derivedSpecNode,
2046 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
2047 const int derivedScope,
2048 ContentSpecNode* const baseSpecNode,
2049 ValueVectorOf<ContentSpecNode*>* const baseNodes,
2050 const int baseScope,
2051 const ComplexTypeInfo* const baseInfo) {
2052
2053 // check Occurrence ranges
2054 XMLSize_t derivedCount = derivedNodes->size();
2055 XMLSize_t baseCount = baseNodes->size();
2056 int derivedMin = derivedSpecNode->getMinOccurs() * (unsigned int)derivedCount;
2057 int derivedMax = derivedSpecNode->getMaxOccurs();
2058
2059 if (derivedMax != SchemaSymbols::XSD_UNBOUNDED) {
2060 derivedMax *= (unsigned int)derivedCount;
2061 }
2062
2063 if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(),
2064 baseSpecNode->getMaxOccurs())) {
2065 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
2066 }
2067
2068 // check for mapping of children
2069 for (XMLSize_t i = 0; i < derivedCount; i++) {
2070
2071 ContentSpecNode* derivedNode = derivedNodes->elementAt(i);
2072 bool matched = false;
2073
2074 for (XMLSize_t j = 0; j < baseCount && !matched; j++) {
2075
2076 try {
2077
2078 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope,
2079 baseNodes->elementAt(j), baseScope, baseInfo);
2080 matched = true;
2081 }
2082 catch (const XMLException&) {
2083 }
2084 }
2085
2086 // didn't find a match.
2087 if (!matched) {
2088 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_MapAndSum, fMemoryManager);
2089 }
2090 }
2091
2092 }
2093
2094 XERCES_CPP_NAMESPACE_END
2095