merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / backend / binaryreadhandler.cxx
blobeefca289522416fbb8953639e67c131101eb608e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: binaryreadhandler.cxx,v $
10 * $Revision: 1.12 $
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"
40 #include "tracer.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)
47 namespace configmgr
49 // -----------------------------------------------------------------------------
50 namespace backend
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)
62 , m_aNodeFactory()
63 , m_aComponentName(_aComponentName)
66 // -----------------------------------------------------------------------------
67 BinaryReadHandler::~BinaryReadHandler()
70 // -----------------------------------------------------------------------------
72 static inline
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 // -----------------------------------------------------------------------------
80 static
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))
85 return true;
87 return false;
89 // -----------------------------------------------------------------------------
91 static
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]))
96 return false;
98 return true;
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)
110 //Open the reader
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 )
115 return false;
117 rtl::OUString aSchemaVersion;
118 m_BinaryReader.read(aSchemaVersion);
119 if (!aSchemaVersion.equals(_aSchemaVersion))
120 return false;
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
139 return false;
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))
149 return false;
151 // ... or other new locales have been added
152 if (!supportsAll(aAvailableLocales,aNewlyAvailableLocales))
153 return false;
156 else
158 uno::Sequence< rtl::OUString > aNewlyAvailableLocales =
159 getAvailableLocales(pLayers,nNumLayers);
161 // not all locales were requested yet
162 if (!supportsAll(aKnownLocales,aNewlyAvailableLocales))
163 return false;
165 // new locales have been added
166 if (!supportsAll(aAvailableLocales,aNewlyAvailableLocales))
167 return false;
170 rtl::OUString aComponentName;
171 m_BinaryReader.read(aComponentName);
172 if (!aComponentName.equals(m_aComponentName))
173 return false;
175 return true;
177 catch (uno::Exception &)
179 CFG_TRACE_INFO("Binary Cache can't be used");
180 return false;
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())
190 return false;
192 for ( std::vector<rtl::OUString>::const_iterator it = _timeStamps.begin();
193 it != _timeStamps.end();
194 ++it)
196 rtl::OUString binaryTimeStamp;
197 m_BinaryReader.read(binaryTimeStamp);
198 if ( ! it->equals(binaryTimeStamp) )
200 return false;
204 return true;
206 // -----------------------------------------------------------------------------
207 binary::NodeType::Type BinaryReadHandler::readNodeType()
208 SAL_THROW( (io::IOException, uno::RuntimeException) )
210 binary::NodeType::Type eType = binary::NodeType::invalid;
212 sal_Int8 nValue;
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();
225 return eType;
228 // -----------------------------------------------------------------------------
229 binary::ValueFlags::Type BinaryReadHandler::readValueFlags(bool& bSeq, bool& bHasValue, bool& bHasDefault )
230 SAL_THROW( (io::IOException, uno::RuntimeException) )
232 sal_Int8 nValue;
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)
245 bSeq = true;
246 else
247 bSeq = false;
249 if (nRightValue & binary::ValueFlags::first_value_NULL)
250 bHasValue = false;
251 else
252 bHasValue = true;
254 if (nRightValue & binary::ValueFlags::second_value_NULL)
255 bHasDefault = false;
256 else
257 bHasDefault = true;
259 return eType;
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) )
274 sal_Int8 nValue;
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);
283 if(nValue & 0x40 )
285 _aAttributes.markMandatory();
287 if(nValue & 0x80)
289 _aAttributes.markRemovable();
292 // -----------------------------------------------------------------------------
294 void BinaryReadHandler::readGroup(rtl::OUString &_aName, node::Attributes &_aAttributes)
295 SAL_THROW( (io::IOException, uno::RuntimeException) )
297 readAttributes(_aAttributes);
298 readName(_aName);
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);
306 readName(_aName);
307 readName(_sInstanceName);
308 readName(_sInstanceModule);
311 // -----------------------------------------------------------------------------
312 template <class T>
313 inline
314 void readAsAny(BinaryReader& rBinaryReader, uno::Any & _aValue, uno::Type& _aType, T& _aVar)
315 SAL_THROW( (io::IOException, uno::RuntimeException) )
317 rBinaryReader.read(_aVar);
318 _aValue <<= _aVar;
319 _aType = _aValue.getValueType();
322 // -----------------------------------------------------------------------------
323 uno::Type convertValueTypeToType(binary::ValueFlags::Type eBasicValueType, bool bSeq)
325 uno::Type aType;
327 if (!bSeq)
329 switch(eBasicValueType)
331 // --------------- Simple types ---------------
333 case binary::ValueFlags::val_boolean:
334 aType = SimpleTypeHelper::getBooleanType();
335 break;
336 case binary::ValueFlags::val_int16:
337 aType = SimpleTypeHelper::getShortType();
338 break;
339 case binary::ValueFlags::val_int32:
340 aType = SimpleTypeHelper::getIntType();
341 break;
342 case binary::ValueFlags::val_int64:
343 aType = SimpleTypeHelper::getLongType();
344 break;
345 case binary::ValueFlags::val_double:
346 aType = SimpleTypeHelper::getDoubleType();
347 break;
348 case binary::ValueFlags::val_string:
349 aType = SimpleTypeHelper::getStringType();
350 break;
351 case binary::ValueFlags::val_binary:
352 aType = SimpleTypeHelper::getBinaryType();
353 break;
354 case binary::ValueFlags::val_any:
355 aType = SimpleTypeHelper::getAnyType();
356 break;
357 default:
358 OSL_ENSURE(false,"Invalid value type");
359 break;
362 else
364 // ------------ Sequences ------------
365 switch(eBasicValueType)
367 case binary::ValueFlags::val_boolean:
368 aType = ::getCppuType(static_cast<uno::Sequence<sal_Bool> const*>(0));
369 break;
370 case binary::ValueFlags::val_int16:
371 aType = ::getCppuType(static_cast<uno::Sequence<sal_Int16> const*>(0));
372 break;
373 case binary::ValueFlags::val_int32:
374 aType = ::getCppuType(static_cast<uno::Sequence<sal_Int32> const*>(0));
375 break;
376 case binary::ValueFlags::val_int64:
377 aType = ::getCppuType(static_cast<uno::Sequence<sal_Int64> const*>(0));
378 break;
379 case binary::ValueFlags::val_double:
380 aType = ::getCppuType(static_cast<uno::Sequence<double> const*>(0));
381 break;
382 case binary::ValueFlags::val_string:
383 aType = ::getCppuType(static_cast<uno::Sequence<rtl::OUString> const*>(0));
384 break;
385 case binary::ValueFlags::val_binary:
386 aType = ::getCppuType(static_cast<uno::Sequence< uno::Sequence< sal_Int8 > > const*>(0));
387 break;
388 default:
389 OSL_ENSURE(false,"Invalid sequence value type");
390 break;
394 return aType;
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) )
402 bool bSeq = false;
403 bool bHasValue = false;
404 bool bHasDefault = false;
406 binary::ValueFlags::Type eBasicType = readValueFlags(bSeq, bHasValue, bHasDefault);
407 readAttributes(_aAttributes);
408 readName(_aName);
410 if (!bSeq && (bHasValue || bHasDefault))
412 switch(eBasicType)
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:
421 rtl::OUString aStr;
422 if (bHasValue)
423 readAsAny(m_BinaryReader, _aValue, _aType, aStr);
424 if (bHasDefault)
425 readAsAny(m_BinaryReader, _aDefaultValue, _aType, aStr);
426 break;
428 case binary::ValueFlags::val_boolean:
430 sal_Bool nValue;
431 if (bHasValue)
432 readAsAny(m_BinaryReader,_aValue, _aType, nValue);
433 if (bHasDefault)
434 readAsAny(m_BinaryReader,_aDefaultValue, _aType, nValue);
435 break;
437 case binary::ValueFlags::val_int16:
439 sal_Int16 nValue;
440 if (bHasValue)
441 readAsAny(m_BinaryReader,_aValue, _aType, nValue);
442 if (bHasDefault)
443 readAsAny(m_BinaryReader,_aDefaultValue, _aType, nValue);
444 break;
446 case binary::ValueFlags::val_int32:
448 sal_Int32 nValue;
449 if (bHasValue)
450 readAsAny(m_BinaryReader,_aValue, _aType, nValue);
451 if (bHasDefault)
452 readAsAny(m_BinaryReader,_aDefaultValue, _aType, nValue);
453 break;
455 case binary::ValueFlags::val_int64:
457 sal_Int64 nValue;
458 if (bHasValue)
459 readAsAny(m_BinaryReader,_aValue, _aType, nValue);
460 if (bHasDefault)
461 readAsAny(m_BinaryReader,_aDefaultValue, _aType, nValue);
462 break;
464 case binary::ValueFlags::val_double:
466 double nValue;
467 if (bHasValue)
468 readAsAny(m_BinaryReader,_aValue, _aType, nValue);
469 if (bHasDefault)
470 readAsAny(m_BinaryReader, _aDefaultValue, _aType, nValue);
471 break;
473 case binary::ValueFlags::val_binary:
475 uno::Sequence< sal_Int8 > aValue;
476 if (bHasValue)
477 readAsAny(m_BinaryReader,_aValue, _aType, aValue);
478 if (bHasDefault)
479 readAsAny(m_BinaryReader,_aDefaultValue, _aType, aValue);
480 break;
482 default:
483 OSL_ENSURE(false, "Invalid value type");
484 throw io::WrongFormatException();
487 else
489 _aType = convertValueTypeToType(eBasicType, bSeq);
490 if (_aType == uno::Type())
491 throw io::WrongFormatException();
494 if(bSeq)
496 OSL_ASSERT(_aType.getTypeClass() == uno::TypeClass_SEQUENCE);
497 uno::Type const aElementType = getSequenceElementType(_aType);
498 if (bHasValue)
499 readSequenceValue(m_BinaryReader, _aValue, aElementType );
501 if(bHasDefault)
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;
543 rtl::OUString aName;
544 node::Attributes aAttributes;
545 const bool not_extensible = false;
547 binary::NodeType::Type eType = this->readNodeType();
548 switch (eType)
550 case binary::NodeType::groupnode:
552 this->readGroup(aName, aAttributes);
553 pTree = m_aNodeFactory.createGroup(aName,not_extensible,aAttributes);
554 break;
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);
561 break;
563 case binary::NodeType::nodata:
564 break;
566 default:
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");
580 return pTree;
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())
595 return false;
597 if(!this->verifyFileHeader(pLayers, nNumLayers, _aSchemaVersion, aRequestedLocale, outKnownLocales))
598 return false;
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);
605 if (xTimeStamp.is())
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())
620 rtl::OUString aName;
621 node::Attributes aAttributes;
622 const bool not_extensible = false;
623 switch (eType)
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");
633 continue;
636 readChildren( *pNewNode );
637 rTree.addChild(base_ptr(pNewNode));
638 break;
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");
649 continue;
652 readChildren( *pNewSetNode );
653 rTree.addChild(base_ptr(pNewSetNode));
654 break;
656 case binary::NodeType::valuenode:
658 uno::Any aValue;
659 uno::Any aDefaultValue;
660 uno::Type aType;
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);
671 else
673 pValueNode = rValueFactory.createNullValueNode(aName,aType, aAttributes);
676 rTree.addChild(base_ptr(pValueNode));
677 break;
679 default:
680 OSL_ENSURE(false, "Binary cache: Invalid node type");
681 throw io::WrongFormatException();
685 // -----------------------------------------------------------------------------
687 // -----------------------------------------------------------------------------
689 // -----------------------------------------------------------------------------