GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: SchemaValidator.cpp 806488 2009-08-21 10:36:58Z amassari $ 00020 */ 00021 00022 // --------------------------------------------------------------------------- 00023 // Includes 00024 // --------------------------------------------------------------------------- 00025 #include <xercesc/util/Janitor.hpp> 00026 #include <xercesc/framework/XMLDocumentHandler.hpp> 00027 #include <xercesc/framework/XMLSchemaDescription.hpp> 00028 #include <xercesc/framework/psvi/XSAnnotation.hpp> 00029 #include <xercesc/internal/XMLReader.hpp> 00030 #include <xercesc/internal/XMLScanner.hpp> 00031 #include <xercesc/internal/ElemStack.hpp> 00032 #include <xercesc/validators/datatype/DatatypeValidatorFactory.hpp> 00033 #include <xercesc/validators/datatype/ListDatatypeValidator.hpp> 00034 #include <xercesc/validators/datatype/UnionDatatypeValidator.hpp> 00035 #include <xercesc/validators/datatype/ENTITYDatatypeValidator.hpp> 00036 #include <xercesc/validators/datatype/IDDatatypeValidator.hpp> 00037 #include <xercesc/validators/datatype/IDREFDatatypeValidator.hpp> 00038 #include <xercesc/validators/schema/SchemaSymbols.hpp> 00039 #include <xercesc/validators/schema/SchemaValidator.hpp> 00040 #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp> 00041 #include <xercesc/validators/schema/XercesGroupInfo.hpp> 00042 #include <xercesc/validators/schema/XSDLocator.hpp> 00043 #include <xercesc/util/OutOfMemoryException.hpp> 00044 00045 XERCES_CPP_NAMESPACE_BEGIN 00046 00047 // --------------------------------------------------------------------------- 00048 // SchemaValidator: Constructors and Destructor 00049 // --------------------------------------------------------------------------- 00050 SchemaValidator::SchemaValidator( XMLErrorReporter* const errReporter 00051 , MemoryManager* const manager) : 00052 00053 XMLValidator(errReporter) 00054 , fMemoryManager(manager) 00055 , fSchemaGrammar(0) 00056 , fGrammarResolver(0) 00057 , fXsiType(0) 00058 , fNil(false) 00059 , fNilFound(false) 00060 , fCurrentDatatypeValidator(0) 00061 , fNotationBuf(0) 00062 , fDatatypeBuffer(1023, manager) 00063 , fTrailing(false) 00064 , fSeenNonWhiteSpace(false) 00065 , fSeenId(false) 00066 , fTypeStack(0) 00067 , fMostRecentAttrValidator(0) 00068 , fErrorOccurred(false) 00069 , fElemIsSpecified(false) 00070 { 00071 fTypeStack = new (fMemoryManager) ValueStackOf<ComplexTypeInfo*>(8, fMemoryManager); 00072 } 00073 00074 SchemaValidator::~SchemaValidator() 00075 { 00076 delete fXsiType; 00077 delete fTypeStack; 00078 00079 if (fNotationBuf) 00080 delete fNotationBuf; 00081 } 00082 00083 // --------------------------------------------------------------------------- 00084 // SchemaValidator: Implementation of the XMLValidator interface 00085 // --------------------------------------------------------------------------- 00086 bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl 00087 , QName** const children 00088 , XMLSize_t childCount 00089 , XMLSize_t* indexFailingChild) 00090 { 00091 fErrorOccurred = false; 00092 fElemIsSpecified = false; 00093 00094 // 00095 // Look up the element id in our element decl pool. This will get us 00096 // the element decl in our own way of looking at them. 00097 // 00098 if (!elemDecl) 00099 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_InvalidElemId, fMemoryManager); 00100 00101 // 00102 // Get the content spec type of this element. This will tell us what 00103 // to do to validate it. 00104 // 00105 // the top of the type stack always knows best... 00106 ComplexTypeInfo* currType = fTypeStack->pop(); 00107 00108 const SchemaElementDecl::ModelTypes modelType = (currType) 00109 ? (SchemaElementDecl::ModelTypes)(currType->getContentType()) 00110 : ((SchemaElementDecl*)elemDecl)->getModelType(); 00111 00112 if (modelType == SchemaElementDecl::Empty || 00113 modelType == SchemaElementDecl::ElementOnlyEmpty) 00114 { 00115 // 00116 // We can do this one here. It cannot have any children. If it does 00117 // we return 0 as the index of the first bad child. 00118 // 00119 if (childCount) { 00120 fErrorOccurred = true; 00121 *indexFailingChild=0; 00122 return false; 00123 } 00124 } 00125 else if ((modelType == SchemaElementDecl::Mixed_Simple) 00126 || (modelType == SchemaElementDecl::Mixed_Complex) 00127 || (modelType == SchemaElementDecl::Children)) 00128 { 00129 // if nillable, it's an error to have value 00130 // XML Schema REC: Validation Rule: Element Locally Valid (Element) 00131 // 3.2.1 The element information item must have no 00132 // character or element information item [children]. 00133 // 00134 if (fNil) { 00135 if (childCount > 0 || !XMLString::equals(fDatatypeBuffer.getRawBuffer(), XMLUni::fgZeroLenString)) { 00136 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName()); 00137 fErrorOccurred = true; 00138 } 00139 } 00140 else { 00141 // Get the element's content model or fault it in 00142 XMLContentModel* elemCM = (currType) 00143 ? currType->getContentModel() 00144 : ((SchemaElementDecl*)elemDecl)->getContentModel(); 00145 00146 // Ask it to validate and return its return 00147 unsigned int emptyNS = getScanner()->getEmptyNamespaceId(); 00148 bool result = elemCM->validateContent(children, childCount, emptyNS, indexFailingChild, getScanner()->getMemoryManager()); 00149 if (!result) { 00150 result = elemCM->validateContentSpecial(children 00151 , childCount 00152 , emptyNS 00153 , fGrammarResolver 00154 , fGrammarResolver->getStringPool() 00155 , indexFailingChild 00156 , getScanner()->getMemoryManager()); 00157 } 00158 00159 if(!result) { 00160 fErrorOccurred = true; 00161 } 00162 00163 return result; 00164 } 00165 } 00166 else if (modelType == SchemaElementDecl::Simple || modelType == SchemaElementDecl::Any) 00167 { 00168 // Normally for SchemaElementDecl::Any, We pass no judgement on it and anything goes 00169 // but if there is a fXsiTypeValidator, we need to use it for validation 00170 if (modelType == SchemaElementDecl::Simple && childCount > 0) { 00171 emitError(XMLValid::SimpleTypeHasChild, elemDecl->getFullName()); 00172 fErrorOccurred = true; 00173 } 00174 else 00175 { 00176 XMLCh* value = fDatatypeBuffer.getRawBuffer(); 00177 XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue(); 00178 00179 if (fNil) 00180 { 00181 if ((!XMLString::equals(value, XMLUni::fgZeroLenString)) 00182 || elemDefaultValue) 00183 { 00184 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName()); 00185 fErrorOccurred = true; 00186 } 00187 } 00188 else if (fCurrentDatatypeValidator) 00189 { 00190 DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType(); 00191 bool validateCanonical = false; 00192 if (eleDefDVType == DatatypeValidator::NOTATION) 00193 { 00194 // if notation, need to bind URI to notation first 00195 if (!fNotationBuf) 00196 fNotationBuf = new (fMemoryManager) XMLBuffer(1023, fMemoryManager); 00197 00198 // Make sure that this value maps to one of the 00199 // notation values in the enumList parameter. We don't have to 00200 // look it up in the notation pool (if a notation) because we 00201 // will look up the enumerated values themselves. If they are in 00202 // the notation pool (after the Grammar is parsed), then obviously 00203 // this value will be legal since it matches one of them. 00204 int colonPos = -1; 00205 unsigned int uriId = getScanner()->resolveQName(value, *fNotationBuf, ElemStack::Mode_Element, colonPos); 00206 00207 const XMLCh* uriText = getScanner()->getURIText(uriId); 00208 if (uriText && *uriText) { 00209 fNotationBuf->set(uriText); 00210 fNotationBuf->append(chColon); 00211 fNotationBuf->append(&value[colonPos + 1]); 00212 value = fNotationBuf->getRawBuffer(); 00213 } 00214 } 00215 00216 if (elemDefaultValue) 00217 { 00218 if (XMLString::equals(value, XMLUni::fgZeroLenString)) 00219 { 00220 fElemIsSpecified = true; 00221 // if this element didn't specified any value 00222 // use default value 00223 if (getScanner()->getDocHandler()) 00224 getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false); 00225 00226 // Normally for default value, it has been validated already during TraverseSchema 00227 // But if there was a xsi:type and this validator is fXsiTypeValidator, 00228 // need to validate again 00229 // we determine this if the current content dataype validator 00230 // is neither the one in the element nor the one in the current 00231 // complex type (if any) 00232 if ((fCurrentDatatypeValidator != ((SchemaElementDecl*)elemDecl)->getDatatypeValidator()) 00233 && (!fTypeStack->peek() || (fCurrentDatatypeValidator != fTypeStack->peek()->getDatatypeValidator()))) { 00234 value = elemDefaultValue; 00235 validateCanonical = true; 00236 } 00237 else 00238 value = 0; 00239 } 00240 else 00241 { 00242 // this element has specified some value 00243 // if the flag is FIXED, then this value must be same as default value 00244 if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_FIXED) != 0) 00245 { 00246 if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 ) 00247 { 00248 emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName()); 00249 fErrorOccurred = true; 00250 } 00251 } 00252 } 00253 } 00254 00255 if ((!fErrorOccurred) && value) 00256 { 00257 try { 00258 fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager); 00259 if (validateCanonical) { 00260 XMLCh* canonical = (XMLCh*) fCurrentDatatypeValidator->getCanonicalRepresentation(value, fMemoryManager); 00261 ArrayJanitor<XMLCh> tempCanonical(canonical, fMemoryManager); 00262 fCurrentDatatypeValidator->validate(canonical, getScanner()->getValidationContext(), fMemoryManager); 00263 } 00264 } 00265 catch (XMLException& idve) 00266 { 00267 emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage()); 00268 fErrorOccurred = true; 00269 } 00270 catch(const OutOfMemoryException&) { 00271 throw; 00272 } 00273 catch (...) 00274 { 00275 emitError(XMLValid::GenericError); 00276 throw; 00277 } 00278 } 00279 } 00280 else if (modelType == SchemaElementDecl::Simple) 00281 { 00282 emitError(XMLValid::NoDatatypeValidatorForSimpleType, elemDecl->getFullName()); 00283 fErrorOccurred = true; 00284 } 00285 // modelType is any 00286 else if (elemDefaultValue) 00287 { 00288 if (XMLString::equals(value, XMLUni::fgZeroLenString)) 00289 { 00290 fElemIsSpecified = true; 00291 // if this element didn't specified any value 00292 // use default value 00293 if (getScanner()->getDocHandler()) { 00294 getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false); 00295 } 00296 } 00297 } 00298 } 00299 } 00300 else 00301 { 00302 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, fMemoryManager); 00303 } 00304 00305 // must rely on scanner to clear fDatatypeBuffer 00306 // since it may need to query its contents after this method completes 00307 fNil = false; 00308 fNilFound = false; 00309 fTrailing=false; 00310 fSeenNonWhiteSpace = false; 00311 fCurrentDatatypeValidator = 0; 00312 00313 // Went ok, so return success 00314 return true; 00315 } 00316 00317 void SchemaValidator::faultInAttr (XMLAttr& toFill, const XMLAttDef& attDef) const 00318 { 00319 // 00320 // At this level, we cannot set the URI id. So we just set it to zero 00321 // and leave it at that. The scanner, who called us, will look at the 00322 // prefix we stored (if any), resolve it, and store the URL id if any. 00323 // 00324 SchemaAttDef* schemaAttDef = (SchemaAttDef*) &attDef; 00325 QName* attName = schemaAttDef->getAttName(); 00326 00327 toFill.set 00328 ( 00329 attName->getURI() 00330 , attName->getLocalPart() 00331 , attName->getPrefix() 00332 , schemaAttDef->getValue() 00333 , schemaAttDef->getType() 00334 ); 00335 } 00336 00337 void SchemaValidator::reset() 00338 { 00339 fTrailing = false; 00340 fSeenNonWhiteSpace = false; 00341 fSeenId = false; 00342 fTypeStack->removeAllElements(); 00343 delete fXsiType; 00344 fXsiType = 0; 00345 fCurrentDatatypeValidator = 0; 00346 fNil = false; 00347 fNilFound = false; 00348 fDatatypeBuffer.reset(); 00349 fErrorOccurred = false; 00350 } 00351 00352 bool SchemaValidator::requiresNamespaces() const 00353 { 00354 return true; 00355 } 00356 00357 void SchemaValidator::validateAttrValue (const XMLAttDef* attDef 00358 , const XMLCh* const attrValue 00359 , bool preValidation 00360 , const XMLElementDecl* elemDecl) 00361 { 00362 fErrorOccurred = false; 00363 00364 //turn on IdRefList checking 00365 getScanner()->getValidationContext()->toCheckIdRefList(true); 00366 00367 // 00368 // Get quick refs to lot of the stuff in the passed objects in 00369 // order to simplify the code below, which will reference them very 00370 // often. 00371 // 00372 XMLAttDef::AttTypes type = attDef->getType(); 00373 const XMLAttDef::DefAttTypes defType = attDef->getDefaultType(); 00374 00375 // 00376 // If the default type is fixed, then make sure the passed value maps 00377 // to the fixed value. 00378 // 00379 // If during preContentValidation, the value we are validating is the fixed value itself 00380 // so no need to compare. 00381 // Only need to do this for regular attribute value validation 00382 // 00383 if ((defType == XMLAttDef::Fixed || defType == XMLAttDef::Required_And_Fixed) && !preValidation) 00384 { 00385 const XMLCh* const valueText = attDef->getValue(); 00386 if (!XMLString::equals(attrValue, valueText)) { 00387 emitError(XMLValid::NotSameAsFixedValue, attDef->getFullName(), attrValue, valueText); 00388 fErrorOccurred = true; 00389 } 00390 } 00391 00392 // An empty string cannot be valid for non_CDATA any of the other types 00393 if (!attrValue[0] && type != XMLAttDef::Simple) 00394 { 00395 emitError(XMLValid::InvalidEmptyAttValue, attDef->getFullName()); 00396 // accords with original DOMTypeInfo implementation, but this does not feel right. 00397 fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); 00398 fErrorOccurred = true; 00399 return; 00400 } 00401 00402 DatatypeValidator* attDefDV = ((SchemaAttDef*) attDef)->getDatatypeValidator(); 00403 if (!attDefDV) { 00404 emitError(XMLValid::NoDatatypeValidatorForAttribute, attDef->getFullName()); 00405 fErrorOccurred = true; 00406 } 00407 else { 00408 DatatypeValidator::ValidatorType attDefDVType = attDefDV->getType(); 00409 ValidationContext *context = getScanner()->getValidationContext(); 00410 try { 00411 00412 // first, if notation, need to bind URI to notation first 00413 if (attDefDVType == DatatypeValidator::NOTATION) 00414 { 00415 // 00416 // Make sure that this value maps to one of the 00417 // notation values in the enumList parameter. We don't have to 00418 // look it up in the notation pool (if a notation) because we 00419 // will look up the enumerated values themselves. If they are in 00420 // the notation pool (after the Grammar is parsed), then obviously 00421 // this value will be legal since it matches one of them. 00422 // 00423 XMLBuffer notationBuf(1023, fMemoryManager); 00424 int colonPos = -1; 00425 unsigned int uriId = getScanner()->resolveQName(attrValue, notationBuf, ElemStack::Mode_Element, colonPos); 00426 const XMLCh* uriText = getScanner()->getURIText(uriId); 00427 if (uriText && *uriText) { 00428 notationBuf.set(uriText); 00429 notationBuf.append(chColon); 00430 notationBuf.append(&attrValue[colonPos + 1]); 00431 } 00432 else { 00433 notationBuf.set(attrValue); 00434 } 00435 00436 attDefDV->validate(notationBuf.getRawBuffer() 00437 , context 00438 , fMemoryManager); 00439 } 00440 else { 00441 attDefDV->validate(attrValue 00442 , context 00443 , fMemoryManager); 00444 } 00445 00446 } 00447 catch (XMLException& idve) { 00448 fErrorOccurred = true; 00449 emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage()); 00450 } 00451 catch(const OutOfMemoryException&) 00452 { 00453 throw; 00454 } 00455 catch (...) { 00456 emitError(XMLValid::GenericError); 00457 fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); 00458 fErrorOccurred = true; 00459 throw; 00460 } 00461 fMostRecentAttrValidator = attDefDV; 00462 // now we can look for ID's, entities, ... 00463 00464 // set up the entitydeclpool in ENTITYDatatypeValidator 00465 // and the idreflist in ID/IDREFDatatypeValidator 00466 00467 // indicate if this attribute is of type ID 00468 bool thisIsAnId = false; 00469 00470 if (attDefDVType == DatatypeValidator::List) { 00471 DatatypeValidator* itemDTV = ((ListDatatypeValidator*)attDefDV)->getItemTypeDTV(); 00472 DatatypeValidator::ValidatorType itemDTVType = itemDTV->getType(); 00473 if (itemDTVType == DatatypeValidator::ID) { 00474 thisIsAnId = true; 00475 } 00476 else if (itemDTVType == DatatypeValidator::IDREF) { 00477 // if in prevalidatoin, do not add attDef to IDREFList 00478 if (preValidation) 00479 //todo: when to setIdRefList back to non-null 00480 getScanner()->getValidationContext()->toCheckIdRefList(false); 00481 } 00482 } 00483 else if (attDefDVType == DatatypeValidator::Union) { 00484 DatatypeValidator *memberDTV = context->getValidatingMemberType(); 00485 // actual type for DOMTypeInfo is memberDTV 00486 fMostRecentAttrValidator = memberDTV; 00487 // no member datatype validator if there was an error 00488 if(memberDTV) 00489 { 00490 DatatypeValidator::ValidatorType memberDTVType = memberDTV->getType(); 00491 if (memberDTVType == DatatypeValidator::ID) { 00492 thisIsAnId = true; 00493 } 00494 else if (memberDTVType == DatatypeValidator::IDREF) { 00495 // if in prevalidatoin, do not add attDef to IDREFList 00496 if (preValidation) 00497 getScanner()->getValidationContext()->toCheckIdRefList(false); 00498 } 00499 } 00500 } 00501 else if (attDefDVType == DatatypeValidator::ID) { 00502 thisIsAnId = true; 00503 } 00504 else if (attDefDVType == DatatypeValidator::IDREF) { 00505 // if in prevalidation, do not add attDef to IDREFList 00506 if (preValidation) 00507 getScanner()->getValidationContext()->toCheckIdRefList(false); 00508 } 00509 if (thisIsAnId) { 00510 if (fSeenId) { 00511 emitError 00512 ( 00513 XMLValid::MultipleIdAttrs 00514 , elemDecl->getFullName() 00515 ); 00516 fErrorOccurred = true; 00517 } 00518 else 00519 fSeenId = true; 00520 } 00521 00522 } 00523 00524 if(fErrorOccurred) { 00525 fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE); 00526 } 00527 fTrailing = false; 00528 fSeenNonWhiteSpace = false; 00529 } 00530 00531 void SchemaValidator::validateElement(const XMLElementDecl* elemDef) 00532 { 00533 ComplexTypeInfo* elemTypeInfo = ((SchemaElementDecl*)elemDef)->getComplexTypeInfo(); 00534 fTypeStack->push(elemTypeInfo); 00535 fCurrentDatatypeValidator = (elemTypeInfo) 00536 ? elemTypeInfo->getDatatypeValidator() 00537 : ((SchemaElementDecl*)elemDef)->getDatatypeValidator(); 00538 00539 fErrorOccurred = false; 00540 00541 if (fXsiType) { 00542 // handle "xsi:type" right here 00543 DatatypeValidator *xsiTypeDV = 0; 00544 unsigned int uri = fXsiType->getURI(); 00545 const XMLCh* localPart = fXsiType->getLocalPart(); 00546 00547 if (uri != XMLElementDecl::fgInvalidElemId && 00548 uri != XMLElementDecl::fgPCDataElemId && 00549 uri != XMLContentModel::gEpsilonFakeId && 00550 uri != XMLContentModel::gEOCFakeId) { 00551 00552 // retrieve Grammar for the uri 00553 const XMLCh* uriStr = getScanner()->getURIText(uri); 00554 SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uriStr); 00555 if (!sGrammar) { 00556 00557 // Check built-in simple types 00558 if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { 00559 00560 xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart); 00561 00562 if (!xsiTypeDV) { 00563 emitError(XMLValid::BadXsiType, fXsiType->getRawName()); 00564 fErrorOccurred = true; 00565 } 00566 else { 00567 if (elemTypeInfo || (fCurrentDatatypeValidator 00568 && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV))) { 00569 // the type is not derived from ancestor 00570 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); 00571 fErrorOccurred = true; 00572 } 00573 else if(fCurrentDatatypeValidator != xsiTypeDV) 00574 { 00575 // the type is derived from ancestor 00576 if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) { 00577 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName()); 00578 fErrorOccurred = true; 00579 } 00580 if (elemDef->hasAttDefs()) { 00581 // if we have an attribute but xsi:type's type is simple, we have a problem... 00582 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); 00583 fErrorOccurred = true; 00584 } 00585 } 00586 fCurrentDatatypeValidator = xsiTypeDV; 00587 } 00588 } 00589 else { 00590 // Grammar not found 00591 emitError(XMLValid::GrammarNotFound, uriStr); 00592 fErrorOccurred = true; 00593 } 00594 } 00595 else if (sGrammar->getGrammarType() != Grammar::SchemaGrammarType) { 00596 emitError(XMLValid::GrammarNotFound, uriStr); 00597 fErrorOccurred = true; 00598 } 00599 else { 00600 // retrieve complexType registry and DatatypeValidator registry 00601 RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar->getComplexTypeRegistry(); 00602 if (!complexTypeRegistry) { 00603 emitError(XMLValid::BadXsiType, fXsiType->getRawName()); 00604 fErrorOccurred = true; 00605 } 00606 else { 00607 00608 // retrieve the typeInfo specified in xsi:type 00609 XMLBuffer aBuffer(1023, fMemoryManager); 00610 aBuffer.set(uriStr); 00611 aBuffer.append(chComma); 00612 aBuffer.append(localPart); 00613 ComplexTypeInfo* typeInfo = complexTypeRegistry->get(aBuffer.getRawBuffer()); 00614 00615 if (typeInfo) { 00616 // typeInfo is found 00617 if (typeInfo->getAbstract()) { 00618 emitError(XMLValid::NoAbstractInXsiType, aBuffer.getRawBuffer()); 00619 fErrorOccurred = true; 00620 } 00621 else 00622 { 00623 if (elemTypeInfo) 00624 { 00625 ComplexTypeInfo* tempType = typeInfo; 00626 while (tempType) { 00627 if (tempType == elemTypeInfo) 00628 break; 00629 tempType = tempType->getBaseComplexTypeInfo(); 00630 } 00631 00632 if (!tempType) { 00633 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); 00634 fErrorOccurred = true; 00635 } 00636 else if(elemTypeInfo != typeInfo) { 00637 // perform the check on the entire inheritance chain 00638 ComplexTypeInfo* tempType = typeInfo; 00639 while (tempType) { 00640 if (tempType == elemTypeInfo) 00641 break; 00642 int derivationMethod = tempType->getDerivedBy(); 00643 if ((((SchemaElementDecl*)elemDef)->getBlockSet() & derivationMethod) != 0) { 00644 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName()); 00645 fErrorOccurred = true; 00646 } 00647 if ((elemTypeInfo->getBlockSet() & derivationMethod) != 0) { 00648 emitError(XMLValid::TypeNoSubforBlock, elemTypeInfo->getTypeName()); 00649 fErrorOccurred = true; 00650 } 00651 tempType = tempType->getBaseComplexTypeInfo(); 00652 } 00653 } 00654 } 00655 else 00656 { 00657 // if the original type is a simple type, check derivation ok. 00658 if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(typeInfo->getDatatypeValidator())) { 00659 // the type is not derived from ancestor 00660 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); 00661 fErrorOccurred = true; 00662 } 00663 } 00664 00665 if (!fErrorOccurred) 00666 { 00667 fTypeStack->pop(); 00668 fTypeStack->push(typeInfo); 00669 fCurrentDatatypeValidator = typeInfo->getDatatypeValidator(); 00670 } 00671 } 00672 } 00673 else 00674 { 00675 // typeInfo not found 00676 xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart); 00677 00678 if (!xsiTypeDV) { 00679 emitError(XMLValid::BadXsiType, fXsiType->getRawName()); 00680 fErrorOccurred = true; 00681 } 00682 else { 00683 if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV)) { 00684 // the type is not derived from ancestor 00685 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); 00686 fErrorOccurred = true; 00687 } 00688 else if(fCurrentDatatypeValidator != xsiTypeDV) 00689 { 00690 DatatypeValidator::ValidatorType derivedType=xsiTypeDV->getType(); 00691 if((derivedType == DatatypeValidator::List || derivedType == DatatypeValidator::Union) && fCurrentDatatypeValidator==0) 00692 { 00693 // the substitution is always allowed if the type is list or union and the base type was xs:anySimpleType 00694 } 00695 else 00696 { 00697 // the type is derived from ancestor 00698 if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) { 00699 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName()); 00700 fErrorOccurred = true; 00701 } 00702 if (elemDef->hasAttDefs()) { 00703 // if we have an attribute but xsi:type's type is simple, we have a problem... 00704 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName()); 00705 fErrorOccurred = true; 00706 } 00707 } 00708 } 00709 00710 fCurrentDatatypeValidator = xsiTypeDV; 00711 } 00712 } 00713 } 00714 } 00715 } 00716 00717 delete fXsiType; 00718 fXsiType = 0; 00719 } 00720 else { 00721 // 00722 // xsi:type was not specified... 00723 // If the corresponding type is abstract, detect an error 00724 // 00725 if (elemTypeInfo && elemTypeInfo->getAbstract()) { 00726 emitError(XMLValid::NoUseAbstractType, elemDef->getFullName()); 00727 fErrorOccurred = true; 00728 } 00729 } 00730 00731 // 00732 // Check whether this element is abstract. If so, an error 00733 // 00734 int miscFlags = ((SchemaElementDecl*)elemDef)->getMiscFlags(); 00735 if ((miscFlags & SchemaSymbols::XSD_ABSTRACT) != 0) { 00736 emitError(XMLValid::NoDirectUseAbstractElement, elemDef->getFullName()); 00737 fErrorOccurred = true; 00738 } 00739 00740 // 00741 // Check whether this element allows Nillable 00742 // 00743 if (fNilFound && (miscFlags & SchemaSymbols::XSD_NILLABLE) == 0 ) { 00744 fNil = false; 00745 fNilFound = false; 00746 emitError(XMLValid::NillNotAllowed, elemDef->getFullName()); 00747 fErrorOccurred = true; 00748 } 00749 00750 fDatatypeBuffer.reset(); 00751 fTrailing = false; 00752 fSeenNonWhiteSpace = false; 00753 fSeenId = false; 00754 } 00755 00756 void SchemaValidator::preContentValidation(bool, 00757 bool validateDefAttr) 00758 { 00759 // Lets go through all the grammar in the GrammarResolver 00760 // and validate those that has not been validated yet 00761 // 00762 // Lets enumerate all of the elements in the element decl pool 00763 // and put out an error for any that did not get declared. 00764 // We also check all of the attributes as well. 00765 // 00766 // And enumerate all the complextype info in the grammar 00767 // and do Unique Particle Attribution Checking 00768 00769 RefHashTableOfEnumerator<Grammar> grammarEnum = fGrammarResolver->getGrammarEnumerator(); 00770 while (grammarEnum.hasMoreElements()) 00771 { 00772 SchemaGrammar& sGrammar = (SchemaGrammar&) grammarEnum.nextElement(); 00773 if (sGrammar.getGrammarType() != Grammar::SchemaGrammarType || sGrammar.getValidated()) 00774 continue; 00775 00776 sGrammar.setValidated(true); 00777 00778 RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = sGrammar.getElemEnumerator(); 00779 00780 while (elemEnum.hasMoreElements()) 00781 { 00782 SchemaElementDecl& curElem = elemEnum.nextElement(); 00783 00784 // First check if declared or not 00785 // 00786 // See if this element decl was ever marked as declared. If 00787 // not, then put out an error. In some cases its just 00788 // a warning, such as being referenced in a content model. 00789 // 00790 const SchemaElementDecl::CreateReasons reason = curElem.getCreateReason(); 00791 00792 if (reason != XMLElementDecl::Declared) 00793 { 00794 if (reason == XMLElementDecl::AttList) 00795 { 00796 getScanner()->emitError 00797 ( 00798 XMLErrs::UndeclaredElemInAttList 00799 , curElem.getFullName() 00800 ); 00801 } 00802 else if (reason == XMLElementDecl::AsRootElem) 00803 { 00804 emitError 00805 ( 00806 XMLValid::UndeclaredElemInDocType 00807 , curElem.getFullName() 00808 ); 00809 } 00810 else if (reason == XMLElementDecl::InContentModel) 00811 { 00812 getScanner()->emitError 00813 ( 00814 XMLErrs::UndeclaredElemInCM 00815 , curElem.getFullName() 00816 ); 00817 } 00818 else 00819 { 00820 } 00821 } 00822 00823 // 00824 // Then check all of the attributes of the current element. 00825 // We check for: 00826 // 00827 // 1) Multiple ID attributes 00828 // 2) That all of the default values of attributes are 00829 // valid for their type. 00830 // 3) That for any notation types, that their lists 00831 // of possible values refer to declared notations. 00832 // 00833 if (curElem.hasAttDefs()) { 00834 XMLAttDefList& attDefList = curElem.getAttDefList(); 00835 bool seenId = false; 00836 00837 for(XMLSize_t i=0; i<attDefList.getAttDefCount(); i++) 00838 { 00839 const XMLAttDef& curAttDef = attDefList.getAttDef(i); 00840 00841 if (curAttDef.getType() == XMLAttDef::ID) 00842 { 00843 if (seenId) 00844 { 00845 emitError 00846 ( 00847 XMLValid::MultipleIdAttrs 00848 , curElem.getFullName() 00849 ); 00850 break; 00851 } 00852 00853 seenId = true; 00854 } 00855 else if (curAttDef.getType() == XMLAttDef::Notation && curAttDef.getEnumeration()) 00856 { 00857 // 00858 // We need to verify that all of its possible values 00859 // (in the enum list) refer to valid notations. 00860 // 00861 XMLCh* list = XMLString::replicate(curAttDef.getEnumeration(), fMemoryManager); 00862 ArrayJanitor<XMLCh> janList(list, fMemoryManager); 00863 00864 // 00865 // Search forward for a space or a null. If a null, 00866 // we are done. If a space, cap it and look it up. 00867 // 00868 bool breakFlag = false; 00869 XMLCh* listPtr = list; 00870 XMLCh* lastPtr = listPtr; 00871 while (true) 00872 { 00873 while (*listPtr && (*listPtr != chSpace)) 00874 listPtr++; 00875 00876 // 00877 // If at the end, indicate we need to break after 00878 // this one. Else, cap it off here. 00879 // 00880 if (!*listPtr) 00881 breakFlag = true; 00882 else 00883 *listPtr = chNull; 00884 00885 if (!sGrammar.getNotationDecl(lastPtr)) 00886 { 00887 emitError 00888 ( 00889 XMLValid::UnknownNotRefAttr 00890 , curAttDef.getFullName() 00891 , lastPtr 00892 ); 00893 } 00894 00895 // Break out if we hit the end last time 00896 if (breakFlag) 00897 break; 00898 00899 // Else move upwards and try again 00900 listPtr++; 00901 lastPtr = listPtr; 00902 } 00903 } 00904 00905 // If it has a default/fixed value, then validate it 00906 if (validateDefAttr && curAttDef.getValue()) 00907 { 00908 validateAttrValue 00909 ( 00910 &curAttDef 00911 , curAttDef.getValue() 00912 , true 00913 , &curElem 00914 ); 00915 } 00916 } 00917 } 00918 } 00919 00920 // For each complex type info, check the Unique Particle Attribution 00921 if (getScanner()->getValidationSchemaFullChecking()) { 00922 RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar.getComplexTypeRegistry(); 00923 00924 RefHashTableOfEnumerator<ComplexTypeInfo> complexTypeEnum(complexTypeRegistry, false, fMemoryManager); 00925 while (complexTypeEnum.hasMoreElements()) 00926 { 00927 ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement(); 00928 curTypeInfo.checkUniqueParticleAttribution(&sGrammar, fGrammarResolver, fGrammarResolver->getStringPool(), this); 00929 checkParticleDerivation(&sGrammar, &curTypeInfo); 00930 checkRefElementConsistency(&sGrammar, &curTypeInfo); 00931 } 00932 00933 RefHashTableOf<XercesGroupInfo>* groupInfoRegistry = sGrammar.getGroupInfoRegistry(); 00934 RefHashTableOfEnumerator<XercesGroupInfo> groupEnum(groupInfoRegistry, false, fMemoryManager); 00935 00936 while (groupEnum.hasMoreElements()) { 00937 00938 XercesGroupInfo& curGroup = groupEnum.nextElement(); 00939 XercesGroupInfo* baseGroup = curGroup.getBaseGroup(); 00940 00941 if (baseGroup) { 00942 try { 00943 checkParticleDerivationOk(&sGrammar, curGroup.getContentSpec(), curGroup.getScope(), 00944 baseGroup->getContentSpec(), baseGroup->getScope()); 00945 } 00946 catch (const XMLException& excep) { 00947 fSchemaErrorReporter.emitError(excep, curGroup.getLocator()); 00948 } 00949 } 00950 00951 if (curGroup.getCheckElementConsistency()) 00952 checkRefElementConsistency(&sGrammar, 0, &curGroup); 00953 } 00954 } 00955 } 00956 } 00957 00958 void SchemaValidator::postParseValidation() 00959 { 00960 // 00961 // At this time, there is nothing to do here. The scanner itself handles 00962 // ID/IDREF validation, since that is the same no matter what kind of 00963 // validator. 00964 // 00965 } 00966 00967 // --------------------------------------------------------------------------- 00968 // SchemaValidator: Validator method 00969 // --------------------------------------------------------------------------- 00970 // Do Schema Normalization depends on the WhiteSpace Facet 00971 // preserve : No normalization is done 00972 // replace : All occurrences of #x9 (tab), #xA (linefeed) and #xD (carriage return) 00973 // are replaced with #x20 (space). 00974 // collapse : Subsequent to the replacements specified above under replace, 00975 // contiguous sequences of #x20s are collapsed to a single #x20, 00976 // and initial and/or final #x20s are deleted. 00977 // 00978 void SchemaValidator::normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill, bool bStandalone /*= false*/) 00979 { 00980 toFill.reset(); 00981 00982 //empty string 00983 if (!*value) 00984 return; 00985 00986 if(bStandalone) 00987 fTrailing = fSeenNonWhiteSpace = false; 00988 00989 short wsFacet = dV->getWSFacet(); 00990 00991 // Loop through the chars of the source value and normalize it 00992 // according to the whitespace facet 00993 XMLCh nextCh; 00994 const XMLCh* srcPtr = value; 00995 XMLReader* fCurReader = getReaderMgr()->getCurrentReader(); 00996 00997 if (wsFacet == DatatypeValidator::REPLACE) 00998 { 00999 while (*srcPtr) 01000 { 01001 nextCh = *srcPtr++; 01002 if (fCurReader->isWhitespace(nextCh)) 01003 nextCh = chSpace; 01004 // Add this char to the target buffer 01005 toFill.append(nextCh); 01006 } 01007 } 01008 else // COLLAPSE 01009 { 01010 enum States 01011 { 01012 InWhitespace 01013 , InContent 01014 }; 01015 01016 States curState = fTrailing ? InWhitespace : InContent; 01017 while (*srcPtr) 01018 { 01019 nextCh = *srcPtr++; 01020 if (curState == InContent) 01021 { 01022 if (fCurReader->isWhitespace(nextCh)) 01023 { 01024 curState = InWhitespace; 01025 continue; 01026 } 01027 fSeenNonWhiteSpace = true; 01028 } 01029 else if (curState == InWhitespace) 01030 { 01031 if (fCurReader->isWhitespace(nextCh)) 01032 continue; 01033 if (fSeenNonWhiteSpace) 01034 toFill.append(chSpace); 01035 curState = InContent; 01036 fSeenNonWhiteSpace = true; 01037 } 01038 // Add this char to the target buffer 01039 toFill.append(nextCh); 01040 } 01041 01042 if (fCurReader->isWhitespace(*(srcPtr-1))) 01043 fTrailing = true; 01044 else 01045 fTrailing = false; 01046 } 01047 if(bStandalone) 01048 fTrailing = fSeenNonWhiteSpace = false; 01049 } 01050 01051 01052 // --------------------------------------------------------------------------- 01053 // SchemaValidator: Particle Derivation Checking 01054 // --------------------------------------------------------------------------- 01055 void SchemaValidator::checkRefElementConsistency(SchemaGrammar* const currentGrammar, 01056 const ComplexTypeInfo* const curTypeInfo, 01057 const XercesGroupInfo* const curGroup) { 01058 01059 XMLSize_t elemCount = (curTypeInfo) ? curTypeInfo->elementCount() : curGroup->elementCount(); 01060 int elemScope = (curTypeInfo) ? curTypeInfo->getScopeDefined() : curGroup->getScope(); 01061 XSDLocator* typeInfoLocator = (curTypeInfo) ? curTypeInfo->getLocator() : curGroup->getLocator(); 01062 01063 for (XMLSize_t i=0; i < elemCount; i++) { 01064 01065 const SchemaElementDecl* elemDecl = (curTypeInfo) ? curTypeInfo->elementAt(i) : curGroup->elementAt(i); 01066 01067 if (elemDecl->isGlobalDecl()) { 01068 01069 unsigned int elemURI = elemDecl->getURI(); 01070 const XMLCh* elemName = elemDecl->getBaseName(); 01071 const SchemaElementDecl* other = (SchemaElementDecl*) 01072 currentGrammar->getElemDecl(elemURI, elemName, 0, elemScope); 01073 01074 if (other 01075 && (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() || 01076 elemDecl->getDatatypeValidator() != other->getDatatypeValidator())) { 01077 fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration, 01078 XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager); 01079 continue; 01080 } 01081 01082 RefHash2KeysTableOf<ElemVector>* validSubsGroups = currentGrammar->getValidSubstitutionGroups(); 01083 ValueVectorOf<SchemaElementDecl*>* subsElements = validSubsGroups->get(elemName, elemURI); 01084 01085 if (subsElements) { 01086 01087 XMLSize_t subsElemSize = subsElements->size(); 01088 01089 for (XMLSize_t j=0; j < subsElemSize; j++) { 01090 01091 SchemaElementDecl* subsElem = subsElements->elementAt(j); 01092 const XMLCh* subsElemName = subsElem->getBaseName(); 01093 other = (SchemaElementDecl*) 01094 currentGrammar->getElemDecl(subsElem->getURI(), subsElemName, 0, elemScope); 01095 01096 if (other 01097 && (subsElem->getComplexTypeInfo() != other->getComplexTypeInfo() 01098 || subsElem->getDatatypeValidator() != other->getDatatypeValidator())) { 01099 fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration, 01100 XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager); 01101 } 01102 } 01103 } 01104 } 01105 } 01106 } 01107 01108 // --------------------------------------------------------------------------- 01109 // SchemaValidator: Particle Derivation Checking 01110 // --------------------------------------------------------------------------- 01111 void SchemaValidator::checkParticleDerivation(SchemaGrammar* const currentGrammar, 01112 const ComplexTypeInfo* const curTypeInfo) { 01113 01114 ComplexTypeInfo* baseTypeInfo = 0; 01115 ContentSpecNode* curSpecNode = 0; 01116 01117 if (curTypeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION 01118 && ((baseTypeInfo = curTypeInfo->getBaseComplexTypeInfo()) != 0) 01119 && ((curSpecNode = curTypeInfo->getContentSpec()) != 0)) { 01120 01121 try { 01122 checkParticleDerivationOk(currentGrammar, curSpecNode, 01123 curTypeInfo->getScopeDefined(), 01124 baseTypeInfo->getContentSpec(), 01125 baseTypeInfo->getScopeDefined(), baseTypeInfo); 01126 } 01127 catch (const XMLException& excep) { 01128 fSchemaErrorReporter.emitError(excep, curTypeInfo->getLocator()); 01129 } 01130 } 01131 } 01132 01133 ContentSpecNode* SchemaValidator::getNonUnaryGroup(ContentSpecNode* const pNode) { 01134 01135 int pNodeType = (pNode->getType() & 0x0f); 01136 if (pNodeType == ContentSpecNode::Leaf 01137 || pNodeType == ContentSpecNode::Any 01138 || pNodeType == ContentSpecNode::Any_Other 01139 || pNodeType == ContentSpecNode::Any_NS) 01140 return pNode; 01141 01142 if (pNode->getMinOccurs() == 1 && pNode->getMaxOccurs() == 1 01143 && pNode->getFirst() && !pNode->getSecond()) 01144 return getNonUnaryGroup(pNode->getFirst()); 01145 01146 return pNode; 01147 } 01148 01149 void SchemaValidator::checkParticleDerivationOk(SchemaGrammar* const aGrammar, 01150 ContentSpecNode* const curNode, 01151 const int derivedScope, 01152 ContentSpecNode* const baseNode, 01153 const int baseScope, 01154 const ComplexTypeInfo* const baseInfo, 01155 const bool toCheckOccurence) { 01156 01157 // Check for pointless occurrences of all, choice, sequence. The result is 01158 // the contentspec which is not pointless. If the result is a non-pointless 01159 // group, Vector is filled in with the children of interest 01160 if (curNode && !baseNode) 01161 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_EmptyBase, fMemoryManager); 01162 01163 if (!curNode) 01164 return; 01165 01166 ContentSpecNode* curSpecNode = getNonUnaryGroup(curNode); 01167 ContentSpecNode* baseSpecNode = getNonUnaryGroup(baseNode); 01168 ValueVectorOf<ContentSpecNode*> curVector(8, fMemoryManager); 01169 ValueVectorOf<ContentSpecNode*> baseVector(8, fMemoryManager); 01170 ContentSpecNode::NodeTypes curNodeType = curSpecNode->getType(); 01171 ContentSpecNode::NodeTypes baseNodeType = baseSpecNode->getType(); 01172 01173 if ((curNodeType & 0x0f) == ContentSpecNode::Sequence || 01174 (curNodeType & 0x0f) == ContentSpecNode::Choice || 01175 curNodeType == ContentSpecNode::All) { 01176 curSpecNode = checkForPointlessOccurrences(curSpecNode, curNodeType, &curVector); 01177 } 01178 01179 if ((baseNodeType & 0x0f) == ContentSpecNode::Sequence || 01180 (baseNodeType & 0x0f) == ContentSpecNode::Choice || 01181 baseNodeType == ContentSpecNode::All) { 01182 baseSpecNode = checkForPointlessOccurrences(baseSpecNode, baseNodeType, &baseVector); 01183 } 01184 01185 curNodeType = curSpecNode->getType(); 01186 baseNodeType = baseSpecNode->getType(); 01187 01188 switch (curNodeType & 0x0f) { 01189 case ContentSpecNode::Leaf: 01190 { 01191 switch (baseNodeType & 0x0f) { 01192 case ContentSpecNode::Leaf: 01193 { 01194 checkNameAndTypeOK(aGrammar, curSpecNode, derivedScope, baseSpecNode, baseScope, baseInfo); 01195 return; 01196 } 01197 case ContentSpecNode::Any: 01198 case ContentSpecNode::Any_Other: 01199 case ContentSpecNode::Any_NS: 01200 { 01201 checkNSCompat(curSpecNode, baseSpecNode, toCheckOccurence); 01202 return; 01203 } 01204 case ContentSpecNode::Choice: 01205 case ContentSpecNode::Sequence: 01206 case ContentSpecNode::All: 01207 { 01208 checkRecurseAsIfGroup(aGrammar, curSpecNode, derivedScope, 01209 baseSpecNode, baseScope, &baseVector, baseInfo); 01210 return; 01211 } 01212 default: 01213 { 01214 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); 01215 } 01216 } 01217 } 01218 case ContentSpecNode::Any: 01219 case ContentSpecNode::Any_Other: 01220 case ContentSpecNode::Any_NS: 01221 { 01222 switch (baseNodeType & 0x0f) { 01223 case ContentSpecNode::Any: 01224 case ContentSpecNode::Any_Other: 01225 case ContentSpecNode::Any_NS: 01226 { 01227 checkNSSubset(curSpecNode, baseSpecNode); 01228 return; 01229 } 01230 case ContentSpecNode::Choice: 01231 case ContentSpecNode::Sequence: 01232 case ContentSpecNode::All: 01233 case ContentSpecNode::Leaf: 01234 { 01235 if (baseNodeType == ContentSpecNode::Any_NS_Choice) { 01236 if (checkNSSubsetChoiceRoot(curSpecNode, baseSpecNode)) { 01237 return; 01238 } 01239 } 01240 01241 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes1, fMemoryManager); 01242 } 01243 default: 01244 { 01245 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); 01246 } 01247 } 01248 } 01249 case ContentSpecNode::All: 01250 { 01251 switch (baseNodeType & 0x0f) { 01252 case ContentSpecNode::Any: 01253 case ContentSpecNode::Any_Other: 01254 case ContentSpecNode::Any_NS: 01255 { 01256 checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence); 01257 return; 01258 } 01259 case ContentSpecNode::All: 01260 { 01261 checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, 01262 baseSpecNode, baseScope, &baseVector, baseInfo); 01263 return; 01264 } 01265 case ContentSpecNode::Choice: 01266 case ContentSpecNode::Sequence: 01267 case ContentSpecNode::Leaf: 01268 { 01269 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes2, fMemoryManager); 01270 } 01271 default: 01272 { 01273 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); 01274 } 01275 } 01276 } 01277 case ContentSpecNode::Choice: 01278 { 01279 switch (baseNodeType & 0x0f) { 01280 case ContentSpecNode::Any: 01281 case ContentSpecNode::Any_Other: 01282 case ContentSpecNode::Any_NS: 01283 { 01284 checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence); 01285 return; 01286 } 01287 case ContentSpecNode::Choice: 01288 { 01289 checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, 01290 baseSpecNode, baseScope, &baseVector, baseInfo, true); 01291 return; 01292 } 01293 case ContentSpecNode::All: 01294 case ContentSpecNode::Sequence: 01295 case ContentSpecNode::Leaf: 01296 { 01297 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes3, fMemoryManager); 01298 } 01299 default: 01300 { 01301 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); 01302 } 01303 } 01304 } 01305 case ContentSpecNode::Sequence: 01306 { 01307 switch (baseNodeType & 0x0f) { 01308 case ContentSpecNode::Any: 01309 case ContentSpecNode::Any_Other: 01310 case ContentSpecNode::Any_NS: 01311 { 01312 checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence); 01313 return; 01314 } 01315 case ContentSpecNode::All: 01316 { 01317 checkRecurseUnordered(aGrammar, curSpecNode, &curVector, derivedScope, 01318 baseSpecNode, &baseVector, baseScope, baseInfo); 01319 return; 01320 } 01321 case ContentSpecNode::Sequence: 01322 { 01323 checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector, 01324 baseSpecNode, baseScope, &baseVector, baseInfo); 01325 return; 01326 } 01327 case ContentSpecNode::Choice: 01328 { 01329 checkMapAndSum(aGrammar, curSpecNode, &curVector, derivedScope, 01330 baseSpecNode, &baseVector, baseScope, baseInfo); 01331 return; 01332 } 01333 case ContentSpecNode::Leaf: 01334 { 01335 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes4, fMemoryManager); 01336 } 01337 default: 01338 { 01339 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager); 01340 } 01341 } 01342 } 01343 } 01344 } 01345 01346 ContentSpecNode* 01347 SchemaValidator::checkForPointlessOccurrences(ContentSpecNode* const specNode, 01348 const ContentSpecNode::NodeTypes nodeType, 01349 ValueVectorOf<ContentSpecNode*>* const nodes) { 01350 01351 ContentSpecNode* rightNode = specNode->getSecond(); 01352 int min = specNode->getMinOccurs(); 01353 int max = specNode->getMaxOccurs(); 01354 01355 if (!rightNode) { 01356 01357 gatherChildren(nodeType, specNode->getFirst(), nodes); 01358 01359 if (nodes->size() == 1 && min == 1 && max == 1) { 01360 return nodes->elementAt(0); 01361 } 01362 01363 return specNode; 01364 } 01365 01366 gatherChildren(nodeType, specNode->getFirst(), nodes); 01367 gatherChildren(nodeType, rightNode, nodes); 01368 01369 return specNode; 01370 } 01371 01372 void SchemaValidator::gatherChildren(const ContentSpecNode::NodeTypes parentNodeType, 01373 ContentSpecNode* const specNode, 01374 ValueVectorOf<ContentSpecNode*>* const nodes) { 01375 01376 if (!specNode) { 01377 return; 01378 } 01379 01380 int min = specNode->getMinOccurs(); 01381 int max = specNode->getMaxOccurs(); 01382 ContentSpecNode::NodeTypes nodeType = specNode->getType(); 01383 ContentSpecNode* rightNode = specNode->getSecond(); 01384 01385 if (nodeType == ContentSpecNode::Leaf || 01386 (nodeType & 0x0f) == ContentSpecNode::Any || 01387 (nodeType & 0x0f) == ContentSpecNode::Any_NS || 01388 (nodeType & 0x0f) == ContentSpecNode::Any_Other) { 01389 nodes->addElement(specNode); 01390 } 01391 else if (min !=1 || max != 1) { 01392 nodes->addElement(specNode); 01393 } 01394 else if (!rightNode) { 01395 gatherChildren(nodeType, specNode->getFirst(), nodes); 01396 } 01397 else if ((parentNodeType & 0x0f) == (nodeType & 0x0f)) { 01398 01399 gatherChildren(nodeType, specNode->getFirst(), nodes); 01400 gatherChildren(nodeType, rightNode, nodes); 01401 } 01402 else { 01403 nodes->addElement(specNode); 01404 } 01405 } 01406 01407 void 01408 SchemaValidator::checkNSCompat(const ContentSpecNode* const derivedSpecNode, 01409 const ContentSpecNode* const baseSpecNode, 01410 const bool toCheckOccurence) { 01411 01412 // check Occurrence ranges 01413 if (toCheckOccurence && 01414 !isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), 01415 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { 01416 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE, 01417 derivedSpecNode->getElement()->getLocalPart(), fMemoryManager); 01418 } 01419 01420 // check wildcard subset 01421 if (!wildcardEltAllowsNamespace(baseSpecNode, derivedSpecNode->getElement()->getURI())) { 01422 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NSCompat1, 01423 derivedSpecNode->getElement()->getLocalPart(), fMemoryManager); 01424 } 01425 } 01426 01427 bool 01428 SchemaValidator::wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode, 01429 const unsigned int derivedURI) { 01430 01431 ContentSpecNode::NodeTypes nodeType = baseSpecNode->getType(); 01432 01433 if ((nodeType & 0x0f) == ContentSpecNode::Any) { 01434 return true; 01435 } 01436 01437 unsigned int baseURI = baseSpecNode->getElement()->getURI(); 01438 01439 if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) { 01440 if (derivedURI == baseURI) { 01441 return true; 01442 } 01443 } 01444 else { // must be ANY_OTHER 01445 if (derivedURI != baseURI && derivedURI != getScanner()->getEmptyNamespaceId()) { 01446 return true; 01447 } 01448 } 01449 01450 return false; 01451 } 01452 01453 void 01454 SchemaValidator::checkNameAndTypeOK(SchemaGrammar* const currentGrammar, 01455 const ContentSpecNode* const derivedSpecNode, 01456 const int derivedScope, 01457 const ContentSpecNode* const baseSpecNode, 01458 const int baseScope, 01459 const ComplexTypeInfo* const baseInfo) { 01460 01461 if (derivedSpecNode->getMaxOccurs() == 0) 01462 return; 01463 01464 unsigned int derivedURI = derivedSpecNode->getElement()->getURI(); 01465 01466 // case of mixed complex types with attributes only 01467 if (derivedURI == XMLElementDecl::fgPCDataElemId) { 01468 return; 01469 } 01470 01471 SchemaGrammar* dGrammar = currentGrammar; 01472 01473 if (derivedURI != getScanner()->getEmptyNamespaceId()) 01474 { 01475 const XMLCh* dURI = fGrammarResolver->getStringPool()->getValueForId(derivedURI); 01476 dGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(dURI); 01477 } 01478 01479 if (!dGrammar) { //something is wrong 01480 return; 01481 } 01482 01483 const XMLCh* derivedName = derivedSpecNode->getElement()->getLocalPart(); 01484 01485 SchemaElementDecl* derivedElemDecl = findElement(derivedScope, derivedURI, derivedName, dGrammar); 01486 01487 if (!derivedElemDecl) { 01488 return; 01489 } 01490 01491 const XMLCh* baseName = baseSpecNode->getElement()->getLocalPart(); 01492 unsigned int baseURI = baseSpecNode->getElement()->getURI(); 01493 bool subsGroup = false; 01494 01495 if (!XMLString::equals(derivedName, baseName) || derivedURI != baseURI) { 01496 // Check if derived is substitutable for base. 01497 // 01498 SchemaElementDecl* e = derivedElemDecl->getSubstitutionGroupElem (); 01499 01500 for (; e != 0; e = e->getSubstitutionGroupElem ()) { 01501 if (XMLString::equals(e->getBaseName (), baseName) && e->getURI () == baseURI) { 01502 break; 01503 } 01504 } 01505 01506 if (e == 0) { 01507 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NameTypeOK1, fMemoryManager); 01508 } 01509 01510 subsGroup = true; 01511 } 01512 01513 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), 01514 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { 01515 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE, derivedName, fMemoryManager); 01516 } 01517 01518 // Find the schema grammar for the base element using the base type as 01519 // a reference if it is available (it is unavailable if we are checking 01520 // element group restriction which happens in redefine). 01521 // 01522 SchemaGrammar* bGrammar = dGrammar; 01523 01524 if (baseInfo) 01525 { 01526 const XMLCh* baseTypeURI = baseInfo->getTypeUri (); 01527 01528 if (baseTypeURI != 0 && *baseTypeURI != 0) // Non-empty namespace. 01529 bGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(baseTypeURI); 01530 01531 if (!bGrammar) { //something is wrong 01532 return; 01533 } 01534 } 01535 01536 SchemaElementDecl* baseElemDecl = 01537 findElement(baseScope, baseURI, baseName, bGrammar, baseInfo); 01538 01539 if (!baseElemDecl) { 01540 return; 01541 } 01542 01543 int derivedFlags = derivedElemDecl->getMiscFlags(); 01544 int baseFlags = baseElemDecl->getMiscFlags(); 01545 01546 if (((baseFlags & SchemaSymbols::XSD_NILLABLE) == 0) && 01547 ((derivedFlags & SchemaSymbols::XSD_NILLABLE) != 0)) { 01548 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK2, derivedName, fMemoryManager); 01549 } 01550 01551 const XMLCh* derivedDefVal = derivedElemDecl->getDefaultValue(); 01552 const XMLCh* baseDefVal = baseElemDecl->getDefaultValue(); 01553 01554 if (baseDefVal && (baseFlags & SchemaSymbols::XSD_FIXED) != 0 && 01555 ((derivedFlags & SchemaSymbols::XSD_FIXED) == 0 || 01556 !XMLString::equals(derivedDefVal, baseDefVal))) { 01557 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK3, derivedName, fMemoryManager); 01558 } 01559 01560 int derivedBlockSet = derivedElemDecl->getBlockSet(); 01561 int baseBlockSet = baseElemDecl->getBlockSet(); 01562 01563 if ((derivedBlockSet & baseBlockSet) != baseBlockSet) { 01564 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK4, derivedName, fMemoryManager); 01565 } 01566 01567 // check identity constraints 01568 checkICRestriction(derivedElemDecl, baseElemDecl, derivedName, baseName); 01569 01570 // check that the derived element's type is derived from the base's. 01571 if (!subsGroup) 01572 checkTypesOK(derivedElemDecl, baseElemDecl, derivedName); 01573 } 01574 01575 SchemaElementDecl* 01576 SchemaValidator::findElement(const int scope, const unsigned int uriIndex, 01577 const XMLCh* const name, 01578 SchemaGrammar* const grammar, 01579 const ComplexTypeInfo* const typeInfo) { 01580 01581 // check for element at given scope first 01582 SchemaElementDecl* elemDecl = (SchemaElementDecl*) grammar->getElemDecl(uriIndex, name, 0, scope); 01583 01584 // if not found, check at global scope 01585 if (!elemDecl) { 01586 01587 elemDecl = (SchemaElementDecl*) 01588 grammar->getElemDecl(uriIndex, name, 0, Grammar::TOP_LEVEL_SCOPE); 01589 01590 // if still not found, and base is specified, look it up there 01591 if (!elemDecl && typeInfo) { 01592 01593 const ComplexTypeInfo* baseInfo = typeInfo; 01594 01595 while (baseInfo) { 01596 01597 elemDecl = (SchemaElementDecl*) 01598 grammar->getElemDecl(uriIndex, name, 0, baseInfo->getScopeDefined()); 01599 01600 if (elemDecl) { 01601 break; 01602 } 01603 01604 baseInfo = baseInfo->getBaseComplexTypeInfo(); 01605 } 01606 } 01607 } 01608 01609 return elemDecl; 01610 } 01611 01612 void 01613 SchemaValidator::checkICRestriction(const SchemaElementDecl* const derivedElemDecl, 01614 const SchemaElementDecl* const baseElemDecl, 01615 const XMLCh* const derivedElemName, 01616 const XMLCh* const baseElemName) { 01617 01618 // REVIST - need to get more clarification 01619 XMLSize_t derivedICCount = derivedElemDecl->getIdentityConstraintCount(); 01620 XMLSize_t baseICCount = baseElemDecl->getIdentityConstraintCount(); 01621 01622 if (derivedICCount > baseICCount) { 01623 ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK6, derivedElemName, baseElemName, fMemoryManager); 01624 } 01625 01626 for (XMLSize_t i=0; i < derivedICCount; i++) { 01627 01628 bool found = false; 01629 IdentityConstraint* ic= derivedElemDecl->getIdentityConstraintAt(i); 01630 01631 for (XMLSize_t j=0; j < baseICCount; j++) { 01632 if (*ic == *(baseElemDecl->getIdentityConstraintAt(j))) { 01633 01634 found = true; 01635 break; 01636 } 01637 } 01638 01639 if (!found) { 01640 ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK7, derivedElemName, baseElemName, fMemoryManager); 01641 } 01642 } 01643 } 01644 01645 void 01646 SchemaValidator::checkTypesOK(const SchemaElementDecl* const derivedElemDecl, 01647 const SchemaElementDecl* const baseElemDecl, 01648 const XMLCh* const derivedElemName) { 01649 01650 SchemaElementDecl::ModelTypes baseType = baseElemDecl->getModelType(); 01651 01652 if (baseType == SchemaElementDecl::Any) { 01653 return; 01654 } 01655 01656 ComplexTypeInfo* rInfo = derivedElemDecl->getComplexTypeInfo(); 01657 ComplexTypeInfo* bInfo = baseElemDecl->getComplexTypeInfo(); 01658 01659 if (derivedElemDecl->getModelType() == SchemaElementDecl::Simple) { 01660 01661 if (baseType != SchemaElementDecl::Simple) { 01662 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager); 01663 } 01664 01665 if (!rInfo) { 01666 01667 DatatypeValidator* bDV = baseElemDecl->getDatatypeValidator(); 01668 01669 if (bInfo || bDV == 0 || 01670 !bDV->isSubstitutableBy(derivedElemDecl->getDatatypeValidator())) { 01671 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager); 01672 } 01673 01674 return; 01675 } 01676 } 01677 01678 if (rInfo == bInfo) 01679 return; 01680 01681 for (; rInfo && rInfo != bInfo; rInfo = rInfo->getBaseComplexTypeInfo()) { 01682 if (rInfo->getDerivedBy() != SchemaSymbols::XSD_RESTRICTION) { 01683 01684 rInfo = 0; 01685 break; 01686 } 01687 } 01688 01689 if (!rInfo) { 01690 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager); 01691 } 01692 } 01693 01694 void 01695 SchemaValidator::checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar, 01696 ContentSpecNode* const derivedSpecNodeIn, 01697 const int derivedScope, 01698 const ContentSpecNode* const baseSpecNode, 01699 const int baseScope, 01700 ValueVectorOf<ContentSpecNode*>* const baseNodes, 01701 const ComplexTypeInfo* const baseInfo) { 01702 01703 ContentSpecNode::NodeTypes baseType = baseSpecNode->getType(); 01704 bool toLax = false; 01705 01706 //Treat the element as if it were in a group of the same variety as base 01707 ContentSpecNode derivedGroupNode(baseType, derivedSpecNodeIn, 0, false, true, fMemoryManager); 01708 const ContentSpecNode* const derivedSpecNode = &derivedGroupNode; 01709 01710 if ((baseSpecNode->getType() & 0x0f) == ContentSpecNode::Choice) { 01711 toLax = true; 01712 } 01713 01714 // Instead of calling this routine, inline it 01715 // checkRecurse(currentGrammar, &derivedGroupNode, derivedScope, &derivedNodes, 01716 // baseSpecNode, baseScope, baseNodes, baseInfo, toLax); 01717 01718 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), 01719 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { 01720 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager); 01721 } 01722 01723 // check for mapping of children 01724 XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; 01725 XMLSize_t count2= baseNodes->size(); 01726 XMLSize_t current = 0; 01727 01728 { 01729 bool matched = false; 01730 01731 for (XMLSize_t j = current; j < count2; j++) { 01732 01733 ContentSpecNode* baseNode = baseNodes->elementAt(j); 01734 current++; 01735 01736 bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch' 01737 try { 01738 01739 checkParticleDerivationOk(currentGrammar, derivedSpecNodeIn, 01740 derivedScope, baseNode, baseScope, baseInfo); 01741 matched = true; 01742 break; 01743 } 01744 catch(const XMLException&) { 01745 if (!toLax && baseNode->getMinTotalRange()) { 01746 bDoBreak=true; 01747 } 01748 } 01749 if(bDoBreak) 01750 break; 01751 } 01752 01753 // did not find a match 01754 if (!matched) { 01755 codeToThrow = XMLExcepts::PD_Recurse2; 01756 } 01757 } 01758 01759 // Now, see if there are some elements in the base we didn't match up 01760 // in case of Sequence or All 01761 if (!toLax && codeToThrow == XMLExcepts::NoError) { 01762 for (XMLSize_t j = current; j < count2; j++) { 01763 if (baseNodes->elementAt(j)->getMinTotalRange() * baseSpecNode->getMinOccurs()) { 01764 codeToThrow = XMLExcepts::PD_Recurse2; 01765 break; 01766 } 01767 } 01768 } 01769 01770 if (codeToThrow != XMLExcepts::NoError) { 01771 ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager); 01772 } 01773 } 01774 01775 void 01776 SchemaValidator::checkRecurse(SchemaGrammar* const currentGrammar, 01777 const ContentSpecNode* const derivedSpecNode, 01778 const int derivedScope, 01779 ValueVectorOf<ContentSpecNode*>* const derivedNodes, 01780 const ContentSpecNode* const baseSpecNode, 01781 const int baseScope, 01782 ValueVectorOf<ContentSpecNode*>* const baseNodes, 01783 const ComplexTypeInfo* const baseInfo, 01784 const bool toLax) { 01785 01786 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), 01787 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { 01788 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager); 01789 } 01790 01791 // check for mapping of children 01792 XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; 01793 XMLSize_t count1= derivedNodes->size(); 01794 XMLSize_t count2= baseNodes->size(); 01795 XMLSize_t current = 0; 01796 01797 for (XMLSize_t i=0; i<count1; i++) { 01798 01799 bool matched = false; 01800 01801 for (XMLSize_t j = current; j < count2; j++) { 01802 01803 ContentSpecNode* baseNode = baseNodes->elementAt(j); 01804 current++; 01805 01806 bool bDoBreak=false; // workaround for Borland bug with 'break' in 'catch' 01807 try { 01808 01809 checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), 01810 derivedScope, baseNode, baseScope, baseInfo); 01811 matched = true; 01812 break; 01813 } 01814 catch(const XMLException&) { 01815 if (!toLax && baseNode->getMinTotalRange()) { 01816 bDoBreak=true; 01817 } 01818 } 01819 if(bDoBreak) 01820 break; 01821 } 01822 01823 // did not find a match 01824 if (!matched) { 01825 01826 codeToThrow = XMLExcepts::PD_Recurse2; 01827 break; 01828 } 01829 } 01830 01831 // Now, see if there are some elements in the base we didn't match up 01832 // in case of Sequence or All 01833 if (!toLax && codeToThrow == XMLExcepts::NoError) { 01834 for (XMLSize_t j = current; j < count2; j++) { 01835 if (baseNodes->elementAt(j)->getMinTotalRange()) { 01836 codeToThrow = XMLExcepts::PD_Recurse2; 01837 break; 01838 } 01839 } 01840 } 01841 01842 if (codeToThrow != XMLExcepts::NoError) { 01843 ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager); 01844 } 01845 } 01846 01847 void SchemaValidator::checkNSSubset(const ContentSpecNode* const derivedSpecNode, 01848 const ContentSpecNode* const baseSpecNode) { 01849 01850 // check Occurrence ranges 01851 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), 01852 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { 01853 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset1, fMemoryManager); 01854 } 01855 01856 if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) { 01857 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset2, fMemoryManager); 01858 } 01859 } 01860 01861 bool SchemaValidator::checkNSSubsetChoiceRoot(const ContentSpecNode* const derivedSpecNode, 01862 const ContentSpecNode* const baseSpecNode) { 01863 bool found = false; 01864 01865 if (baseSpecNode->getType() == ContentSpecNode::Any_NS_Choice) { 01866 const ContentSpecNode* first = baseSpecNode->getFirst(); 01867 const ContentSpecNode* second = baseSpecNode->getSecond(); 01868 01869 if (first) { 01870 found = checkNSSubsetChoiceRoot(derivedSpecNode, first); 01871 if (found) return true; 01872 } 01873 if (second) { 01874 found = checkNSSubsetChoiceRoot(derivedSpecNode, second); 01875 if (found) return true; 01876 } 01877 } 01878 else { // should be Any_NS 01879 found = checkNSSubsetChoice(derivedSpecNode, baseSpecNode); 01880 } 01881 01882 return found; 01883 } 01884 01885 bool SchemaValidator::checkNSSubsetChoice(const ContentSpecNode* const derivedSpecNode, 01886 const ContentSpecNode* const baseSpecNode) { 01887 01888 // check Occurrence ranges 01889 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), 01890 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { 01891 return false; 01892 } 01893 01894 if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) { 01895 return false; 01896 } 01897 return true; 01898 } 01899 01900 bool 01901 SchemaValidator::isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode, 01902 const ContentSpecNode* const baseSpecNode) { 01903 01904 ContentSpecNode::NodeTypes baseType = baseSpecNode->getType(); 01905 01906 if ((baseType & 0x0f) == ContentSpecNode::Any) { 01907 return true; 01908 } 01909 01910 ContentSpecNode::NodeTypes derivedType = derivedSpecNode->getType(); 01911 unsigned int baseURI = baseSpecNode->getElement()->getURI(); 01912 unsigned int derivedURI = derivedSpecNode->getElement()->getURI(); 01913 01914 // Below we assume that empty string has id 1. 01915 // 01916 if (((derivedType & 0x0f) == ContentSpecNode::Any_Other) && 01917 ((baseType & 0x0f) == ContentSpecNode::Any_Other) && 01918 (baseURI == derivedURI || baseURI == 1)) { 01919 return true; 01920 } 01921 01922 if ((derivedType & 0x0f) == ContentSpecNode::Any_NS) { 01923 01924 if (((baseType & 0x0f) == ContentSpecNode::Any_NS) && 01925 baseURI == derivedURI) { 01926 return true; 01927 } 01928 01929 if (((baseType & 0x0f) == ContentSpecNode::Any_Other) && 01930 (derivedURI == 1 || baseURI != derivedURI)) { 01931 return true; 01932 } 01933 } 01934 01935 return false; 01936 } 01937 01938 void 01939 SchemaValidator::checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar, 01940 const ContentSpecNode* const derivedSpecNode, 01941 ValueVectorOf<ContentSpecNode*>* const derivedNodes, 01942 const int derivedScope, 01943 ContentSpecNode* const baseSpecNode, 01944 const bool toCheckOccurence) { 01945 01946 // Implement total range check 01947 int derivedMin = derivedSpecNode->getMinTotalRange(); 01948 int derivedMax = derivedSpecNode->getMaxTotalRange(); 01949 01950 // check Occurrence ranges 01951 if (toCheckOccurence && 01952 !isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(), 01953 baseSpecNode->getMaxOccurs())) { 01954 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSRecurseCheckCardinality1, fMemoryManager); 01955 } 01956 01957 // Check that each member of the group is a valid restriction of the wildcard 01958 XMLSize_t nodesCount = derivedNodes->size(); 01959 01960 for (XMLSize_t i = 0; i < nodesCount; i++) { 01961 checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), derivedScope, baseSpecNode, -1, 0, false); 01962 } 01963 } 01964 01965 void 01966 SchemaValidator::checkRecurseUnordered(SchemaGrammar* const currentGrammar, 01967 const ContentSpecNode* const derivedSpecNode, 01968 ValueVectorOf<ContentSpecNode*>* const derivedNodes, 01969 const int derivedScope, 01970 ContentSpecNode* const baseSpecNode, 01971 ValueVectorOf<ContentSpecNode*>* const baseNodes, 01972 const int baseScope, 01973 const ComplexTypeInfo* const baseInfo) { 01974 01975 // check Occurrence ranges 01976 if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(), 01977 baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) { 01978 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager); 01979 } 01980 01981 XMLExcepts::Codes codeToThrow = XMLExcepts::NoError; 01982 XMLSize_t derivedCount= derivedNodes->size(); 01983 XMLSize_t baseCount = baseNodes->size(); 01984 bool* foundIt = (bool*) fMemoryManager->allocate 01985 ( 01986 baseCount * sizeof(bool) 01987 );//new bool[baseCount]; 01988 ArrayJanitor<bool> janFoundIt(foundIt, fMemoryManager); 01989 01990 for (XMLSize_t k=0; k < baseCount; k++) { 01991 foundIt[k] = false; 01992 } 01993 01994 // check for mapping of children 01995 for (XMLSize_t i = 0; i < derivedCount; i++) { 01996 01997 ContentSpecNode* derivedNode = derivedNodes->elementAt(i); 01998 bool matched = false; 01999 02000 for (XMLSize_t j = 0; j < baseCount; j++) { 02001 02002 try { 02003 02004 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope, 02005 baseNodes->elementAt(j), baseScope, baseInfo); 02006 02007 if (foundIt[j]) { 02008 break; 02009 } 02010 02011 foundIt[j] = true; 02012 matched = true; 02013 break; 02014 } 02015 catch (const XMLException&) { 02016 } 02017 } 02018 02019 // didn't find a match. 02020 if (!matched) { 02021 02022 codeToThrow = XMLExcepts::PD_RecurseUnordered; 02023 break; 02024 } 02025 } 02026 02027 // For all unmapped particles in base, check to see it it's emptiable or not 02028 if (codeToThrow == XMLExcepts::NoError) { 02029 for (XMLSize_t j=0; j < baseCount; j++) { 02030 if (!foundIt[j] && baseNodes->elementAt(j)->getMinTotalRange()) { 02031 02032 codeToThrow = XMLExcepts::PD_RecurseUnordered; 02033 break; 02034 } 02035 } 02036 } 02037 02038 if (codeToThrow != XMLExcepts::NoError) { 02039 ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager); 02040 } 02041 } 02042 02043 void 02044 SchemaValidator::checkMapAndSum(SchemaGrammar* const currentGrammar, 02045 const ContentSpecNode* const derivedSpecNode, 02046 ValueVectorOf<ContentSpecNode*>* const derivedNodes, 02047 const int derivedScope, 02048 ContentSpecNode* const baseSpecNode, 02049 ValueVectorOf<ContentSpecNode*>* const baseNodes, 02050 const int baseScope, 02051 const ComplexTypeInfo* const baseInfo) { 02052 02053 // check Occurrence ranges 02054 XMLSize_t derivedCount = derivedNodes->size(); 02055 XMLSize_t baseCount = baseNodes->size(); 02056 int derivedMin = derivedSpecNode->getMinOccurs() * (unsigned int)derivedCount; 02057 int derivedMax = derivedSpecNode->getMaxOccurs(); 02058 02059 if (derivedMax != SchemaSymbols::XSD_UNBOUNDED) { 02060 derivedMax *= (unsigned int)derivedCount; 02061 } 02062 02063 if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(), 02064 baseSpecNode->getMaxOccurs())) { 02065 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager); 02066 } 02067 02068 // check for mapping of children 02069 for (XMLSize_t i = 0; i < derivedCount; i++) { 02070 02071 ContentSpecNode* derivedNode = derivedNodes->elementAt(i); 02072 bool matched = false; 02073 02074 for (XMLSize_t j = 0; j < baseCount && !matched; j++) { 02075 02076 try { 02077 02078 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope, 02079 baseNodes->elementAt(j), baseScope, baseInfo); 02080 matched = true; 02081 } 02082 catch (const XMLException&) { 02083 } 02084 } 02085 02086 // didn't find a match. 02087 if (!matched) { 02088 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_MapAndSum, fMemoryManager); 02089 } 02090 } 02091 02092 } 02093 02094 XERCES_CPP_NAMESPACE_END