GME  13
XMLGrammarPoolImpl.cpp
Go to the documentation of this file.
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: XMLGrammarPoolImpl.cpp 676823 2008-07-15 07:57:44Z borisk $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <xercesc/framework/XMLGrammarPoolImpl.hpp>
00027 #include <xercesc/internal/XSerializeEngine.hpp>
00028 #include <xercesc/internal/XTemplateSerializer.hpp>
00029 #include <xercesc/validators/DTD/DTDGrammar.hpp>
00030 #include <xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp>
00031 #include <xercesc/validators/schema/SchemaGrammar.hpp>
00032 #include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp>
00033 #include <xercesc/util/OutOfMemoryException.hpp>
00034 #include <xercesc/util/SynchronizedStringPool.hpp>
00035 
00036 XERCES_CPP_NAMESPACE_BEGIN
00037 
00038 // private function used to update fXSModel
00039 void XMLGrammarPoolImpl::createXSModel()
00040 {
00041     delete fXSModel;
00042     fXSModel = 0;
00043     fXSModel = new (getMemoryManager()) XSModel(this, getMemoryManager());
00044     fXSModelIsValid = true;
00045 }
00046 
00047 // ---------------------------------------------------------------------------
00048 //  XMLGrammarPoolImpl: constructor and destructor
00049 // ---------------------------------------------------------------------------
00050 XMLGrammarPoolImpl::~XMLGrammarPoolImpl()
00051 {
00052     delete fGrammarRegistry;
00053     delete fStringPool;
00054     if(fSynchronizedStringPool)
00055         delete fSynchronizedStringPool;
00056     if(fXSModel)
00057         delete fXSModel;
00058 }
00059 
00060 XMLGrammarPoolImpl::XMLGrammarPoolImpl(MemoryManager* const memMgr)
00061 :XMLGrammarPool(memMgr)
00062 ,fGrammarRegistry(0)
00063 ,fStringPool(0)
00064 ,fSynchronizedStringPool(0)
00065 ,fXSModel(0)
00066 ,fLocked(false)
00067 ,fXSModelIsValid(false)
00068 {
00069     fGrammarRegistry = new (memMgr) RefHashTableOf<Grammar>(29, true, memMgr);
00070     fStringPool = new (memMgr) XMLStringPool(109, memMgr);
00071 }
00072 
00073 // -----------------------------------------------------------------------
00074 // Implementation of Grammar Pool Interface
00075 // -----------------------------------------------------------------------
00076 bool XMLGrammarPoolImpl::cacheGrammar(Grammar* const               gramToCache )
00077 {
00078     if(fLocked || !gramToCache)
00079         return false;
00080 
00081     const XMLCh* grammarKey = gramToCache->getGrammarDescription()->getGrammarKey();
00082 
00083     if (fGrammarRegistry->containsKey(grammarKey))
00084     {
00085         return false;
00086     }
00087 
00088     fGrammarRegistry->put((void*) grammarKey, gramToCache);
00089 
00090     if (fXSModelIsValid && gramToCache->getGrammarType() == Grammar::SchemaGrammarType)
00091     {
00092         fXSModelIsValid = false;
00093     }
00094     return true;
00095 }
00096 
00097 Grammar* XMLGrammarPoolImpl::retrieveGrammar(XMLGrammarDescription* const gramDesc)
00098 {
00099     if (!gramDesc)
00100         return 0;
00101 
00102     /***
00103      * This implementation simply use GrammarKey
00104      */
00105     return fGrammarRegistry->get(gramDesc->getGrammarKey());
00106 }
00107 
00108 Grammar* XMLGrammarPoolImpl::orphanGrammar(const XMLCh* const nameSpaceKey)
00109 {
00110     if (!fLocked)
00111     {
00112         Grammar* grammar = fGrammarRegistry->orphanKey(nameSpaceKey);
00113         if (fXSModelIsValid && grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType)
00114         {
00115             fXSModelIsValid = false;
00116         }
00117         return grammar;
00118     }
00119     return 0;
00120 }
00121 
00122 RefHashTableOfEnumerator<Grammar>
00123 XMLGrammarPoolImpl::getGrammarEnumerator() const
00124 {
00125     return RefHashTableOfEnumerator<Grammar>(fGrammarRegistry, false, fGrammarRegistry->getMemoryManager());
00126 }
00127 
00128 
00129 bool XMLGrammarPoolImpl::clear()
00130 {
00131     if (!fLocked)
00132     {
00133         fGrammarRegistry->removeAll();
00134 
00135         fXSModelIsValid = false;
00136         if (fXSModel)
00137         {
00138             delete fXSModel;
00139             fXSModel = 0;
00140         }
00141         return true;
00142     }
00143     return false;
00144 }
00145 
00146 void XMLGrammarPoolImpl::lockPool()
00147 {
00148     if (!fLocked)
00149     {
00150         fLocked = true;
00151         MemoryManager *memMgr = getMemoryManager();
00152         if(!fSynchronizedStringPool)
00153         {
00154             fSynchronizedStringPool = new (memMgr) XMLSynchronizedStringPool(fStringPool, 109, memMgr);
00155         }
00156         if (!fXSModelIsValid)
00157         {
00158             createXSModel();
00159         }
00160     }
00161 }
00162 
00163 void XMLGrammarPoolImpl::unlockPool()
00164 {
00165     if (fLocked)
00166     {
00167         fLocked = false;
00168         if(fSynchronizedStringPool)
00169         {
00170             fSynchronizedStringPool->flushAll();
00171             // if user calls Lock again, need to have null fSynchronizedStringPool
00172             delete fSynchronizedStringPool;
00173             fSynchronizedStringPool = 0;
00174         }
00175         fXSModelIsValid = false;
00176         if (fXSModel)
00177         {
00178             delete fXSModel;
00179             fXSModel = 0;
00180         }
00181     }
00182 }
00183 
00184 // -----------------------------------------------------------------------
00185 // Implementation of Factory Interface
00186 // -----------------------------------------------------------------------
00187 DTDGrammar*  XMLGrammarPoolImpl::createDTDGrammar()
00188 {
00189         return new (getMemoryManager()) DTDGrammar(getMemoryManager());
00190 }
00191 
00192 SchemaGrammar* XMLGrammarPoolImpl::createSchemaGrammar()
00193 {
00194         return new (getMemoryManager()) SchemaGrammar(getMemoryManager());
00195 }
00196 
00197 XMLDTDDescription*  XMLGrammarPoolImpl::createDTDDescription(const XMLCh* const systemId)
00198 {
00199         return new (getMemoryManager()) XMLDTDDescriptionImpl(systemId, getMemoryManager());
00200 }
00201 
00202 XMLSchemaDescription* XMLGrammarPoolImpl::createSchemaDescription(const XMLCh* const targetNamespace)
00203 {
00204         return new (getMemoryManager()) XMLSchemaDescriptionImpl(targetNamespace, getMemoryManager());
00205 }
00206 
00207 XSModel *XMLGrammarPoolImpl::getXSModel(bool& XSModelWasChanged)
00208 {
00209     XSModelWasChanged = false;
00210     if (fLocked || fXSModelIsValid)
00211         return fXSModel;
00212 
00213     createXSModel();
00214     XSModelWasChanged = true;
00215     return fXSModel;
00216 }
00217 
00218 XMLStringPool *XMLGrammarPoolImpl::getURIStringPool()
00219 {
00220     if(fLocked)
00221         return fSynchronizedStringPool;
00222     return fStringPool;
00223 }
00224 
00225 // -----------------------------------------------------------------------
00226 // serialization and deserialization support
00227 // -----------------------------------------------------------------------
00228 /***
00229  *
00230  * don't serialize
00231  *
00232  *   XMLSynchronizedStringPool*  fSynchronizedStringPool;
00233  */
00234 
00235 /***
00236  *   .non-empty gramamrRegistry
00237  ***/
00238 void XMLGrammarPoolImpl::serializeGrammars(BinOutputStream* const binOut)
00239 {
00240     RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarRegistry, false, getMemoryManager());
00241     if (!(grammarEnum.hasMoreElements()))
00242     {
00243         ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_GrammarPool_Empty, getMemoryManager());
00244     }
00245 
00246     XSerializeEngine  serEng(binOut, this);
00247 
00248     //version information
00249     serEng<<(unsigned int)XERCES_GRAMMAR_SERIALIZATION_LEVEL;
00250 
00251     //lock status
00252     serEng<<fLocked;
00253 
00254     //StringPool, don't use <<
00255     fStringPool->serialize(serEng);
00256 
00257     /***
00258      * Serialize RefHashTableOf<Grammar>*    fGrammarRegistry;
00259      ***/
00260     XTemplateSerializer::storeObject(fGrammarRegistry, serEng);
00261 }
00262 
00263 /***
00264  *   .empty stringPool
00265  *   .empty gramamrRegistry
00266  ***/
00267 void XMLGrammarPoolImpl::deserializeGrammars(BinInputStream* const binIn)
00268 {
00269     MemoryManager *memMgr = getMemoryManager();
00270     unsigned int stringCount = fStringPool->getStringCount();
00271     if (stringCount)
00272     {
00273         /***
00274          * it contains only the four predefined one, that is ok
00275          * but we need to reset the string before deserialize it
00276          *
00277          ***/
00278         if ( stringCount <= 4 )
00279         {
00280             fStringPool->flushAll();
00281         }
00282         else
00283         {
00284             ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_StringPool_NotEmpty, memMgr);
00285         }
00286     }
00287 
00288     RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarRegistry, false, memMgr);
00289     if (grammarEnum.hasMoreElements())
00290     {
00291         ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_GrammarPool_NotEmpty, memMgr);
00292     }
00293 
00294     // This object will take care of cleaning up if an exception is
00295     // thrown during deserialization.
00296     JanitorMemFunCall<XMLGrammarPoolImpl>   cleanup(this, &XMLGrammarPoolImpl::cleanUp);
00297 
00298     try
00299     {
00300         XSerializeEngine  serEng(binIn, this);
00301 
00302         //version information
00303         unsigned int  StorerLevel;
00304         serEng>>StorerLevel;
00305         serEng.fStorerLevel = StorerLevel;
00306 
00307         // The storer level must match the loader level.
00308         //
00309         if (StorerLevel != (unsigned int)XERCES_GRAMMAR_SERIALIZATION_LEVEL)
00310         {
00311             XMLCh     StorerLevelChar[5];
00312             XMLCh     LoaderLevelChar[5];
00313             XMLString::binToText(StorerLevel,                          StorerLevelChar,   4, 10, memMgr);
00314             XMLString::binToText(XERCES_GRAMMAR_SERIALIZATION_LEVEL,   LoaderLevelChar,   4, 10, memMgr);
00315 
00316             ThrowXMLwithMemMgr2(XSerializationException
00317                     , XMLExcepts::XSer_Storer_Loader_Mismatch
00318                     , StorerLevelChar
00319                     , LoaderLevelChar
00320                     , memMgr);
00321         }
00322 
00323         //lock status
00324         serEng>>fLocked;
00325 
00326         //StringPool, don't use >>
00327         fStringPool->serialize(serEng);
00328 
00329         /***
00330          * Deserialize RefHashTableOf<Grammar>*    fGrammarRegistry;
00331          ***/
00332         XTemplateSerializer::loadObject(&fGrammarRegistry, 29, true, serEng);
00333 
00334     }
00335     catch(const OutOfMemoryException&)
00336     {
00337         // This is a special case, because we don't want
00338         // to execute cleanup code on out-of-memory
00339         // conditions.
00340         cleanup.release();
00341 
00342         throw;
00343     }
00344 
00345     // Everything is OK, so we can release the cleanup object.
00346     cleanup.release();
00347 
00348     if (fLocked)
00349     {
00350         createXSModel();
00351     }
00352 }
00353 
00354 
00355 void
00356 XMLGrammarPoolImpl::cleanUp()
00357 {
00358     fLocked = false;
00359 
00360     clear();
00361 }
00362 
00363 
00364 XERCES_CPP_NAMESPACE_END