blob: 9683a5c226532f69bab71d1fa5af3571c1582d38 [file] [log] [blame]
/*
* 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: XMLGrammarPoolImpl.cpp 568078 2007-08-21 11:43:25Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/internal/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()
{
if (fLocked)
return fXSModel;
if (fXSModelIsValid)
return fXSModel;
createXSModel();
return fXSModel;
}
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 = (short)StorerLevel;
//if the storer level is after the loader level
//the loader shall not read the data any more
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_NewerThan_Loader
, 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