office-gobmx/configmgr/source/backend/binaryreadhandler.cxx
Oliver Bolte 6911686bad INTEGRATION: CWS pchfix02 (1.7.18); FILE MERGED
2006/09/01 17:20:28 kaib 1.7.18.1: #i68856# Added header markers and pch files
2006-09-16 14:03:08 +00:00

709 lines
28 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: binaryreadhandler.cxx,v $
*
* $Revision: 1.8 $
*
* last change: $Author: obo $ $Date: 2006-09-16 15:03:08 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_configmgr.hxx"
#include "binaryreadhandler.hxx"
#include "binarycache.hxx"
#include "binarytype.hxx"
#ifndef CONFIGMGR_SIMPLETYPEHELPER_HXX
#include "simpletypehelper.hxx"
#endif
#ifndef CONFIGMGR_TYPECONVERTER_HXX
#include "typeconverter.hxx"
#endif
#ifndef CONFIGMGR_TREE_NODEFACTORY_HXX
#include "treenodefactory.hxx"
#endif
#include "tracer.hxx"
#ifndef _COM_SUN_STAR_IO_WRONGFORMATEXCEPTION_HPP_
#include <com/sun/star/io/WrongFormatException.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XTIMESTAMPED_HPP_
#include <com/sun/star/util/XTimeStamped.hpp>
#endif
#define ASCII(x) rtl::OUString::createFromAscii(x)
namespace configmgr
{
using namespace binary;
// -----------------------------------------------------------------------------
namespace backend
{
namespace css = com::sun::star;
namespace io = css::io;
namespace util = css::util;
// -----------------------------------------------------------------------------
BinaryReadHandler::BinaryReadHandler(rtl::OUString const & _aFileURL,
rtl::OUString const & _aComponentName,
MultiServiceFactory const & )
: m_BinaryReader(_aFileURL)
, m_aNodeFactory()
, m_aComponentName(_aComponentName)
{
}
// -----------------------------------------------------------------------------
BinaryReadHandler::~BinaryReadHandler()
{
}
// -----------------------------------------------------------------------------
static inline
bool isRequestingNoLocale(localehelper::Locale const & aRequestedLocale)
{
OUString const & aLanguage = aRequestedLocale.Language;
return aLanguage.getLength() == 0 || localehelper::isDefaultLanguage(aLanguage);
}
// -----------------------------------------------------------------------------
static
bool supportsLocale(uno::Sequence< OUString > const & aStoredLocales, OUString const & aRequestedLocale)
{
for (sal_Int32 ix=0; ix<aStoredLocales.getLength(); ++ix)
if (aStoredLocales[ix].equalsIgnoreAsciiCase(aRequestedLocale))
return true;
return false;
}
// -----------------------------------------------------------------------------
static
bool supportsAll(uno::Sequence< OUString > const & aStoredLocales, uno::Sequence< OUString > const & aRequestedLocales)
{
for (sal_Int32 jx=0; jx<aRequestedLocales.getLength(); ++jx)
if (!supportsLocale(aStoredLocales,aRequestedLocales[jx]))
return false;
return true;
}
// -----------------------------------------------------------------------------
bool BinaryReadHandler::verifyFileHeader( const uno::Reference<backenduno::XLayer> * pLayers,
sal_Int32 nNumLayers,
const OUString& _aSchemaVersion,
localehelper::Locale const & aRequestedLocale,
localehelper::LocaleSequence & outKnownLocales)
{
try
{
//Open the reader
sal_Int16 nMagic, nVersion;
m_BinaryReader.read(nMagic);
m_BinaryReader.read(nVersion);
if (nMagic !=CFG_BINARY_MAGIC || nVersion != CFG_BINARY_VERSION )
return false;
rtl::OUString aSchemaVersion;
m_BinaryReader.read(aSchemaVersion);
if (!aSchemaVersion.equals(_aSchemaVersion))
return false;
uno::Sequence< rtl::OUString > aAvailableLocales;
uno::Sequence< rtl::OUString > aKnownLocales;
m_BinaryReader.read(aKnownLocales);
m_BinaryReader.read(aAvailableLocales);
outKnownLocales = localehelper::makeLocaleSequence(aKnownLocales);
if (isRequestingNoLocale(aRequestedLocale))
{
// any existing combination of locales (including none) is valid
}
else if (!localehelper::designatesAllLocales(aRequestedLocale))
{
// one particular locale requested
OUString const aIsoLocale = localehelper::makeIsoLocale(aRequestedLocale);
if (!supportsLocale(aKnownLocales,aIsoLocale))
{
// a locale we didn't load previously
return false;
}
else if (! supportsLocale(aAvailableLocales,aIsoLocale))
{
// a locale we handled by fallback previously
uno::Sequence< rtl::OUString > aNewlyAvailableLocales =
getAvailableLocales(pLayers,nNumLayers);
// ... and that has become available now
if (supportsLocale(aNewlyAvailableLocales,aIsoLocale))
return false;
// ... or other new locales have been added
if (!supportsAll(aAvailableLocales,aNewlyAvailableLocales))
return false;
}
}
else
{
uno::Sequence< rtl::OUString > aNewlyAvailableLocales =
getAvailableLocales(pLayers,nNumLayers);
// not all locales were requested yet
if (!supportsAll(aKnownLocales,aNewlyAvailableLocales))
return false;
// new locales have been added
if (!supportsAll(aAvailableLocales,aNewlyAvailableLocales))
return false;
}
rtl::OUString aComponentName;
m_BinaryReader.read(aComponentName);
if (!aComponentName.equals(m_aComponentName))
return false;
return true;
}
catch (uno::Exception &)
{
CFG_TRACE_INFO("Binary Cache can't be used");
return false;
}
}
// -----------------------------------------------------------------------------
bool BinaryReadHandler::isUptodate(const std::vector<rtl::OUString> & _timeStamps)
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
sal_Int32 nNumBinaryLayers;
m_BinaryReader.read(nNumBinaryLayers);
if (nNumBinaryLayers < 0 || sal_uInt32(nNumBinaryLayers) != _timeStamps.size())
return false;
for ( std::vector<rtl::OUString>::const_iterator it = _timeStamps.begin();
it != _timeStamps.end();
++it)
{
rtl::OUString binaryTimeStamp;
m_BinaryReader.read(binaryTimeStamp);
if ( ! it->equals(binaryTimeStamp) )
{
return false;
}
}
return true;
}
// -----------------------------------------------------------------------------
NodeType::Type BinaryReadHandler::readNodeType()
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
NodeType::Type eType = NodeType::invalid;
sal_Int8 nValue;
m_BinaryReader.read(nValue);
sal_uInt8 const nRightValue( nValue );
if ( (nRightValue & NodeType::nodetype_mask) == nRightValue )
eType = NodeType::Type(nRightValue);
if (eType == NodeType::invalid)
{
OSL_ENSURE(false, "unknown or unhandled node type");
throw io::WrongFormatException();
}
return eType;
}
// -----------------------------------------------------------------------------
ValueFlags::Type BinaryReadHandler::readValueFlags(bool& bSeq, bool& bHasValue, bool& bHasDefault )
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
sal_Int8 nValue;
m_BinaryReader.read(nValue);
sal_uInt8 const nRightValue( nValue );
ValueFlags::Type eType = ValueFlags::Type(nRightValue & ValueFlags::basictype_mask);
if ( eType >= ValueFlags::val_invalid)
{
OSL_ENSURE(false, "unknown or unhandled value type");
throw io::WrongFormatException();
}
if (nRightValue & ValueFlags::seq)
bSeq = true;
else
bSeq = false;
if (nRightValue & ValueFlags::first_value_NULL)
bHasValue = false;
else
bHasValue = true;
if (nRightValue & ValueFlags::second_value_NULL)
bHasDefault = false;
else
bHasDefault = true;
return eType;
}
// -----------------------------------------------------------------------------
void BinaryReadHandler::readString(rtl::OUString &_aString)
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
m_BinaryReader.read (_aString);
}
// -----------------------------------------------------------------------------
void BinaryReadHandler::readAttributes(node::Attributes &_aAttributes)
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
sal_Int8 nValue;
m_BinaryReader.read(nValue);
_aAttributes.setState( node::State(nValue & 0x03) );
_aAttributes.setAccess( nValue & 0x04 ? true : false, nValue & 0x08 ? true : false);
_aAttributes.setNullable(nValue & 0x10 ? true : false);
_aAttributes.setLocalized(nValue & 0x20 ? true : false);
if(nValue & 0x40 )
{
_aAttributes.markMandatory();
}
if(nValue & 0x80)
{
_aAttributes.markRemovable();
}
}
// -----------------------------------------------------------------------------
void BinaryReadHandler::readGroup(rtl::OUString &_aName, node::Attributes &_aAttributes)
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
readAttributes(_aAttributes);
readString(_aName);
}
// -----------------------------------------------------------------------------
void BinaryReadHandler::readSet(rtl::OUString &_aName, node::Attributes &_aAttributes,
rtl::OUString &_sInstanceName, rtl::OUString &_sInstanceModule)
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
readAttributes(_aAttributes);
readString(_aName);
readString(_sInstanceName);
readString(_sInstanceModule);
}
// -----------------------------------------------------------------------------
template <class T>
inline
void readAsAny(BinaryReader& rBinaryReader, uno::Any & _aValue, uno::Type& _aType, T& _aVar)
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
rBinaryReader.read(_aVar);
_aValue <<= _aVar;
_aType = _aValue.getValueType();
}
// -----------------------------------------------------------------------------
uno::Type convertValueTypeToType(ValueFlags::Type eBasicValueType, bool bSeq)
{
uno::Type aType;
if (!bSeq)
{
switch(eBasicValueType)
{
// --------------- Simple types ---------------
case ValueFlags::val_boolean:
aType = SimpleTypeHelper::getBooleanType();
break;
case ValueFlags::val_int16:
aType = SimpleTypeHelper::getShortType();
break;
case ValueFlags::val_int32:
aType = SimpleTypeHelper::getIntType();
break;
case ValueFlags::val_int64:
aType = SimpleTypeHelper::getLongType();
break;
case ValueFlags::val_double:
aType = SimpleTypeHelper::getDoubleType();
break;
case ValueFlags::val_string:
aType = SimpleTypeHelper::getStringType();
break;
case ValueFlags::val_binary:
aType = SimpleTypeHelper::getBinaryType();
break;
case ValueFlags::val_any:
aType = SimpleTypeHelper::getAnyType();
break;
default:
OSL_ENSURE(false,"Invalid value type");
break;
}
}
else
{
// ------------ Sequences ------------
switch(eBasicValueType)
{
case ValueFlags::val_boolean:
aType = ::getCppuType(static_cast<uno::Sequence<sal_Bool> const*>(0));
break;
case ValueFlags::val_int16:
aType = ::getCppuType(static_cast<uno::Sequence<sal_Int16> const*>(0));
break;
case ValueFlags::val_int32:
aType = ::getCppuType(static_cast<uno::Sequence<sal_Int32> const*>(0));
break;
case ValueFlags::val_int64:
aType = ::getCppuType(static_cast<uno::Sequence<sal_Int64> const*>(0));
break;
case ValueFlags::val_double:
aType = ::getCppuType(static_cast<uno::Sequence<double> const*>(0));
break;
case ValueFlags::val_string:
aType = ::getCppuType(static_cast<uno::Sequence<rtl::OUString> const*>(0));
break;
case ValueFlags::val_binary:
aType = ::getCppuType(static_cast<uno::Sequence<BinaryReader::Binary> const*>(0));
break;
default:
OSL_ENSURE(false,"Invalid sequence value type");
break;
}
}
return aType;
}
// -----------------------------------------------------------------------------
void BinaryReadHandler::readValue(rtl::OUString &_aName, node::Attributes &_aAttributes,
uno::Any& _aValue, uno::Any& _aDefaultValue,uno::Type& _aType)
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
bool bSeq = false;
bool bHasValue = false;
bool bHasDefault = false;
ValueFlags::Type eBasicType = readValueFlags(bSeq, bHasValue, bHasDefault);
readAttributes(_aAttributes);
readString(_aName);
if (!bSeq && (bHasValue || bHasDefault))
{
switch(eBasicType)
{
case ValueFlags::val_any:
{
OSL_ENSURE(false,"Node of type Any cannot have value");
throw io::WrongFormatException();
}
case ValueFlags::val_string:
{
rtl::OUString aStr;
if (bHasValue)
readAsAny(m_BinaryReader, _aValue, _aType, aStr);
if (bHasDefault)
readAsAny(m_BinaryReader, _aDefaultValue, _aType, aStr);
break;
}
case ValueFlags::val_boolean:
{
sal_Bool nValue;
if (bHasValue)
readAsAny(m_BinaryReader,_aValue, _aType, nValue);
if (bHasDefault)
readAsAny(m_BinaryReader,_aDefaultValue, _aType, nValue);
break;
}
case ValueFlags::val_int16:
{
sal_Int16 nValue;
if (bHasValue)
readAsAny(m_BinaryReader,_aValue, _aType, nValue);
if (bHasDefault)
readAsAny(m_BinaryReader,_aDefaultValue, _aType, nValue);
break;
}
case ValueFlags::val_int32:
{
sal_Int32 nValue;
if (bHasValue)
readAsAny(m_BinaryReader,_aValue, _aType, nValue);
if (bHasDefault)
readAsAny(m_BinaryReader,_aDefaultValue, _aType, nValue);
break;
}
case ValueFlags::val_int64:
{
sal_Int64 nValue;
if (bHasValue)
readAsAny(m_BinaryReader,_aValue, _aType, nValue);
if (bHasDefault)
readAsAny(m_BinaryReader,_aDefaultValue, _aType, nValue);
break;
}
case ValueFlags::val_double:
{
double nValue;
if (bHasValue)
readAsAny(m_BinaryReader,_aValue, _aType, nValue);
if (bHasDefault)
readAsAny(m_BinaryReader, _aDefaultValue, _aType, nValue);
break;
}
case ValueFlags::val_binary:
{
BinaryReader::Binary aValue;
if (bHasValue)
readAsAny(m_BinaryReader,_aValue, _aType, aValue);
if (bHasDefault)
readAsAny(m_BinaryReader,_aDefaultValue, _aType, aValue);
break;
}
default:
OSL_ENSURE(false, "Invalid value type");
throw io::WrongFormatException();
}
}
else
{
_aType = convertValueTypeToType(eBasicType, bSeq);
if (_aType == uno::Type())
throw io::WrongFormatException();
}
if(bSeq)
{
OSL_ASSERT(_aType.getTypeClass() == uno::TypeClass_SEQUENCE);
uno::Type const aElementType = getSequenceElementType(_aType);
if (bHasValue)
readSequenceValue(m_BinaryReader, _aValue, aElementType );
if(bHasDefault)
readSequenceValue(m_BinaryReader, _aDefaultValue, aElementType );
}
}
// -----------------------------------------------------------------------------
std::auto_ptr<ISubtree> BinaryReadHandler::readComponentTree()
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
NodeType::Type eType = this->readNodeType();
if (eType != NodeType::component)
{
// TODO: search for component tree
OSL_ENSURE(false, "binary Cache: unexpected tree type for component data");
throw io::WrongFormatException();
}
return readToplevelTree();
}
// -----------------------------------------------------------------------------
std::auto_ptr<ISubtree> BinaryReadHandler::readTemplatesTree()
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
NodeType::Type eType = this->readNodeType();
if (eType != NodeType::templates)
{
// TODO: search for templates tree
OSL_ENSURE(false, "binary Cache: unexpected tree type for template data");
throw io::WrongFormatException();
}
return readToplevelTree();
}
// -----------------------------------------------------------------------------
std::auto_ptr<ISubtree> BinaryReadHandler::readToplevelTree()
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
std::auto_ptr<ISubtree> pTree;
rtl::OUString aName;
node::Attributes aAttributes;
const bool not_extensible = false;
NodeType::Type eType = this->readNodeType();
switch (eType)
{
case NodeType::groupnode:
{
this->readGroup(aName, aAttributes);
pTree = m_aNodeFactory.createGroup(aName,not_extensible,aAttributes);
break;
}
case NodeType::setnode:
{
backenduno::TemplateIdentifier aTemplate;
this->readSet(aName, aAttributes,aTemplate.Name, aTemplate.Component);
pTree = m_aNodeFactory.createSet(aName,aTemplate,not_extensible,aAttributes);
break;
}
case NodeType::nodata:
break;
default:
OSL_ENSURE(false, "binary Cache - cannot read data: unexpected node type for tree");
throw io::WrongFormatException();
}
if (pTree.get() != NULL)
{
readChildren(*pTree);
//read terminating stop node
eType = this->readNodeType();
OSL_ENSURE(NodeType::stop == eType, "Missing stop node to mark end of tree");
}
return pTree;
}
// -----------------------------------------------------------------------------
bool BinaryReadHandler::validateHeader( const uno::Reference<backenduno::XLayer> * pLayers,
sal_Int32 nNumLayers,
const OUString& _aSchemaVersion,
localehelper::Locale const & aRequestedLocale,
localehelper::LocaleSequence & outKnownLocales)
SAL_THROW( (io::IOException, uno::RuntimeException) )
{
//Check here if the file exists
if (!m_BinaryReader.open())
return false;
if(!this->verifyFileHeader(pLayers, nNumLayers, _aSchemaVersion, aRequestedLocale, outKnownLocales))
return false;
//Check if layers are uptodate
std::vector <OUString> timeStamps(nNumLayers);
for (sal_Int32 i = 0 ; i < nNumLayers ; ++ i)
{
uno::Reference<util::XTimeStamped> xTimeStamp = uno::Reference<util::XTimeStamped>(pLayers[i], uno::UNO_QUERY);
if (xTimeStamp.is())
{
OUString aTimeStamp = xTimeStamp->getTimestamp();
timeStamps[i] = aTimeStamp;
}
}
return this->isUptodate(timeStamps);
}
// -----------------------------------------------------------------------------
void BinaryReadHandler::readChildren(ISubtree & rTree )
{
OSL_ASSERT(!NodeType::stop); // loop stops at stop node
while (NodeType::Type eType = this->readNodeType())
{
rtl::OUString aName;
node::Attributes aAttributes;
const bool not_extensible = false;
switch (eType)
{
case NodeType::groupnode:
{
this->readGroup(aName, aAttributes);
std::auto_ptr<ISubtree> pNewNode = m_aNodeFactory.createGroup(aName, not_extensible, aAttributes);
if (pNewNode.get() == NULL)
{
OSL_ENSURE(false, "Error: factory returned NULL group node - skipping");
continue;
}
readChildren( *pNewNode );
rTree.addChild(base_ptr(pNewNode));
break;
}
case NodeType::setnode:
{
backenduno::TemplateIdentifier aTemplate;
this->readSet(aName, aAttributes,aTemplate.Name, aTemplate.Component);
std::auto_ptr<ISubtree> pNewSetNode = m_aNodeFactory.createSet(aName,aTemplate,not_extensible,aAttributes);
if (pNewSetNode.get() == NULL)
{
OSL_ENSURE(false, "Error: factory returned NULL set node - skipping");
continue;
}
readChildren( *pNewSetNode );
rTree.addChild(base_ptr(pNewSetNode));
break;
}
case NodeType::valuenode:
{
uno::Any aValue;
uno::Any aDefaultValue;
uno::Type aType;
this->readValue(aName, aAttributes, aValue, aDefaultValue, aType);
OTreeNodeFactory & rValueFactory = m_aNodeFactory.getNodeFactory();
std::auto_ptr<ValueNode> pValueNode;
if (aValue.hasValue() || aDefaultValue.hasValue())
{
pValueNode = rValueFactory.createValueNode(aName,aValue, aDefaultValue, aAttributes);
}
else
{
pValueNode = rValueFactory.createNullValueNode(aName,aType, aAttributes);
}
rTree.addChild(base_ptr(pValueNode));
break;
}
default:
OSL_ENSURE(false, "Binary cache: Invalid node type");
throw io::WrongFormatException();
}
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
}
// -----------------------------------------------------------------------------
}