| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* |
| * $Id$ |
| */ |
| |
| |
| // --------------------------------------------------------------------------- |
| // Includes |
| // --------------------------------------------------------------------------- |
| #include <xercesc/framework/XMLGrammarPoolImpl.hpp> |
| #include <xercesc/internal/XSerializeEngine.hpp> |
| #include <xercesc/internal/XTemplateSerializer.hpp> |
| #include <xercesc/validators/DTD/DTDGrammar.hpp> |
| #include <xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp> |
| #include <xercesc/validators/schema/SchemaGrammar.hpp> |
| #include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp> |
| #include <xercesc/util/OutOfMemoryException.hpp> |
| #include <xercesc/util/SynchronizedStringPool.hpp> |
| |
| XERCES_CPP_NAMESPACE_BEGIN |
| |
| // private function used to update fXSModel |
| void XMLGrammarPoolImpl::createXSModel() |
| { |
| delete fXSModel; |
| fXSModel = 0; |
| fXSModel = new (getMemoryManager()) XSModel(this, getMemoryManager()); |
| fXSModelIsValid = true; |
| } |
| |
| // --------------------------------------------------------------------------- |
| // XMLGrammarPoolImpl: constructor and destructor |
| // --------------------------------------------------------------------------- |
| XMLGrammarPoolImpl::~XMLGrammarPoolImpl() |
| { |
| delete fGrammarRegistry; |
| delete fStringPool; |
| if(fSynchronizedStringPool) |
| delete fSynchronizedStringPool; |
| if(fXSModel) |
| delete fXSModel; |
| } |
| |
| XMLGrammarPoolImpl::XMLGrammarPoolImpl(MemoryManager* const memMgr) |
| :XMLGrammarPool(memMgr) |
| ,fGrammarRegistry(0) |
| ,fStringPool(0) |
| ,fSynchronizedStringPool(0) |
| ,fXSModel(0) |
| ,fLocked(false) |
| ,fXSModelIsValid(false) |
| { |
| fGrammarRegistry = new (memMgr) RefHashTableOf<Grammar>(29, true, memMgr); |
| fStringPool = new (memMgr) XMLStringPool(109, memMgr); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Implementation of Grammar Pool Interface |
| // ----------------------------------------------------------------------- |
| bool XMLGrammarPoolImpl::cacheGrammar(Grammar* const gramToCache ) |
| { |
| if(fLocked || !gramToCache) |
| return false; |
| |
| const XMLCh* grammarKey = gramToCache->getGrammarDescription()->getGrammarKey(); |
| |
| if (fGrammarRegistry->containsKey(grammarKey)) |
| { |
| return false; |
| } |
| |
| fGrammarRegistry->put((void*) grammarKey, gramToCache); |
| |
| if (fXSModelIsValid && gramToCache->getGrammarType() == Grammar::SchemaGrammarType) |
| { |
| fXSModelIsValid = false; |
| } |
| return true; |
| } |
| |
| Grammar* XMLGrammarPoolImpl::retrieveGrammar(XMLGrammarDescription* const gramDesc) |
| { |
| if (!gramDesc) |
| return 0; |
| |
| /*** |
| * This implementation simply use GrammarKey |
| */ |
| return fGrammarRegistry->get(gramDesc->getGrammarKey()); |
| } |
| |
| Grammar* XMLGrammarPoolImpl::orphanGrammar(const XMLCh* const nameSpaceKey) |
| { |
| if (!fLocked) |
| { |
| Grammar* grammar = fGrammarRegistry->orphanKey(nameSpaceKey); |
| if (fXSModelIsValid && grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType) |
| { |
| fXSModelIsValid = false; |
| } |
| return grammar; |
| } |
| return 0; |
| } |
| |
| RefHashTableOfEnumerator<Grammar> |
| XMLGrammarPoolImpl::getGrammarEnumerator() const |
| { |
| return RefHashTableOfEnumerator<Grammar>(fGrammarRegistry, false, fGrammarRegistry->getMemoryManager()); |
| } |
| |
| |
| bool XMLGrammarPoolImpl::clear() |
| { |
| if (!fLocked) |
| { |
| fGrammarRegistry->removeAll(); |
| |
| fXSModelIsValid = false; |
| if (fXSModel) |
| { |
| delete fXSModel; |
| fXSModel = 0; |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| void XMLGrammarPoolImpl::lockPool() |
| { |
| if (!fLocked) |
| { |
| fLocked = true; |
| MemoryManager *memMgr = getMemoryManager(); |
| if(!fSynchronizedStringPool) |
| { |
| fSynchronizedStringPool = new (memMgr) XMLSynchronizedStringPool(fStringPool, 109, memMgr); |
| } |
| if (!fXSModelIsValid) |
| { |
| createXSModel(); |
| } |
| } |
| } |
| |
| void XMLGrammarPoolImpl::unlockPool() |
| { |
| if (fLocked) |
| { |
| fLocked = false; |
| if(fSynchronizedStringPool) |
| { |
| fSynchronizedStringPool->flushAll(); |
| // if user calls Lock again, need to have null fSynchronizedStringPool |
| delete fSynchronizedStringPool; |
| fSynchronizedStringPool = 0; |
| } |
| fXSModelIsValid = false; |
| if (fXSModel) |
| { |
| delete fXSModel; |
| fXSModel = 0; |
| } |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| // Implementation of Factory Interface |
| // ----------------------------------------------------------------------- |
| DTDGrammar* XMLGrammarPoolImpl::createDTDGrammar() |
| { |
| return new (getMemoryManager()) DTDGrammar(getMemoryManager()); |
| } |
| |
| SchemaGrammar* XMLGrammarPoolImpl::createSchemaGrammar() |
| { |
| return new (getMemoryManager()) SchemaGrammar(getMemoryManager()); |
| } |
| |
| XMLDTDDescription* XMLGrammarPoolImpl::createDTDDescription(const XMLCh* const systemId) |
| { |
| return new (getMemoryManager()) XMLDTDDescriptionImpl(systemId, getMemoryManager()); |
| } |
| |
| XMLSchemaDescription* XMLGrammarPoolImpl::createSchemaDescription(const XMLCh* const targetNamespace) |
| { |
| return new (getMemoryManager()) XMLSchemaDescriptionImpl(targetNamespace, getMemoryManager()); |
| } |
| |
| XSModel *XMLGrammarPoolImpl::getXSModel(bool& XSModelWasChanged) |
| { |
| XSModelWasChanged = false; |
| if (fLocked || fXSModelIsValid) |
| return fXSModel; |
| |
| createXSModel(); |
| XSModelWasChanged = true; |
| return fXSModel; |
| } |
| |
| XMLStringPool *XMLGrammarPoolImpl::getURIStringPool() |
| { |
| if(fLocked) |
| return fSynchronizedStringPool; |
| return fStringPool; |
| } |
| |
| // ----------------------------------------------------------------------- |
| // serialization and deserialization support |
| // ----------------------------------------------------------------------- |
| /*** |
| * |
| * don't serialize |
| * |
| * XMLSynchronizedStringPool* fSynchronizedStringPool; |
| */ |
| |
| /*** |
| * .non-empty gramamrRegistry |
| ***/ |
| void XMLGrammarPoolImpl::serializeGrammars(BinOutputStream* const binOut) |
| { |
| RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarRegistry, false, getMemoryManager()); |
| if (!(grammarEnum.hasMoreElements())) |
| { |
| ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_GrammarPool_Empty, getMemoryManager()); |
| } |
| |
| XSerializeEngine serEng(binOut, this); |
| |
| //version information |
| serEng<<(unsigned int)XERCES_GRAMMAR_SERIALIZATION_LEVEL; |
| |
| //lock status |
| serEng<<fLocked; |
| |
| //StringPool, don't use << |
| fStringPool->serialize(serEng); |
| |
| /*** |
| * Serialize RefHashTableOf<Grammar>* fGrammarRegistry; |
| ***/ |
| XTemplateSerializer::storeObject(fGrammarRegistry, serEng); |
| } |
| |
| /*** |
| * .empty stringPool |
| * .empty gramamrRegistry |
| ***/ |
| void XMLGrammarPoolImpl::deserializeGrammars(BinInputStream* const binIn) |
| { |
| MemoryManager *memMgr = getMemoryManager(); |
| unsigned int stringCount = fStringPool->getStringCount(); |
| if (stringCount) |
| { |
| /*** |
| * it contains only the four predefined one, that is ok |
| * but we need to reset the string before deserialize it |
| * |
| ***/ |
| if ( stringCount <= 4 ) |
| { |
| fStringPool->flushAll(); |
| } |
| else |
| { |
| ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_StringPool_NotEmpty, memMgr); |
| } |
| } |
| |
| RefHashTableOfEnumerator<Grammar> grammarEnum(fGrammarRegistry, false, memMgr); |
| if (grammarEnum.hasMoreElements()) |
| { |
| ThrowXMLwithMemMgr(XSerializationException, XMLExcepts::XSer_GrammarPool_NotEmpty, memMgr); |
| } |
| |
| // This object will take care of cleaning up if an exception is |
| // thrown during deserialization. |
| JanitorMemFunCall<XMLGrammarPoolImpl> cleanup(this, &XMLGrammarPoolImpl::cleanUp); |
| |
| try |
| { |
| XSerializeEngine serEng(binIn, this); |
| |
| //version information |
| unsigned int StorerLevel; |
| serEng>>StorerLevel; |
| serEng.fStorerLevel = StorerLevel; |
| |
| // The storer level must match the loader level. |
| // |
| if (StorerLevel != (unsigned int)XERCES_GRAMMAR_SERIALIZATION_LEVEL) |
| { |
| XMLCh StorerLevelChar[5]; |
| XMLCh LoaderLevelChar[5]; |
| XMLString::binToText(StorerLevel, StorerLevelChar, 4, 10, memMgr); |
| XMLString::binToText(XERCES_GRAMMAR_SERIALIZATION_LEVEL, LoaderLevelChar, 4, 10, memMgr); |
| |
| ThrowXMLwithMemMgr2(XSerializationException |
| , XMLExcepts::XSer_Storer_Loader_Mismatch |
| , StorerLevelChar |
| , LoaderLevelChar |
| , memMgr); |
| } |
| |
| //lock status |
| serEng>>fLocked; |
| |
| //StringPool, don't use >> |
| fStringPool->serialize(serEng); |
| |
| /*** |
| * Deserialize RefHashTableOf<Grammar>* fGrammarRegistry; |
| ***/ |
| XTemplateSerializer::loadObject(&fGrammarRegistry, 29, true, serEng); |
| |
| } |
| catch(const OutOfMemoryException&) |
| { |
| // This is a special case, because we don't want |
| // to execute cleanup code on out-of-memory |
| // conditions. |
| cleanup.release(); |
| |
| throw; |
| } |
| |
| // Everything is OK, so we can release the cleanup object. |
| cleanup.release(); |
| |
| if (fLocked) |
| { |
| createXSModel(); |
| } |
| } |
| |
| |
| void |
| XMLGrammarPoolImpl::cleanUp() |
| { |
| fLocked = false; |
| |
| clear(); |
| } |
| |
| |
| XERCES_CPP_NAMESPACE_END |