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: binaryreadhandler.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 "binaryreadhandler.hxx"
34 #include "binarycache.hxx"
35 #include "binarytype.hxx"
36 #include "simpletypehelper.hxx"
37 #include "typeconverter.hxx"
38 #include "treenodefactory.hxx"
41 #include <com/sun/star/io/WrongFormatException.hpp>
42 #include <com/sun/star/util/XTimeStamped.hpp>
45 #define ASCII(x) rtl::OUString::createFromAscii(x)
49 // -----------------------------------------------------------------------------
53 namespace css
= com::sun::star
;
54 namespace io
= css::io
;
55 namespace util
= css::util
;
57 // -----------------------------------------------------------------------------
58 BinaryReadHandler::BinaryReadHandler(rtl::OUString
const & _aFileURL
,
59 rtl::OUString
const & _aComponentName
,
60 uno::Reference
<lang::XMultiServiceFactory
> const & )
61 : m_BinaryReader(_aFileURL
)
63 , m_aComponentName(_aComponentName
)
66 // -----------------------------------------------------------------------------
67 BinaryReadHandler::~BinaryReadHandler()
70 // -----------------------------------------------------------------------------
73 bool isRequestingNoLocale(com::sun::star::lang::Locale
const & aRequestedLocale
)
75 rtl::OUString
const & aLanguage
= aRequestedLocale
.Language
;
76 return aLanguage
.getLength() == 0 || localehelper::isDefaultLanguage(aLanguage
);
78 // -----------------------------------------------------------------------------
81 bool supportsLocale(uno::Sequence
< rtl::OUString
> const & aStoredLocales
, rtl::OUString
const & aRequestedLocale
)
83 for (sal_Int32 ix
=0; ix
<aStoredLocales
.getLength(); ++ix
)
84 if (aStoredLocales
[ix
].equalsIgnoreAsciiCase(aRequestedLocale
))
89 // -----------------------------------------------------------------------------
92 bool supportsAll(uno::Sequence
< rtl::OUString
> const & aStoredLocales
, uno::Sequence
< rtl::OUString
> const & aRequestedLocales
)
94 for (sal_Int32 jx
=0; jx
<aRequestedLocales
.getLength(); ++jx
)
95 if (!supportsLocale(aStoredLocales
,aRequestedLocales
[jx
]))
100 // -----------------------------------------------------------------------------
102 bool BinaryReadHandler::verifyFileHeader( const uno::Reference
<backenduno::XLayer
> * pLayers
,
103 sal_Int32 nNumLayers
,
104 const rtl::OUString
& _aSchemaVersion
,
105 com::sun::star::lang::Locale
const & aRequestedLocale
,
106 std::vector
< com::sun::star::lang::Locale
> & outKnownLocales
)
111 sal_Int16 nMagic
, nVersion
;
112 m_BinaryReader
.read(nMagic
);
113 m_BinaryReader
.read(nVersion
);
114 if (nMagic
!=binary::CFG_BINARY_MAGIC
|| nVersion
!= binary::CFG_BINARY_VERSION
)
117 rtl::OUString aSchemaVersion
;
118 m_BinaryReader
.read(aSchemaVersion
);
119 if (!aSchemaVersion
.equals(_aSchemaVersion
))
122 uno::Sequence
< rtl::OUString
> aAvailableLocales
;
123 uno::Sequence
< rtl::OUString
> aKnownLocales
;
124 m_BinaryReader
.read(aKnownLocales
);
125 m_BinaryReader
.read(aAvailableLocales
);
126 outKnownLocales
= localehelper::makeLocaleSequence(aKnownLocales
);
128 if (isRequestingNoLocale(aRequestedLocale
))
130 // any existing combination of locales (including none) is valid
132 else if (!localehelper::designatesAllLocales(aRequestedLocale
))
134 // one particular locale requested
135 rtl::OUString
const aIsoLocale
= localehelper::makeIsoLocale(aRequestedLocale
);
136 if (!supportsLocale(aKnownLocales
,aIsoLocale
))
138 // a locale we didn't load previously
141 else if (! supportsLocale(aAvailableLocales
,aIsoLocale
))
143 // a locale we handled by fallback previously
144 uno::Sequence
< rtl::OUString
> aNewlyAvailableLocales
=
145 getAvailableLocales(pLayers
,nNumLayers
);
147 // ... and that has become available now
148 if (supportsLocale(aNewlyAvailableLocales
,aIsoLocale
))
151 // ... or other new locales have been added
152 if (!supportsAll(aAvailableLocales
,aNewlyAvailableLocales
))
158 uno::Sequence
< rtl::OUString
> aNewlyAvailableLocales
=
159 getAvailableLocales(pLayers
,nNumLayers
);
161 // not all locales were requested yet
162 if (!supportsAll(aKnownLocales
,aNewlyAvailableLocales
))
165 // new locales have been added
166 if (!supportsAll(aAvailableLocales
,aNewlyAvailableLocales
))
170 rtl::OUString aComponentName
;
171 m_BinaryReader
.read(aComponentName
);
172 if (!aComponentName
.equals(m_aComponentName
))
177 catch (uno::Exception
&)
179 CFG_TRACE_INFO("Binary Cache can't be used");
183 // -----------------------------------------------------------------------------
184 bool BinaryReadHandler::isUptodate(const std::vector
<rtl::OUString
> & _timeStamps
)
185 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
187 sal_Int32 nNumBinaryLayers
;
188 m_BinaryReader
.read(nNumBinaryLayers
);
189 if (nNumBinaryLayers
< 0 || sal_uInt32(nNumBinaryLayers
) != _timeStamps
.size())
192 for ( std::vector
<rtl::OUString
>::const_iterator it
= _timeStamps
.begin();
193 it
!= _timeStamps
.end();
196 rtl::OUString binaryTimeStamp
;
197 m_BinaryReader
.read(binaryTimeStamp
);
198 if ( ! it
->equals(binaryTimeStamp
) )
206 // -----------------------------------------------------------------------------
207 binary::NodeType::Type
BinaryReadHandler::readNodeType()
208 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
210 binary::NodeType::Type eType
= binary::NodeType::invalid
;
213 m_BinaryReader
.read(nValue
);
215 sal_uInt8
const nRightValue( nValue
);
216 if ( (nRightValue
& binary::NodeType::nodetype_mask
) == nRightValue
)
217 eType
= binary::NodeType::Type(nRightValue
);
219 if (eType
== binary::NodeType::invalid
)
221 OSL_ENSURE(false, "unknown or unhandled node type");
222 throw io::WrongFormatException();
228 // -----------------------------------------------------------------------------
229 binary::ValueFlags::Type
BinaryReadHandler::readValueFlags(bool& bSeq
, bool& bHasValue
, bool& bHasDefault
)
230 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
233 m_BinaryReader
.read(nValue
);
235 sal_uInt8
const nRightValue( nValue
);
236 binary::ValueFlags::Type eType
= binary::ValueFlags::Type(nRightValue
& binary::ValueFlags::basictype_mask
);
237 if ( eType
>= binary::ValueFlags::val_invalid
)
239 OSL_ENSURE(false, "unknown or unhandled value type");
240 throw io::WrongFormatException();
244 if (nRightValue
& binary::ValueFlags::seq
)
249 if (nRightValue
& binary::ValueFlags::first_value_NULL
)
254 if (nRightValue
& binary::ValueFlags::second_value_NULL
)
262 // -----------------------------------------------------------------------------
264 void BinaryReadHandler::readName(rtl::OUString
&_aString
)
265 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
267 m_BinaryReader
.read (_aString
);
270 // -----------------------------------------------------------------------------
271 void BinaryReadHandler::readAttributes(node::Attributes
&_aAttributes
)
272 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
275 m_BinaryReader
.read(nValue
);
277 _aAttributes
.setState( node::State(nValue
& 0x03) );
279 _aAttributes
.setAccess( nValue
& 0x04 ? true : false, nValue
& 0x08 ? true : false);
281 _aAttributes
.setNullable(nValue
& 0x10 ? true : false);
282 _aAttributes
.setLocalized(nValue
& 0x20 ? true : false);
285 _aAttributes
.markMandatory();
289 _aAttributes
.markRemovable();
292 // -----------------------------------------------------------------------------
294 void BinaryReadHandler::readGroup(rtl::OUString
&_aName
, node::Attributes
&_aAttributes
)
295 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
297 readAttributes(_aAttributes
);
300 // -----------------------------------------------------------------------------
301 void BinaryReadHandler::readSet(rtl::OUString
&_aName
, node::Attributes
&_aAttributes
,
302 rtl::OUString
&_sInstanceName
, rtl::OUString
&_sInstanceModule
)
303 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
305 readAttributes(_aAttributes
);
307 readName(_sInstanceName
);
308 readName(_sInstanceModule
);
311 // -----------------------------------------------------------------------------
314 void readAsAny(BinaryReader
& rBinaryReader
, uno::Any
& _aValue
, uno::Type
& _aType
, T
& _aVar
)
315 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
317 rBinaryReader
.read(_aVar
);
319 _aType
= _aValue
.getValueType();
322 // -----------------------------------------------------------------------------
323 uno::Type
convertValueTypeToType(binary::ValueFlags::Type eBasicValueType
, bool bSeq
)
329 switch(eBasicValueType
)
331 // --------------- Simple types ---------------
333 case binary::ValueFlags::val_boolean
:
334 aType
= SimpleTypeHelper::getBooleanType();
336 case binary::ValueFlags::val_int16
:
337 aType
= SimpleTypeHelper::getShortType();
339 case binary::ValueFlags::val_int32
:
340 aType
= SimpleTypeHelper::getIntType();
342 case binary::ValueFlags::val_int64
:
343 aType
= SimpleTypeHelper::getLongType();
345 case binary::ValueFlags::val_double
:
346 aType
= SimpleTypeHelper::getDoubleType();
348 case binary::ValueFlags::val_string
:
349 aType
= SimpleTypeHelper::getStringType();
351 case binary::ValueFlags::val_binary
:
352 aType
= SimpleTypeHelper::getBinaryType();
354 case binary::ValueFlags::val_any
:
355 aType
= SimpleTypeHelper::getAnyType();
358 OSL_ENSURE(false,"Invalid value type");
364 // ------------ Sequences ------------
365 switch(eBasicValueType
)
367 case binary::ValueFlags::val_boolean
:
368 aType
= ::getCppuType(static_cast<uno::Sequence
<sal_Bool
> const*>(0));
370 case binary::ValueFlags::val_int16
:
371 aType
= ::getCppuType(static_cast<uno::Sequence
<sal_Int16
> const*>(0));
373 case binary::ValueFlags::val_int32
:
374 aType
= ::getCppuType(static_cast<uno::Sequence
<sal_Int32
> const*>(0));
376 case binary::ValueFlags::val_int64
:
377 aType
= ::getCppuType(static_cast<uno::Sequence
<sal_Int64
> const*>(0));
379 case binary::ValueFlags::val_double
:
380 aType
= ::getCppuType(static_cast<uno::Sequence
<double> const*>(0));
382 case binary::ValueFlags::val_string
:
383 aType
= ::getCppuType(static_cast<uno::Sequence
<rtl::OUString
> const*>(0));
385 case binary::ValueFlags::val_binary
:
386 aType
= ::getCppuType(static_cast<uno::Sequence
< uno::Sequence
< sal_Int8
> > const*>(0));
389 OSL_ENSURE(false,"Invalid sequence value type");
397 // -----------------------------------------------------------------------------
398 void BinaryReadHandler::readValue(rtl::OUString
&_aName
, node::Attributes
&_aAttributes
,
399 uno::Any
& _aValue
, uno::Any
& _aDefaultValue
,uno::Type
& _aType
)
400 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
403 bool bHasValue
= false;
404 bool bHasDefault
= false;
406 binary::ValueFlags::Type eBasicType
= readValueFlags(bSeq
, bHasValue
, bHasDefault
);
407 readAttributes(_aAttributes
);
410 if (!bSeq
&& (bHasValue
|| bHasDefault
))
414 case binary::ValueFlags::val_any
:
416 OSL_ENSURE(false,"Node of type Any cannot have value");
417 throw io::WrongFormatException();
419 case binary::ValueFlags::val_string
:
423 readAsAny(m_BinaryReader
, _aValue
, _aType
, aStr
);
425 readAsAny(m_BinaryReader
, _aDefaultValue
, _aType
, aStr
);
428 case binary::ValueFlags::val_boolean
:
432 readAsAny(m_BinaryReader
,_aValue
, _aType
, nValue
);
434 readAsAny(m_BinaryReader
,_aDefaultValue
, _aType
, nValue
);
437 case binary::ValueFlags::val_int16
:
441 readAsAny(m_BinaryReader
,_aValue
, _aType
, nValue
);
443 readAsAny(m_BinaryReader
,_aDefaultValue
, _aType
, nValue
);
446 case binary::ValueFlags::val_int32
:
450 readAsAny(m_BinaryReader
,_aValue
, _aType
, nValue
);
452 readAsAny(m_BinaryReader
,_aDefaultValue
, _aType
, nValue
);
455 case binary::ValueFlags::val_int64
:
459 readAsAny(m_BinaryReader
,_aValue
, _aType
, nValue
);
461 readAsAny(m_BinaryReader
,_aDefaultValue
, _aType
, nValue
);
464 case binary::ValueFlags::val_double
:
468 readAsAny(m_BinaryReader
,_aValue
, _aType
, nValue
);
470 readAsAny(m_BinaryReader
, _aDefaultValue
, _aType
, nValue
);
473 case binary::ValueFlags::val_binary
:
475 uno::Sequence
< sal_Int8
> aValue
;
477 readAsAny(m_BinaryReader
,_aValue
, _aType
, aValue
);
479 readAsAny(m_BinaryReader
,_aDefaultValue
, _aType
, aValue
);
483 OSL_ENSURE(false, "Invalid value type");
484 throw io::WrongFormatException();
489 _aType
= convertValueTypeToType(eBasicType
, bSeq
);
490 if (_aType
== uno::Type())
491 throw io::WrongFormatException();
496 OSL_ASSERT(_aType
.getTypeClass() == uno::TypeClass_SEQUENCE
);
497 uno::Type
const aElementType
= getSequenceElementType(_aType
);
499 readSequenceValue(m_BinaryReader
, _aValue
, aElementType
);
502 readSequenceValue(m_BinaryReader
, _aDefaultValue
, aElementType
);
506 // -----------------------------------------------------------------------------
507 std::auto_ptr
<ISubtree
> BinaryReadHandler::readComponentTree()
508 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
510 binary::NodeType::Type eType
= this->readNodeType();
512 if (eType
!= binary::NodeType::component
)
514 // TODO: search for component tree
515 OSL_ENSURE(false, "binary Cache: unexpected tree type for component data");
516 throw io::WrongFormatException();
519 return readToplevelTree();
521 // -----------------------------------------------------------------------------
522 std::auto_ptr
<ISubtree
> BinaryReadHandler::readTemplatesTree()
523 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
525 binary::NodeType::Type eType
= this->readNodeType();
527 if (eType
!= binary::NodeType::templates
)
529 // TODO: search for templates tree
530 OSL_ENSURE(false, "binary Cache: unexpected tree type for template data");
531 throw io::WrongFormatException();
534 return readToplevelTree();
536 // -----------------------------------------------------------------------------
538 std::auto_ptr
<ISubtree
> BinaryReadHandler::readToplevelTree()
539 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
541 std::auto_ptr
<ISubtree
> pTree
;
544 node::Attributes aAttributes
;
545 const bool not_extensible
= false;
547 binary::NodeType::Type eType
= this->readNodeType();
550 case binary::NodeType::groupnode
:
552 this->readGroup(aName
, aAttributes
);
553 pTree
= m_aNodeFactory
.createGroup(aName
,not_extensible
,aAttributes
);
556 case binary::NodeType::setnode
:
558 backenduno::TemplateIdentifier aTemplate
;
559 this->readSet(aName
, aAttributes
,aTemplate
.Name
, aTemplate
.Component
);
560 pTree
= m_aNodeFactory
.createSet(aName
,aTemplate
,not_extensible
,aAttributes
);
563 case binary::NodeType::nodata
:
567 OSL_ENSURE(false, "binary Cache - cannot read data: unexpected node type for tree");
568 throw io::WrongFormatException();
572 if (pTree
.get() != NULL
)
574 readChildren(*pTree
);
576 //read terminating stop node
577 eType
= this->readNodeType();
578 OSL_ENSURE(binary::NodeType::stop
== eType
, "Missing stop node to mark end of tree");
584 // -----------------------------------------------------------------------------
585 bool BinaryReadHandler::validateHeader( const uno::Reference
<backenduno::XLayer
> * pLayers
,
586 sal_Int32 nNumLayers
,
587 const rtl::OUString
& _aSchemaVersion
,
588 com::sun::star::lang::Locale
const & aRequestedLocale
,
589 std::vector
< com::sun::star::lang::Locale
> & outKnownLocales
)
590 SAL_THROW( (io::IOException
, uno::RuntimeException
) )
593 //Check here if the file exists
594 if (!m_BinaryReader
.open())
597 if(!this->verifyFileHeader(pLayers
, nNumLayers
, _aSchemaVersion
, aRequestedLocale
, outKnownLocales
))
600 //Check if layers are uptodate
601 std::vector
<rtl::OUString
> timeStamps(nNumLayers
);
602 for (sal_Int32 i
= 0 ; i
< nNumLayers
; ++ i
)
604 uno::Reference
<util::XTimeStamped
> xTimeStamp
= uno::Reference
<util::XTimeStamped
>(pLayers
[i
], uno::UNO_QUERY
);
607 rtl::OUString aTimeStamp
= xTimeStamp
->getTimestamp();
608 timeStamps
[i
] = aTimeStamp
;
612 return this->isUptodate(timeStamps
);
614 // -----------------------------------------------------------------------------
615 void BinaryReadHandler::readChildren(ISubtree
& rTree
)
617 OSL_ASSERT(!binary::NodeType::stop
); // loop stops at stop node
618 while (binary::NodeType::Type eType
= this->readNodeType())
621 node::Attributes aAttributes
;
622 const bool not_extensible
= false;
625 case binary::NodeType::groupnode
:
627 this->readGroup(aName
, aAttributes
);
629 std::auto_ptr
<ISubtree
> pNewNode
= m_aNodeFactory
.createGroup(aName
, not_extensible
, aAttributes
);
630 if (pNewNode
.get() == NULL
)
632 OSL_ENSURE(false, "Error: factory returned NULL group node - skipping");
636 readChildren( *pNewNode
);
637 rTree
.addChild(base_ptr(pNewNode
));
640 case binary::NodeType::setnode
:
642 backenduno::TemplateIdentifier aTemplate
;
643 this->readSet(aName
, aAttributes
,aTemplate
.Name
, aTemplate
.Component
);
645 std::auto_ptr
<ISubtree
> pNewSetNode
= m_aNodeFactory
.createSet(aName
,aTemplate
,not_extensible
,aAttributes
);
646 if (pNewSetNode
.get() == NULL
)
648 OSL_ENSURE(false, "Error: factory returned NULL set node - skipping");
652 readChildren( *pNewSetNode
);
653 rTree
.addChild(base_ptr(pNewSetNode
));
656 case binary::NodeType::valuenode
:
659 uno::Any aDefaultValue
;
662 this->readValue(aName
, aAttributes
, aValue
, aDefaultValue
, aType
);
664 OTreeNodeFactory
& rValueFactory
= m_aNodeFactory
.getNodeFactory();
666 std::auto_ptr
<ValueNode
> pValueNode
;
667 if (aValue
.hasValue() || aDefaultValue
.hasValue())
669 pValueNode
= rValueFactory
.createValueNode(aName
,aValue
, aDefaultValue
, aAttributes
);
673 pValueNode
= rValueFactory
.createNullValueNode(aName
,aType
, aAttributes
);
676 rTree
.addChild(base_ptr(pValueNode
));
680 OSL_ENSURE(false, "Binary cache: Invalid node type");
681 throw io::WrongFormatException();
685 // -----------------------------------------------------------------------------
687 // -----------------------------------------------------------------------------
689 // -----------------------------------------------------------------------------