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 $ 00020 */ 00021 00022 #include <xercesc/validators/common/GrammarResolver.hpp> 00023 #include <xercesc/validators/schema/SchemaSymbols.hpp> 00024 #include <xercesc/validators/schema/SchemaGrammar.hpp> 00025 #include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp> 00026 #include <xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp> 00027 #include <xercesc/framework/XMLGrammarPoolImpl.hpp> 00028 #include <xercesc/framework/psvi/XSAnnotation.hpp> 00029 00030 XERCES_CPP_NAMESPACE_BEGIN 00031 00032 // --------------------------------------------------------------------------- 00033 // GrammarResolver: Constructor and Destructor 00034 // --------------------------------------------------------------------------- 00035 GrammarResolver::GrammarResolver(XMLGrammarPool* const gramPool 00036 , MemoryManager* const manager) 00037 :fCacheGrammar(false) 00038 ,fUseCachedGrammar(false) 00039 ,fGrammarPoolFromExternalApplication(true) 00040 ,fStringPool(0) 00041 ,fGrammarBucket(0) 00042 ,fGrammarFromPool(0) 00043 ,fDataTypeReg(0) 00044 ,fMemoryManager(manager) 00045 ,fGrammarPool(gramPool) 00046 ,fXSModel(0) 00047 ,fGrammarPoolXSModel(0) 00048 ,fGrammarsToAddToXSModel(0) 00049 { 00050 fGrammarBucket = new (manager) RefHashTableOf<Grammar>(29, true, manager); 00051 00052 /*** 00053 * Grammars in this set are not owned 00054 */ 00055 fGrammarFromPool = new (manager) RefHashTableOf<Grammar>(29, false, manager); 00056 00057 if (!gramPool) 00058 { 00059 /*** 00060 * We need to instantiate a default grammar pool object so that 00061 * all grammars and grammar components could be created through 00062 * the Factory methods 00063 */ 00064 fGrammarPool = new (manager) XMLGrammarPoolImpl(manager); 00065 fGrammarPoolFromExternalApplication=false; 00066 } 00067 fStringPool = fGrammarPool->getURIStringPool(); 00068 00069 // REVISIT: size 00070 fGrammarsToAddToXSModel = new (manager) ValueVectorOf<SchemaGrammar*> (29, manager); 00071 } 00072 00073 GrammarResolver::~GrammarResolver() 00074 { 00075 delete fGrammarBucket; 00076 delete fGrammarFromPool; 00077 00078 if (fDataTypeReg) 00079 delete fDataTypeReg; 00080 00081 /*** 00082 * delete the grammar pool iff it is created by this resolver 00083 */ 00084 if (!fGrammarPoolFromExternalApplication) 00085 delete fGrammarPool; 00086 00087 if (fXSModel) 00088 delete fXSModel; 00089 // don't delete fGrammarPoolXSModel! we don't own it! 00090 delete fGrammarsToAddToXSModel; 00091 } 00092 00093 // --------------------------------------------------------------------------- 00094 // GrammarResolver: Getter methods 00095 // --------------------------------------------------------------------------- 00096 DatatypeValidator* 00097 GrammarResolver::getDatatypeValidator(const XMLCh* const uriStr, 00098 const XMLCh* const localPartStr) { 00099 00100 DatatypeValidator* dv = 0; 00101 00102 if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { 00103 00104 if (!fDataTypeReg) { 00105 00106 fDataTypeReg = new (fMemoryManager) DatatypeValidatorFactory(fMemoryManager); 00107 } 00108 00109 dv = fDataTypeReg->getDatatypeValidator(localPartStr); 00110 } 00111 else { 00112 00113 Grammar* grammar = getGrammar(uriStr); 00114 00115 if (grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) { 00116 00117 XMLBuffer nameBuf(128, fMemoryManager); 00118 00119 nameBuf.set(uriStr); 00120 nameBuf.append(chComma); 00121 nameBuf.append(localPartStr); 00122 00123 dv = ((SchemaGrammar*) grammar)->getDatatypeRegistry()->getDatatypeValidator(nameBuf.getRawBuffer()); 00124 } 00125 } 00126 00127 return dv; 00128 } 00129 00130 Grammar* GrammarResolver::getGrammar( const XMLCh* const namespaceKey) 00131 { 00132 if (!namespaceKey) 00133 return 0; 00134 00135 Grammar* grammar = fGrammarBucket->get(namespaceKey); 00136 00137 if (grammar) 00138 return grammar; 00139 00140 if (fUseCachedGrammar) 00141 { 00142 grammar = fGrammarFromPool->get(namespaceKey); 00143 if (grammar) 00144 { 00145 return grammar; 00146 } 00147 else 00148 { 00149 XMLSchemaDescription* gramDesc = fGrammarPool->createSchemaDescription(namespaceKey); 00150 Janitor<XMLGrammarDescription> janName(gramDesc); 00151 grammar = fGrammarPool->retrieveGrammar(gramDesc); 00152 if (grammar) 00153 { 00154 fGrammarFromPool->put((void*) grammar->getGrammarDescription()->getGrammarKey(), grammar); 00155 } 00156 return grammar; 00157 } 00158 } 00159 00160 return 0; 00161 } 00162 00163 Grammar* GrammarResolver::getGrammar( XMLGrammarDescription* const gramDesc) 00164 { 00165 if (!gramDesc) 00166 return 0; 00167 00168 Grammar* grammar = fGrammarBucket->get(gramDesc->getGrammarKey()); 00169 00170 if (grammar) 00171 return grammar; 00172 00173 if (fUseCachedGrammar) 00174 { 00175 grammar = fGrammarFromPool->get(gramDesc->getGrammarKey()); 00176 if (grammar) 00177 { 00178 return grammar; 00179 } 00180 else 00181 { 00182 grammar = fGrammarPool->retrieveGrammar(gramDesc); 00183 if (grammar) 00184 { 00185 fGrammarFromPool->put((void*) grammar->getGrammarDescription()->getGrammarKey(), grammar); 00186 } 00187 return grammar; 00188 } 00189 } 00190 00191 return 0; 00192 } 00193 00194 RefHashTableOfEnumerator<Grammar> 00195 GrammarResolver::getGrammarEnumerator() const 00196 { 00197 return RefHashTableOfEnumerator<Grammar>(fGrammarBucket, false, fMemoryManager); 00198 } 00199 00200 RefHashTableOfEnumerator<Grammar> 00201 GrammarResolver::getReferencedGrammarEnumerator() const 00202 { 00203 return RefHashTableOfEnumerator<Grammar>(fGrammarFromPool, false, fMemoryManager); 00204 } 00205 00206 RefHashTableOfEnumerator<Grammar> 00207 GrammarResolver::getCachedGrammarEnumerator() const 00208 { 00209 return fGrammarPool->getGrammarEnumerator(); 00210 } 00211 00212 bool GrammarResolver::containsNameSpace( const XMLCh* const nameSpaceKey ) 00213 { 00214 if (!nameSpaceKey) 00215 return false; 00216 if (fGrammarBucket->containsKey(nameSpaceKey)) 00217 return true; 00218 if (fUseCachedGrammar) 00219 { 00220 if (fGrammarFromPool->containsKey(nameSpaceKey)) 00221 return true; 00222 00223 // Lastly, need to check in fGrammarPool 00224 XMLSchemaDescription* gramDesc = fGrammarPool->createSchemaDescription(nameSpaceKey); 00225 Janitor<XMLGrammarDescription> janName(gramDesc); 00226 Grammar* grammar = fGrammarPool->retrieveGrammar(gramDesc); 00227 if (grammar) 00228 return true; 00229 } 00230 00231 return false; 00232 } 00233 00234 void GrammarResolver::putGrammar(Grammar* const grammarToAdopt) 00235 { 00236 if (!grammarToAdopt) 00237 return; 00238 00239 /*** 00240 * the grammar will be either in the grammarpool, or in the grammarbucket 00241 */ 00242 if (!fCacheGrammar || !fGrammarPool->cacheGrammar(grammarToAdopt)) 00243 { 00244 // either we aren't caching or the grammar pool doesn't want it 00245 // so we need to look after it 00246 fGrammarBucket->put( (void*) grammarToAdopt->getGrammarDescription()->getGrammarKey(), grammarToAdopt ); 00247 if (grammarToAdopt->getGrammarType() == Grammar::SchemaGrammarType) 00248 { 00249 fGrammarsToAddToXSModel->addElement((SchemaGrammar*) grammarToAdopt); 00250 } 00251 } 00252 } 00253 00254 // --------------------------------------------------------------------------- 00255 // GrammarResolver: methods 00256 // --------------------------------------------------------------------------- 00257 void GrammarResolver::reset() { 00258 fGrammarBucket->removeAll(); 00259 fGrammarsToAddToXSModel->removeAllElements(); 00260 delete fXSModel; 00261 fXSModel = 0; 00262 } 00263 00264 void GrammarResolver::resetCachedGrammar() 00265 { 00266 //REVISIT: if the pool is locked this will fail... should throw an exception? 00267 fGrammarPool->clear(); 00268 // Even though fXSModel and fGrammarPoolXSModel will be invalid don't touch 00269 // them here as getXSModel will handle this. 00270 00271 //to clear all other references to the grammars just deleted from fGrammarPool 00272 fGrammarFromPool->removeAll(); 00273 00274 } 00275 00276 void GrammarResolver::cacheGrammars() 00277 { 00278 RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarBucket, false, fMemoryManager); 00279 ValueVectorOf<XMLCh*> keys(8, fMemoryManager); 00280 unsigned int keyCount = 0; 00281 00282 // Build key set 00283 while (grammarEnum.hasMoreElements()) 00284 { 00285 XMLCh* grammarKey = (XMLCh*) grammarEnum.nextElementKey(); 00286 keys.addElement(grammarKey); 00287 keyCount++; 00288 } 00289 00290 // PSVI: assume everything will be added, if caching fails add grammar back 00291 // into vector 00292 fGrammarsToAddToXSModel->removeAllElements(); 00293 00294 // Cache 00295 for (unsigned int i = 0; i < keyCount; i++) 00296 { 00297 XMLCh* grammarKey = keys.elementAt(i); 00298 00299 /*** 00300 * It is up to the GrammarPool implementation to handle duplicated grammar 00301 */ 00302 Grammar* grammar = fGrammarBucket->get(grammarKey); 00303 if(fGrammarPool->cacheGrammar(grammar)) 00304 { 00305 // only orphan grammar if grammar pool accepts caching of it 00306 fGrammarBucket->orphanKey(grammarKey); 00307 } 00308 else if (grammar->getGrammarType() == Grammar::SchemaGrammarType) 00309 { 00310 // add it back to list of grammars not in grammar pool 00311 fGrammarsToAddToXSModel->addElement((SchemaGrammar*) grammar); 00312 } 00313 } 00314 00315 } 00316 00317 // --------------------------------------------------------------------------- 00318 // GrammarResolver: Setter methods 00319 // --------------------------------------------------------------------------- 00320 void GrammarResolver::cacheGrammarFromParse(const bool aValue) 00321 { 00322 reset(); 00323 fCacheGrammar = aValue; 00324 } 00325 00326 Grammar* GrammarResolver::orphanGrammar(const XMLCh* const nameSpaceKey) 00327 { 00328 if (fCacheGrammar) 00329 { 00330 Grammar* grammar = fGrammarPool->orphanGrammar(nameSpaceKey); 00331 if (grammar) 00332 { 00333 if (fGrammarFromPool->containsKey(nameSpaceKey)) 00334 fGrammarFromPool->removeKey(nameSpaceKey); 00335 } 00336 // Check to see if it's in fGrammarBucket, since 00337 // we put it there if the grammar pool refused to 00338 // cache it. 00339 else if (fGrammarBucket->containsKey(nameSpaceKey)) 00340 { 00341 grammar = fGrammarBucket->orphanKey(nameSpaceKey); 00342 } 00343 00344 return grammar; 00345 } 00346 else 00347 { 00348 return fGrammarBucket->orphanKey(nameSpaceKey); 00349 } 00350 } 00351 00352 XSModel *GrammarResolver::getXSModel() 00353 { 00354 XSModel* xsModel; 00355 if (fCacheGrammar || fUseCachedGrammar) 00356 { 00357 // We know if the grammarpool changed thru caching, orphaning and erasing 00358 // but NOT by other mechanisms such as lockPool() or unlockPool() so it 00359 // is safest to always get it. The grammarPool XSModel will only be 00360 // regenerated if something changed. 00361 bool XSModelWasChanged; 00362 // The grammarpool will always return an xsmodel, even if it is just 00363 // the schema for schema xsmodel... 00364 xsModel = fGrammarPool->getXSModel(XSModelWasChanged); 00365 if (XSModelWasChanged) 00366 { 00367 // we know the grammarpool XSModel has changed or this is the 00368 // first call to getXSModel 00369 if (!fGrammarPoolXSModel && (fGrammarsToAddToXSModel->size() == 0) && 00370 !fXSModel) 00371 { 00372 fGrammarPoolXSModel = xsModel; 00373 return fGrammarPoolXSModel; 00374 } 00375 else 00376 { 00377 fGrammarPoolXSModel = xsModel; 00378 // We had previously augmented the grammar pool XSModel 00379 // with our our grammars or we would like to upate it now 00380 // so we have to regenerate the XSModel 00381 fGrammarsToAddToXSModel->removeAllElements(); 00382 RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarBucket, false, fMemoryManager); 00383 while (grammarEnum.hasMoreElements()) 00384 { 00385 Grammar& grammar = (Grammar&) grammarEnum.nextElement(); 00386 if (grammar.getGrammarType() == Grammar::SchemaGrammarType) 00387 fGrammarsToAddToXSModel->addElement((SchemaGrammar*)&grammar); 00388 } 00389 delete fXSModel; 00390 if (fGrammarsToAddToXSModel->size()) 00391 { 00392 fXSModel = new (fMemoryManager) XSModel(fGrammarPoolXSModel, this, fMemoryManager); 00393 fGrammarsToAddToXSModel->removeAllElements(); 00394 return fXSModel; 00395 } 00396 fXSModel = 0; 00397 return fGrammarPoolXSModel; 00398 } 00399 } 00400 else { 00401 // we know that the grammar pool XSModel is the same as before 00402 if (fGrammarsToAddToXSModel->size()) 00403 { 00404 // we need to update our fXSModel with the new grammars 00405 if (fXSModel) 00406 { 00407 xsModel = new (fMemoryManager) XSModel(fXSModel, this, fMemoryManager); 00408 fXSModel = xsModel; 00409 } 00410 else 00411 { 00412 fXSModel = new (fMemoryManager) XSModel(fGrammarPoolXSModel, this, fMemoryManager); 00413 } 00414 fGrammarsToAddToXSModel->removeAllElements(); 00415 return fXSModel; 00416 } 00417 // Nothing has changed! 00418 if (fXSModel) 00419 { 00420 return fXSModel; 00421 } 00422 else if (fGrammarPoolXSModel) 00423 { 00424 return fGrammarPoolXSModel; 00425 } 00426 fXSModel = new (fMemoryManager) XSModel(0, this, fMemoryManager); 00427 return fXSModel; 00428 } 00429 } 00430 // Not Caching... 00431 if (fGrammarsToAddToXSModel->size()) 00432 { 00433 xsModel = new (fMemoryManager) XSModel(fXSModel, this, fMemoryManager); 00434 fGrammarsToAddToXSModel->removeAllElements(); 00435 fXSModel = xsModel; 00436 } 00437 else if (!fXSModel) 00438 { 00439 // create a new model only if we didn't have one already 00440 fXSModel = new (fMemoryManager) XSModel(0, this, fMemoryManager); 00441 } 00442 return fXSModel; 00443 } 00444 00445 XERCES_CPP_NAMESPACE_END