1755431c24
2006/10/24 06:41:08 pjanik 1.9.10.1: #i70649#: Prevent warnings on Mac OS X.
516 lines
20 KiB
C++
516 lines
20 KiB
C++
/*************************************************************************
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: binarywritehandler.cxx,v $
|
|
*
|
|
* $Revision: 1.10 $
|
|
*
|
|
* last change: $Author: vg $ $Date: 2006-11-21 17:23:32 $
|
|
*
|
|
* 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 "binarywritehandler.hxx"
|
|
#include "binarycache.hxx"
|
|
|
|
#ifndef _COM_SUN_STAR_UTIL_XTIMESTAMPED_HPP_
|
|
#include <com/sun/star/util/XTimeStamped.hpp>
|
|
#endif
|
|
|
|
#ifndef CONFIGMGR_TYPECONVERTER_HXX
|
|
#include "typeconverter.hxx"
|
|
#endif
|
|
#ifndef CONFIGMGR_SIMPLETYPEHELPER_HXX
|
|
#include "simpletypehelper.hxx"
|
|
#endif
|
|
|
|
#define ASCII(x) rtl::OUString::createFromAscii(x)
|
|
namespace configmgr
|
|
{
|
|
// -----------------------------------------------------------------------------
|
|
namespace backend
|
|
{
|
|
|
|
using ::rtl::OUString;
|
|
namespace css = com::sun::star;
|
|
namespace util = css::util ;
|
|
|
|
using namespace binary;
|
|
// -----------------------------------------------------------------------------
|
|
|
|
BinaryWriteHandler::BinaryWriteHandler( rtl::OUString const & _aFileURL,
|
|
rtl::OUString const & _aComponentName,
|
|
MultiServiceFactory const & _aFactory)
|
|
: m_BinaryWriter(_aFileURL,_aFactory)
|
|
, m_aComponentName(_aComponentName)
|
|
{
|
|
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
static
|
|
ValueFlags::Type convertTypeToValueType(uno::Type const& _aType)
|
|
{
|
|
ValueFlags::Type eType = ValueFlags::val_invalid;
|
|
uno::TypeClass const aClass = _aType.getTypeClass();
|
|
switch(aClass)
|
|
{
|
|
case uno::TypeClass_ANY:
|
|
eType = ValueFlags::val_any;
|
|
break;
|
|
case uno::TypeClass_BOOLEAN:
|
|
eType = ValueFlags::val_boolean;
|
|
break;
|
|
case uno::TypeClass_SHORT:
|
|
eType = ValueFlags::val_int16;
|
|
break;
|
|
case uno::TypeClass_LONG:
|
|
eType = ValueFlags::val_int32;
|
|
break;
|
|
case uno::TypeClass_HYPER:
|
|
eType = ValueFlags::val_int64;
|
|
break;
|
|
case uno::TypeClass_DOUBLE:
|
|
eType = ValueFlags::val_double;
|
|
break;
|
|
case uno::TypeClass_STRING:
|
|
eType = ValueFlags::val_string;
|
|
break;
|
|
case uno::TypeClass_SEQUENCE:
|
|
if (_aType == SimpleTypeHelper::getBinaryType())
|
|
{
|
|
eType = ValueFlags::val_binary;
|
|
}
|
|
else
|
|
{
|
|
uno::Type aType = configmgr::getSequenceElementType(_aType);
|
|
eType = convertTypeToValueType(aType);
|
|
|
|
OSL_ENSURE(!(eType & ValueFlags::seq), "Binary Writer - Invalid value type: Multiple nesting of sequences");
|
|
eType = ValueFlags::Type( eType | ValueFlags::seq );
|
|
}
|
|
break;
|
|
default:
|
|
OSL_ENSURE(false, "Binary Writer - Invalid value type: not supported");
|
|
break;
|
|
}
|
|
return eType;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
template <class T>
|
|
inline /* make performance crew happy ;-) */
|
|
void writeDirectly(BinaryWriter& _rWriter, T const& _aVal)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
_rWriter.write(_aVal);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
static
|
|
inline
|
|
void writeDirectly(BinaryWriter& _rWriter, uno::Sequence<sal_Int8> const& _aBinary);
|
|
// -----------------------------------------------------------------------------
|
|
template <class T>
|
|
inline /* make performance crew happy ;-) */
|
|
void writeFromAny(BinaryWriter& _rWriter,uno::Any const& _aValue, T& _aVar)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
OSL_VERIFY(_aValue >>= _aVar ); // "Invalid Any for value"
|
|
writeDirectly(_rWriter,_aVar);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
template <class Element>
|
|
void writeSequence(BinaryWriter& _rWriter, uno::Sequence< Element > const& aSequence)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
sal_Int32 const nLength = aSequence.getLength();
|
|
_rWriter.write(nLength);
|
|
|
|
for(sal_Int32 i=0; i<nLength; ++i)
|
|
{
|
|
writeDirectly(_rWriter, aSequence[i]);
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
static
|
|
inline
|
|
void writeDirectly(BinaryWriter& _rWriter, uno::Sequence<sal_Int8> const& _aBinary)
|
|
{
|
|
writeSequence(_rWriter,_aBinary);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
#define CASE_WRITE_SEQUENCE(TYPE_CLASS, DATA_TYPE) \
|
|
case TYPE_CLASS: \
|
|
{ \
|
|
uno::Sequence< DATA_TYPE > aData; \
|
|
OSL_ASSERT( ::getCppuType(aData.getConstArray()).getTypeClass() == (TYPE_CLASS) ); \
|
|
OSL_VERIFY( _aValue >>= aData ); \
|
|
writeSequence(_rWriter,aData); \
|
|
} break
|
|
|
|
// -----------------------------------------------------------------------------
|
|
static
|
|
void writeSequenceValue(BinaryWriter& _rWriter, uno::Any const& _aValue, uno::Type const& aElementType)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
switch(aElementType.getTypeClass())
|
|
{
|
|
CASE_WRITE_SEQUENCE( uno::TypeClass_BOOLEAN, sal_Bool );
|
|
|
|
CASE_WRITE_SEQUENCE( uno::TypeClass_SHORT, sal_Int16 );
|
|
|
|
CASE_WRITE_SEQUENCE( uno::TypeClass_LONG, sal_Int32 );
|
|
|
|
CASE_WRITE_SEQUENCE( uno::TypeClass_HYPER, sal_Int64 );
|
|
|
|
CASE_WRITE_SEQUENCE( uno::TypeClass_DOUBLE, double );
|
|
|
|
CASE_WRITE_SEQUENCE( uno::TypeClass_STRING, OUString );
|
|
|
|
CASE_WRITE_SEQUENCE( uno::TypeClass_SEQUENCE, uno::Sequence<sal_Int8> );
|
|
|
|
default:
|
|
OSL_ENSURE(false, "Unexpected typeclass for sequence elements");
|
|
break;
|
|
}
|
|
}
|
|
#undef CASE_WRITE_SEQUENCE
|
|
|
|
// -----------------------------------------------------------------------------
|
|
static
|
|
void writeSimpleValue(BinaryWriter& _rWriter, uno::Any const& _aValue, uno::Type const& _aType)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
// PRE: Header must be written
|
|
uno::TypeClass aDestinationClass = _aType.getTypeClass();
|
|
switch (aDestinationClass)
|
|
{
|
|
case uno::TypeClass_BOOLEAN:
|
|
{
|
|
sal_Bool bValue = sal_False;
|
|
writeFromAny(_rWriter, _aValue, bValue);
|
|
break;
|
|
}
|
|
case uno::TypeClass_BYTE:
|
|
{
|
|
sal_Int8 nValue = 0;
|
|
writeFromAny(_rWriter, _aValue, nValue);
|
|
break;
|
|
}
|
|
case uno::TypeClass_SHORT:
|
|
{
|
|
sal_Int16 nValue = 0;
|
|
writeFromAny(_rWriter, _aValue, nValue);
|
|
break;
|
|
}
|
|
case uno::TypeClass_LONG:
|
|
{
|
|
sal_Int32 nValue = 0;
|
|
writeFromAny(_rWriter, _aValue, nValue);
|
|
break;
|
|
}
|
|
case uno::TypeClass_HYPER:
|
|
{
|
|
sal_Int64 nValue = 0;
|
|
writeFromAny(_rWriter, _aValue, nValue);
|
|
break;
|
|
}
|
|
case uno::TypeClass_DOUBLE:
|
|
{
|
|
double nValue = 0;
|
|
writeFromAny(_rWriter, _aValue, nValue);
|
|
break;
|
|
}
|
|
case uno::TypeClass_STRING:
|
|
{
|
|
OUString aStr;
|
|
writeFromAny(_rWriter, _aValue, aStr);
|
|
break;
|
|
}
|
|
case uno::TypeClass_SEQUENCE:
|
|
{
|
|
OSL_ENSURE (_aType == SimpleTypeHelper::getBinaryType(),"Unexpected sequence as simple type");
|
|
uno::Sequence<sal_Int8> aBinary;
|
|
writeFromAny(_rWriter, _aValue, aBinary);
|
|
break;
|
|
}
|
|
default:
|
|
OSL_ENSURE(false, "Unexpected typeclass for simple value");
|
|
break;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeValue(uno::Any const& _aValue)
|
|
{
|
|
bool bSeq;
|
|
uno::Type aTargetType = getBasicType(_aValue.getValueType(), bSeq);
|
|
|
|
if (!bSeq)
|
|
{
|
|
writeSimpleValue(m_BinaryWriter,_aValue, aTargetType);
|
|
}
|
|
else
|
|
{
|
|
writeSequenceValue(m_BinaryWriter,_aValue, aTargetType);
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeFileHeader( rtl::OUString const & _aSchemaVersion,
|
|
const uno::Sequence<OUString> & aKnownLocales,
|
|
const uno::Sequence<OUString> & aDataLocales )
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
m_BinaryWriter.write(CFG_BINARY_MAGIC);
|
|
m_BinaryWriter.write(CFG_BINARY_VERSION);
|
|
m_BinaryWriter.write(_aSchemaVersion);
|
|
writeSequence(m_BinaryWriter,aKnownLocales);
|
|
writeSequence(m_BinaryWriter,aDataLocales);
|
|
m_BinaryWriter.write(m_aComponentName);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeGroupNode(rtl::OUString const& _aName,node::Attributes const& _aAttributes )
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
writeAttributes(_aAttributes );
|
|
m_BinaryWriter.write(_aName);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeSetNode(rtl::OUString const& _aName,
|
|
rtl::OUString const& _aTemplateName,
|
|
rtl::OUString const& _aTemplateModule,
|
|
node::Attributes const& _aAttributes)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
writeAttributes(_aAttributes );
|
|
m_BinaryWriter.write(_aName);
|
|
m_BinaryWriter.write(_aTemplateName);
|
|
m_BinaryWriter.write(_aTemplateModule);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeLayerInfoList(uno::Reference<backenduno::XLayer> const * pLayers, sal_Int32 nNumLayers)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
|
|
m_BinaryWriter.write(nNumLayers);
|
|
for (sal_Int32 i = 0 ; i < nNumLayers ; ++ i)
|
|
{
|
|
uno::Reference<util::XTimeStamped> xTimeStamp = uno::Reference<util::XTimeStamped>(pLayers[i], uno::UNO_QUERY);
|
|
|
|
OUString aTimeStamp = xTimeStamp.is() ? xTimeStamp->getTimestamp() : OUString();
|
|
m_BinaryWriter.write(aTimeStamp);
|
|
}
|
|
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeNodeType(NodeType::Type _eType)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
sal_Int8 nValue = static_cast< sal_Int8 >( _eType );
|
|
m_BinaryWriter.write(nValue);
|
|
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeAttributes(node::Attributes const& _aAttributes)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
sal_Int8 nValue = static_cast< sal_Int8 >( _aAttributes.state() );
|
|
|
|
OSL_ASSERT(0 <= nValue && nValue <= 3);
|
|
|
|
OSL_ENSURE(!_aAttributes.isReadonly() || !_aAttributes.isFinalized(),"Unexpected attribute mix: node is both read-only and finalized");
|
|
|
|
nValue |= (_aAttributes.isReadonly() ? 1 : 0) << 2;
|
|
nValue |= (_aAttributes.isFinalized() ? 1 : 0) << 3;
|
|
|
|
nValue |= (_aAttributes.isNullable() ? 1 : 0) << 4;
|
|
nValue |= (_aAttributes.isLocalized() ? 1 : 0) << 5;
|
|
|
|
nValue |= (_aAttributes.isMandatory() ? 1 : 0) << 6;
|
|
nValue |= (_aAttributes.isRemovable() ? 1 : 0) << 7;
|
|
|
|
m_BinaryWriter.write(nValue);
|
|
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeType(uno::Type const& _aType)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
ValueFlags::Type eType = convertTypeToValueType(_aType);
|
|
sal_Int8 nValueType = sal_Int8(eType);
|
|
m_BinaryWriter.write(nValueType);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeValueNode(rtl::OUString const& _aName,
|
|
node::Attributes const& _aAttributes,
|
|
uno::Type const& _aType,
|
|
uno::Any const& _aUserValue,
|
|
uno::Any const& _aDefaultValue)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
//write value flags
|
|
ValueFlags::Type eType = convertTypeToValueType(_aType);
|
|
sal_Int8 nValueType = sal_Int8(eType);
|
|
|
|
bool hasUserValue = _aUserValue.hasValue();
|
|
bool hasDefault = _aDefaultValue.hasValue();
|
|
|
|
if (!hasUserValue) nValueType |= ValueFlags::first_value_NULL;
|
|
if (!hasDefault) nValueType |= ValueFlags::second_value_NULL;
|
|
|
|
m_BinaryWriter.write(nValueType);
|
|
writeAttributes(_aAttributes );
|
|
m_BinaryWriter.write(_aName);
|
|
|
|
if(hasUserValue)
|
|
{
|
|
OSL_ENSURE(_aUserValue.getValueType() == _aType, "Type mismatch in value node");
|
|
writeValue(_aUserValue);
|
|
}
|
|
if(hasDefault)
|
|
{
|
|
OSL_ENSURE(_aDefaultValue.getValueType() == _aType, "Type mismatch in value node");
|
|
writeValue(_aDefaultValue);
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeStop()
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
sal_Int8 nStopValue = 0;
|
|
m_BinaryWriter.write(nStopValue);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeComponentTree(const ISubtree * _pComponentTree)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
this->writeNodeType(NodeType::component);
|
|
if (_pComponentTree)
|
|
{
|
|
this->writeTree(*_pComponentTree);
|
|
this->writeStop();
|
|
}
|
|
else
|
|
{
|
|
this->writeNodeType(NodeType::nodata);
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeTemplatesTree(const ISubtree * _pTemplatesTree)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
this->writeNodeType(NodeType::templates);
|
|
if (_pTemplatesTree)
|
|
{
|
|
this->writeTree(*_pTemplatesTree);
|
|
this->writeStop();
|
|
}
|
|
else
|
|
{
|
|
this->writeNodeType(NodeType::nodata);
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::writeTree(const ISubtree & rTree)
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
if ( rTree.isSetNode() )
|
|
{
|
|
this->writeNodeType(NodeType::setnode);
|
|
this->writeSetNode( rTree.getName(),
|
|
rTree.getElementTemplateName(),
|
|
rTree.getElementTemplateModule(),
|
|
rTree.getAttributes());
|
|
}
|
|
else
|
|
{
|
|
this->writeNodeType(NodeType::groupnode);
|
|
this->writeGroupNode( rTree.getName(), rTree.getAttributes() );
|
|
}
|
|
|
|
// process children
|
|
this->applyToChildren(rTree);
|
|
|
|
this->writeStop();
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::handle(const ISubtree & rTree)
|
|
{
|
|
writeTree(rTree);
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void BinaryWriteHandler::handle(const ValueNode & rValue)
|
|
{
|
|
this->writeNodeType(NodeType::valuenode);
|
|
|
|
this->writeValueNode( rValue.getName(),
|
|
rValue.getAttributes(),
|
|
rValue.getValueType(),
|
|
rValue.getUserValue(),
|
|
rValue.getDefault() );
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
bool BinaryWriteHandler::generateHeader(const uno::Reference<backenduno::XLayer> * pLayers,
|
|
sal_Int32 nNumLayers,
|
|
const OUString& aEntity,
|
|
const localehelper::LocaleSequence & aKnownLocales )
|
|
SAL_THROW( (io::IOException, uno::RuntimeException) )
|
|
{
|
|
//Open the writer
|
|
if (!m_BinaryWriter.open())
|
|
return false;
|
|
|
|
this->writeFileHeader( aEntity,
|
|
localehelper::makeIsoSequence(aKnownLocales),
|
|
getAvailableLocales(pLayers,nNumLayers) );
|
|
|
|
this->writeLayerInfoList(pLayers, nNumLayers);
|
|
return true;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
}
|