1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: binarywritehandler.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
33 #include "binarywritehandler.hxx"
34 #include "binarycache.hxx"
35 #include <com/sun/star/util/XTimeStamped.hpp>
36 #include "typeconverter.hxx"
37 #include "simpletypehelper.hxx"
39 #define ASCII(x) rtl::OUString::createFromAscii(x)
42 // -----------------------------------------------------------------------------
46 namespace css
= com::sun::star
;
47 namespace util
= css::util
;
49 // -----------------------------------------------------------------------------
51 BinaryWriteHandler::BinaryWriteHandler( rtl::OUString
const & _aFileURL
,
52 rtl::OUString
const & _aComponentName
,
53 uno::Reference
<lang::XMultiServiceFactory
> const & _aFactory
)
54 : m_BinaryWriter(_aFileURL
,_aFactory
)
55 , m_aComponentName(_aComponentName
)
59 // -----------------------------------------------------------------------------
61 binary::ValueFlags::Type
convertTypeToValueType(uno::Type
const& _aType
)
63 binary::ValueFlags::Type eType
= binary::ValueFlags::val_invalid
;
64 uno::TypeClass
const aClass
= _aType
.getTypeClass();
67 case uno::TypeClass_ANY
:
68 eType
= binary::ValueFlags::val_any
;
70 case uno::TypeClass_BOOLEAN
:
71 eType
= binary::ValueFlags::val_boolean
;
73 case uno::TypeClass_SHORT
:
74 eType
= binary::ValueFlags::val_int16
;
76 case uno::TypeClass_LONG
:
77 eType
= binary::ValueFlags::val_int32
;
79 case uno::TypeClass_HYPER
:
80 eType
= binary::ValueFlags::val_int64
;
82 case uno::TypeClass_DOUBLE
:
83 eType
= binary::ValueFlags::val_double
;
85 case uno::TypeClass_STRING
:
86 eType
= binary::ValueFlags::val_string
;
88 case uno::TypeClass_SEQUENCE
:
89 if (_aType
== SimpleTypeHelper::getBinaryType())
91 eType
= binary::ValueFlags::val_binary
;
95 uno::Type aType
= configmgr::getSequenceElementType(_aType
);
96 eType
= convertTypeToValueType(aType
);
98 OSL_ENSURE(!(eType
& binary::ValueFlags::seq
), "Binary Writer - Invalid value type: Multiple nesting of sequences");
99 eType
= binary::ValueFlags::Type( eType
| binary::ValueFlags::seq
);
103 OSL_ENSURE(false, "Binary Writer - Invalid value type: not supported");
109 // -----------------------------------------------------------------------------
111 inline /* make performance crew happy ;-) */
112 void writeDirectly(BinaryWriter
& _rWriter
, T
const& _aVal
)
113 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
115 _rWriter
.write(_aVal
);
117 // -----------------------------------------------------------------------------
120 void writeDirectly(BinaryWriter
& _rWriter
, uno::Sequence
<sal_Int8
> const& _aBinary
);
121 // -----------------------------------------------------------------------------
123 inline /* make performance crew happy ;-) */
124 void writeFromAny(BinaryWriter
& _rWriter
,uno::Any
const& _aValue
, T
& _aVar
)
125 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
127 OSL_VERIFY(_aValue
>>= _aVar
); // "Invalid Any for value"
128 writeDirectly(_rWriter
,_aVar
);
130 // -----------------------------------------------------------------------------
132 template <class Element
>
133 void writeSequence(BinaryWriter
& _rWriter
, uno::Sequence
< Element
> const& aSequence
)
134 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
136 sal_Int32
const nLength
= aSequence
.getLength();
137 _rWriter
.write(nLength
);
139 for(sal_Int32 i
=0; i
<nLength
; ++i
)
141 writeDirectly(_rWriter
, aSequence
[i
]);
144 // -----------------------------------------------------------------------------
147 void writeDirectly(BinaryWriter
& _rWriter
, uno::Sequence
<sal_Int8
> const& _aBinary
)
149 writeSequence(_rWriter
,_aBinary
);
151 // -----------------------------------------------------------------------------
152 #define CASE_WRITE_SEQUENCE(TYPE_CLASS, DATA_TYPE) \
155 uno::Sequence< DATA_TYPE > aData; \
156 OSL_ASSERT( ::getCppuType(aData.getConstArray()).getTypeClass() == (TYPE_CLASS) ); \
157 OSL_VERIFY( _aValue >>= aData ); \
158 writeSequence(_rWriter,aData); \
161 // -----------------------------------------------------------------------------
163 void writeSequenceValue(BinaryWriter
& _rWriter
, uno::Any
const& _aValue
, uno::Type
const& aElementType
)
164 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
166 switch(aElementType
.getTypeClass())
168 CASE_WRITE_SEQUENCE( uno::TypeClass_BOOLEAN
, sal_Bool
);
170 CASE_WRITE_SEQUENCE( uno::TypeClass_SHORT
, sal_Int16
);
172 CASE_WRITE_SEQUENCE( uno::TypeClass_LONG
, sal_Int32
);
174 CASE_WRITE_SEQUENCE( uno::TypeClass_HYPER
, sal_Int64
);
176 CASE_WRITE_SEQUENCE( uno::TypeClass_DOUBLE
, double );
178 CASE_WRITE_SEQUENCE( uno::TypeClass_STRING
, rtl::OUString
);
180 CASE_WRITE_SEQUENCE( uno::TypeClass_SEQUENCE
, uno::Sequence
<sal_Int8
> );
183 OSL_ENSURE(false, "Unexpected typeclass for sequence elements");
187 #undef CASE_WRITE_SEQUENCE
189 // -----------------------------------------------------------------------------
191 void writeSimpleValue(BinaryWriter
& _rWriter
, uno::Any
const& _aValue
, uno::Type
const& _aType
)
192 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
194 // PRE: Header must be written
195 uno::TypeClass aDestinationClass
= _aType
.getTypeClass();
196 switch (aDestinationClass
)
198 case uno::TypeClass_BOOLEAN
:
200 sal_Bool bValue
= sal_False
;
201 writeFromAny(_rWriter
, _aValue
, bValue
);
204 case uno::TypeClass_BYTE
:
207 writeFromAny(_rWriter
, _aValue
, nValue
);
210 case uno::TypeClass_SHORT
:
212 sal_Int16 nValue
= 0;
213 writeFromAny(_rWriter
, _aValue
, nValue
);
216 case uno::TypeClass_LONG
:
218 sal_Int32 nValue
= 0;
219 writeFromAny(_rWriter
, _aValue
, nValue
);
222 case uno::TypeClass_HYPER
:
224 sal_Int64 nValue
= 0;
225 writeFromAny(_rWriter
, _aValue
, nValue
);
228 case uno::TypeClass_DOUBLE
:
231 writeFromAny(_rWriter
, _aValue
, nValue
);
234 case uno::TypeClass_STRING
:
237 writeFromAny(_rWriter
, _aValue
, aStr
);
240 case uno::TypeClass_SEQUENCE
:
242 OSL_ENSURE (_aType
== SimpleTypeHelper::getBinaryType(),"Unexpected sequence as simple type");
243 uno::Sequence
<sal_Int8
> aBinary
;
244 writeFromAny(_rWriter
, _aValue
, aBinary
);
248 OSL_ENSURE(false, "Unexpected typeclass for simple value");
253 // -----------------------------------------------------------------------------
255 void BinaryWriteHandler::writeValue(uno::Any
const& _aValue
)
258 uno::Type aTargetType
= getBasicType(_aValue
.getValueType(), bSeq
);
262 writeSimpleValue(m_BinaryWriter
,_aValue
, aTargetType
);
266 writeSequenceValue(m_BinaryWriter
,_aValue
, aTargetType
);
269 // -----------------------------------------------------------------------------
271 void BinaryWriteHandler::writeFileHeader( rtl::OUString
const & _aSchemaVersion
,
272 const uno::Sequence
<rtl::OUString
> & aKnownLocales
,
273 const uno::Sequence
<rtl::OUString
> & aDataLocales
)
274 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
276 m_BinaryWriter
.write(binary::CFG_BINARY_MAGIC
);
277 m_BinaryWriter
.write(binary::CFG_BINARY_VERSION
);
278 m_BinaryWriter
.write(_aSchemaVersion
);
279 writeSequence(m_BinaryWriter
,aKnownLocales
);
280 writeSequence(m_BinaryWriter
,aDataLocales
);
281 m_BinaryWriter
.write(m_aComponentName
);
283 // -----------------------------------------------------------------------------
285 void BinaryWriteHandler::writeGroupNode(rtl::OUString
const& _aName
,node::Attributes
const& _aAttributes
)
286 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
288 writeAttributes(_aAttributes
);
289 m_BinaryWriter
.write(_aName
);
292 // -----------------------------------------------------------------------------
294 void BinaryWriteHandler::writeSetNode(rtl::OUString
const& _aName
,
295 rtl::OUString
const& _aTemplateName
,
296 rtl::OUString
const& _aTemplateModule
,
297 node::Attributes
const& _aAttributes
)
298 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
300 writeAttributes(_aAttributes
);
301 m_BinaryWriter
.write(_aName
);
302 m_BinaryWriter
.write(_aTemplateName
);
303 m_BinaryWriter
.write(_aTemplateModule
);
305 // -----------------------------------------------------------------------------
307 void BinaryWriteHandler::writeLayerInfoList(uno::Reference
<backenduno::XLayer
> const * pLayers
, sal_Int32 nNumLayers
)
308 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
311 m_BinaryWriter
.write(nNumLayers
);
312 for (sal_Int32 i
= 0 ; i
< nNumLayers
; ++ i
)
314 uno::Reference
<util::XTimeStamped
> xTimeStamp
= uno::Reference
<util::XTimeStamped
>(pLayers
[i
], uno::UNO_QUERY
);
316 rtl::OUString aTimeStamp
= xTimeStamp
.is() ? xTimeStamp
->getTimestamp() : rtl::OUString();
317 m_BinaryWriter
.write(aTimeStamp
);
321 // -----------------------------------------------------------------------------
323 void BinaryWriteHandler::writeNodeType(binary::NodeType::Type _eType
)
324 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
326 sal_Int8 nValue
= static_cast< sal_Int8
>( _eType
);
327 m_BinaryWriter
.write(nValue
);
330 // -----------------------------------------------------------------------------
332 void BinaryWriteHandler::writeAttributes(node::Attributes
const& _aAttributes
)
333 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
335 sal_Int8 nValue
= static_cast< sal_Int8
>( _aAttributes
.state() );
337 OSL_ASSERT(0 <= nValue
&& nValue
<= 3);
339 OSL_ENSURE(!_aAttributes
.isReadonly() || !_aAttributes
.isFinalized(),"Unexpected attribute mix: node is both read-only and finalized");
341 nValue
|= (_aAttributes
.isReadonly() ? 1 : 0) << 2;
342 nValue
|= (_aAttributes
.isFinalized() ? 1 : 0) << 3;
344 nValue
|= (_aAttributes
.isNullable() ? 1 : 0) << 4;
345 nValue
|= (_aAttributes
.isLocalized() ? 1 : 0) << 5;
347 nValue
|= (_aAttributes
.isMandatory() ? 1 : 0) << 6;
348 nValue
|= (_aAttributes
.isRemovable() ? 1 : 0) << 7;
350 m_BinaryWriter
.write(nValue
);
353 // -----------------------------------------------------------------------------
355 void BinaryWriteHandler::writeValueNode(rtl::OUString
const& _aName
,
356 node::Attributes
const& _aAttributes
,
357 uno::Type
const& _aType
,
358 uno::Any
const& _aUserValue
,
359 uno::Any
const& _aDefaultValue
)
360 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
363 binary::ValueFlags::Type eType
= convertTypeToValueType(_aType
);
364 sal_Int8 nValueType
= sal_Int8(eType
);
366 bool hasUserValue
= _aUserValue
.hasValue();
367 bool hasDefault
= _aDefaultValue
.hasValue();
369 if (!hasUserValue
) nValueType
|= binary::ValueFlags::first_value_NULL
;
370 if (!hasDefault
) nValueType
|= binary::ValueFlags::second_value_NULL
;
372 m_BinaryWriter
.write(nValueType
);
373 writeAttributes(_aAttributes
);
374 m_BinaryWriter
.write(_aName
);
378 OSL_ENSURE(_aUserValue
.getValueType() == _aType
, "Type mismatch in value node");
379 writeValue(_aUserValue
);
383 OSL_ENSURE(_aDefaultValue
.getValueType() == _aType
, "Type mismatch in value node");
384 writeValue(_aDefaultValue
);
387 // -----------------------------------------------------------------------------
389 void BinaryWriteHandler::writeStop()
390 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
392 sal_Int8 nStopValue
= 0;
393 m_BinaryWriter
.write(nStopValue
);
395 // -----------------------------------------------------------------------------
397 void BinaryWriteHandler::writeComponentTree(const ISubtree
* _pComponentTree
)
398 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
400 this->writeNodeType(binary::NodeType::component
);
403 this->writeTree(*_pComponentTree
);
408 this->writeNodeType(binary::NodeType::nodata
);
411 // -----------------------------------------------------------------------------
413 void BinaryWriteHandler::writeTemplatesTree(const ISubtree
* _pTemplatesTree
)
414 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
416 this->writeNodeType(binary::NodeType::templates
);
419 this->writeTree(*_pTemplatesTree
);
424 this->writeNodeType(binary::NodeType::nodata
);
427 // -----------------------------------------------------------------------------
429 void BinaryWriteHandler::writeTree(const ISubtree
& rTree
)
430 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
432 if ( rTree
.isSetNode() )
434 this->writeNodeType(binary::NodeType::setnode
);
435 this->writeSetNode( rTree
.getName(),
436 rTree
.getElementTemplateName(),
437 rTree
.getElementTemplateModule(),
438 rTree
.getAttributes());
442 this->writeNodeType(binary::NodeType::groupnode
);
443 this->writeGroupNode( rTree
.getName(), rTree
.getAttributes() );
447 this->applyToChildren(rTree
);
451 // -----------------------------------------------------------------------------
453 void BinaryWriteHandler::handle(const ISubtree
& rTree
)
457 // -----------------------------------------------------------------------------
459 void BinaryWriteHandler::handle(const ValueNode
& rValue
)
461 this->writeNodeType(binary::NodeType::valuenode
);
463 this->writeValueNode( rValue
.getName(),
464 rValue
.getAttributes(),
465 rValue
.getValueType(),
466 rValue
.getUserValue(),
467 rValue
.getDefault() );
469 // -----------------------------------------------------------------------------
471 bool BinaryWriteHandler::generateHeader(const uno::Reference
<backenduno::XLayer
> * pLayers
,
472 sal_Int32 nNumLayers
,
473 const rtl::OUString
& aEntity
,
474 const std::vector
< com::sun::star::lang::Locale
> & aKnownLocales
)
475 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
478 if (!m_BinaryWriter
.open())
481 this->writeFileHeader( aEntity
,
482 localehelper::makeIsoSequence(aKnownLocales
),
483 getAvailableLocales(pLayers
,nNumLayers
) );
485 this->writeLayerInfoList(pLayers
, nNumLayers
);
488 // -----------------------------------------------------------------------------
491 // -----------------------------------------------------------------------------