diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2013-01-31 19:06:09 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2013-01-31 19:09:24 +0100 |
commit | 7a9fed14d45ba99d5639d4cc80286ee146b8d40a (patch) | |
tree | 8e25391af962166faac3dd90e187b1fd5535c6db /cppuhelper | |
parent | d9a18176d6b56119aa91699cd3aa102e36a7805c (diff) |
WIP: Experimental new binary type.rdb format
cppuhelper/source/typedescriptionprovider.cxx would read it if it finds .rdb
files in that format.
Throwaway new reg2bin tool for now can translate existing .rdb files into the
new format.
Change-Id: Iacf219c30cfc358c3d31fb0d73966cf2296a4fe5
Diffstat (limited to 'cppuhelper')
-rw-r--r-- | cppuhelper/source/typedescriptionprovider.cxx | 3067 |
1 files changed, 3046 insertions, 21 deletions
diff --git a/cppuhelper/source/typedescriptionprovider.cxx b/cppuhelper/source/typedescriptionprovider.cxx index 17e447f6f80d..ef9a0e3102fd 100644 --- a/cppuhelper/source/typedescriptionprovider.cxx +++ b/cppuhelper/source/typedescriptionprovider.cxx @@ -10,37 +10,3040 @@ #include "sal/config.h" #include <cassert> +#include <cstring> +#include <set> +#include <stack> #include <vector> +#include "boost/noncopyable.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" #include "com/sun/star/container/XHierarchicalNameAccess.hpp" #include "com/sun/star/lang/XInitialization.hpp" #include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/reflection/InvalidTypeNameException.hpp" +#include "com/sun/star/reflection/NoSuchTypeNameException.hpp" +#include "com/sun/star/reflection/TypeDescriptionSearchDepth.hpp" +#include "com/sun/star/reflection/XConstantTypeDescription.hpp" +#include "com/sun/star/reflection/XConstantsTypeDescription.hpp" +#include "com/sun/star/reflection/XEnumTypeDescription.hpp" +#include "com/sun/star/reflection/XIndirectTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XModuleTypeDescription.hpp" +#include "com/sun/star/reflection/XPublished.hpp" +#include "com/sun/star/reflection/XServiceTypeDescription2.hpp" +#include "com/sun/star/reflection/XSingletonTypeDescription2.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/reflection/XTypeDescriptionEnumeration.hpp" +#include "com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp" #include "com/sun/star/registry/InvalidRegistryException.hpp" #include "com/sun/star/registry/XSimpleRegistry.hpp" +#include "com/sun/star/uno/Any.hxx" #include "com/sun/star/uno/DeploymentException.hpp" #include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" #include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/TypeClass.hpp" #include "com/sun/star/uno/XComponentContext.hpp" #include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/compbase2.hxx" +#include "cppuhelper/implbase1.hxx" +#include "osl/file.h" #include "osl/file.hxx" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" #include "rtl/ustring.hxx" +#include "sal/log.hxx" +#include "sal/types.h" +#include "salhelper/simplereferenceobject.hxx" #include "paths.hxx" #include "typedescriptionprovider.hxx" +// New binary format: +// +// Uses the following definitions: +// +// * UInt16: 2-byte value, LSB first +// * UInt32: 4-byte value, LSB first +// * UInt64: 8-byte value, LSB first +// * Offset: UInt32 value, counting bytes from start of file +// * NUL-Name: zero or more non-NUL US-ASCII bytes followed by a NUL byte +// * Len-Name: UInt32 number of characters followed by that many US-ASCII bytes +// * Entry: Offset of NUL-Name followed by Offset of payload +// * Map: zero or more Entries +// +// Layout of per-entry payload in the root or a module Map: +// +// * kind byte: +// ** 0: module +// *** followed by: +// **** UInt32 number N1 of entries of Map +// **** N1 * Entry +// ** otherwise: +// *** 0x80 bit: 1 if published +// *** 0x40 bit: 1 if deprecated +// *** 0x20 bit: flag (may only be 1 for certain kinds, see below) +// *** remaining bits: +// **** 1: enum type +// ***** followed by: +// ****** UInt32 number N1 of members +// ****** N1 * tuple of: +// ******* Offset of Len-Name +// ******* UInt32 +// **** 2: plain struct type (with base if flag is 1) +// ***** followed by: +// ****** if "with base": Offset of Len-Name +// ****** UInt32 number N1 of direct members +// ****** N1 * tuple of: +// ******* Offset of Len-Name name +// ******* Offset of Len-Name type +// **** 3: polymorphic struct type template +// ***** followed by: +// ****** UInt32 number N1 of type parameters +// ****** N1 * Offset of Len-Name +// ****** UInt32 number N2 of members +// ****** N2 * tuple of: +// ******* kind byte: 0x01 bit is 1 if parameterized type +// ******* Offset of Len-Name name +// ******* Offset of Len-Name type +// **** 4: exception type (with base if flag is 1) +// ***** followed by: +// ****** if "with base": Offset of Len-Name +// ****** UInt32 number N1 of direct members +// ****** N1 * tuple of: +// ******* Offset of Len-Name name +// ******* Offset of Len-Name type +// **** 5: interface type +// ***** followed by: +// ****** UInt32 number N1 of direct mandatory bases +// ****** N1 * Offset of Len-Name +// ****** UInt32 number N2 of direct optional bases +// ****** N2 * Offset of Len-Name +// ****** UInt32 number N3 of direct attributes +// ****** N3 * tuple of: +// ******* kind byte: +// ******** 0x02 bit: 1 if read-only +// ******** 0x01 bit: 1 if bound +// ******* Offset of Len-Name name +// ******* Offset of Len-Name type +// ******* UInt32 number N4 of get exceptions +// ******* N4 * Offset of Len-Name +// ******* UInt32 number N5 of set exceptions +// ******* N5 * Offset of Len-Name +// ****** UInt32 number N6 of direct methods +// ****** N6 * tuple of: +// ******* Offset of Len-Name name +// ******* Offset of Len-Name return type +// ******* UInt32 number N7 of parameters +// ******* N7 * tuple of: +// ******** direction byte: 0 for in, 1 for out, 2 for in-out +// ******** Offset of Len-Name name +// ******** Offset of Len-Name type +// ******* UInt32 number N8 of exceptions +// ******* N8 * Offset of Len-Name +// **** 6: typedef +// ***** followed by: +// ****** Offset of Len-Name +// **** 7: constant group +// ***** followed by: +// ****** UInt32 number N1 of entries of Map +// ****** N1 * Entry +// **** 8: single-interface--based service (with default constructor if flag is +// 1) +// ***** followed by: +// ****** Offset of Len-Name +// ****** if not "with default constructor": +// ******* UInt32 number N1 of constructors +// ******* N1 * tuple of: +// ******** Offset of Len-Name +// ******** UInt32 number N2 of parameters +// ******** N2 * tuple of +// ********* kind byte: 0x04 bit is 1 if rest parameter +// ********* Offset of Len-Name name +// ********* Offset of Len-Name type +// ******** UInt32 number N3 of exceptions +// ******** N3 * Offset of Len-Name +// **** 9: accumulation-based service +// ***** followed by: +// ****** UInt32 number N1 of direct mandatory base services +// ****** N1 * Offset of Len-Name +// ****** UInt32 number N2 of direct optional base services +// ****** N2 * Offset of Len-Name +// ****** UInt32 number N3 of direct mandatory base interfaces +// ****** N3 * Offset of Len-Name +// ****** UInt32 number N4 of direct optional base interfaces +// ****** N4 * Offset of Len-Name +// ****** UInt32 number N5 of direct properties +// ****** N5 * tuple of: +// ******* UInt16 kind: +// ******** 0x0100 bit: 1 if optional +// ******** 0x0080 bit: 1 if removable +// ******** 0x0040 bit: 1 if maybedefault +// ******** 0x0020 bit: 1 if maybeambiguous +// ******** 0x0010 bit: 1 if readonly +// ******** 0x0008 bit: 1 if transient +// ******** 0x0004 bit: 1 if constrained +// ******** 0x0002 bit: 1 if bound +// ******** 0x0001 bit: 1 if maybevoid +// ******* Offset of Len-Name name +// ******* Offset of Len-Name type +// **** 10: interface-based singleton +// ***** followed by: +// ****** Offset of Len-Name +// **** 11: service-based singleton +// ***** followed by: +// ****** Offset of Len-Name +// +// Layout of per-entry payload in a constant group Map: +// +// * kind byte: +// ** 0x80 bit: 1 if deprecated +// ** remaining bits: +// *** 0: BOOLEAN +// **** followed by value byte, 0 represents false, 1 represents true +// *** 1: BYTE +// **** followed by value byte, representing values with two's complement +// *** 2: SHORT +// **** followed by UInt16 value, representing values with two's complement +// *** 3: UNSIGNED SHORT +// **** followed by UInt16 value +// *** 4: LONG +// **** followed by UInt32 value, representing values with two's complement +// *** 5: UNSIGNED LONG +// **** followed by UInt32 value +// *** 6: HYPER +// **** followed by UInt64 value, representing values with two's complement +// *** 7: UNSIGNED HYPER +// **** followed by UInt64 value +// *** 8: FLOAT +// **** followed by UInt32 value, representing values in IEEE-754 single +// precision format +// *** 9: DOUBLE +// **** followed by UInt64 value, representing values in IEEE-754 double +// precision format +// +// Memory layout: +// +// * 8 byte header "UNOIDL\0\xFF +// * Offset of root Map +// * UInt32 number of entries of root Map +// ... + namespace { -void readTypeRdbFile( - rtl::OUString const & uri, bool optional, +// sizeof (UInt16) == 2 +struct UInt16 { + unsigned char byte[2]; + + sal_uInt16 get() const { + return static_cast< sal_uInt16 >(byte[0]) + | (static_cast< sal_uInt16 >(byte[1]) << 8); + } +}; + +// sizeof (UInt32) == 4 +struct UInt32 { + unsigned char byte[4]; + + sal_uInt32 get() const { + return static_cast< sal_uInt32 >(byte[0]) + | (static_cast< sal_uInt32 >(byte[1]) << 8) + | (static_cast< sal_uInt32 >(byte[2]) << 16) + | (static_cast< sal_uInt32 >(byte[3]) << 24); + } +}; + +// sizeof (UInt64) == 8 +struct UInt64 { + unsigned char byte[8]; + + sal_uInt64 get() const { + return static_cast< sal_uInt64 >(byte[0]) + | (static_cast< sal_uInt64 >(byte[1]) << 8) + | (static_cast< sal_uInt64 >(byte[2]) << 16) + | (static_cast< sal_uInt64 >(byte[3]) << 24) + | (static_cast< sal_uInt64 >(byte[4]) << 32) + | (static_cast< sal_uInt64 >(byte[5]) << 40) + | (static_cast< sal_uInt64 >(byte[6]) << 48) + | (static_cast< sal_uInt64 >(byte[7]) << 56); + } +}; + +struct MappedFile: + public salhelper::SimpleReferenceObject, private boost::noncopyable +{ + explicit MappedFile(rtl::OUString const & fileUrl); + + sal_uInt8 read8(sal_uInt32 offset) const; + + sal_uInt16 read16(sal_uInt32 offset) const; + + sal_uInt32 read32(sal_uInt32 offset) const; + + sal_uInt64 read64(sal_uInt32 offset) const; + + rtl::OUString readNameNul(sal_uInt32 offset) const; + + rtl::OUString readNameLen(sal_uInt32 offset, sal_uInt32 * newOffset = 0) + const; + + oslFileHandle handle; + sal_uInt64 size; + void * address; + +private: + virtual ~MappedFile(); + + sal_uInt8 get8(sal_uInt32 offset) const; + + sal_uInt16 get16(sal_uInt32 offset) const; + + sal_uInt32 get32(sal_uInt32 offset) const; + + sal_uInt64 get64(sal_uInt32 offset) const; +}; + +MappedFile::MappedFile(rtl::OUString const & fileUrl) { + oslFileError e = osl_openFile( + fileUrl.pData, &handle, osl_File_OpenFlag_Read); + switch (e) { + case osl_File_E_None: + break; + case osl_File_E_NOENT: + throw css::container::NoSuchElementException( + fileUrl, css::uno::Reference< css::uno::XInterface >()); + default: + throw css::uno::RuntimeException( + "cannot open " + fileUrl + ": " + rtl::OUString::number(e), + css::uno::Reference< css::uno::XInterface >()); + } + e = osl_getFileSize(handle, &size); + if (e == osl_File_E_None) { + e = osl_mapFile( + handle, &address, size, 0, osl_File_MapFlag_RandomAccess); + } + if (e != osl_File_E_None) { + oslFileError e2 = osl_closeFile(handle); + SAL_WARN_IF( + e2 != osl_File_E_None, "cppuhelper", + "cannot close " << fileUrl << ": " << +e2); + throw css::uno::RuntimeException( + "cannot mmap " + fileUrl + ": " + rtl::OUString::number(e), + css::uno::Reference< css::uno::XInterface >()); + } +} + +sal_uInt8 MappedFile::read8(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 1) { + throw css::uno::DeploymentException( + "broken UNOIDL file: offset for 8-bit value too large", + css::uno::Reference< css::uno::XInterface >()); + } + return get8(offset); +} + +sal_uInt16 MappedFile::read16(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 2) { + throw css::uno::DeploymentException( + "broken UNOIDL file: offset for 16-bit value too large", + css::uno::Reference< css::uno::XInterface >()); + } + return get16(offset); +} + +sal_uInt32 MappedFile::read32(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 4) { + throw css::uno::DeploymentException( + "broken UNOIDL file: offset for 32-bit value too large", + css::uno::Reference< css::uno::XInterface >()); + } + return get32(offset); +} + +sal_uInt64 MappedFile::read64(sal_uInt32 offset) const { + assert(size >= 8); + if (offset > size - 8) { + throw css::uno::DeploymentException( + "broken UNOIDL file: offset for 64-bit value too large", + css::uno::Reference< css::uno::XInterface >()); + } + return get64(offset); +} + +rtl::OUString MappedFile::readNameNul(sal_uInt32 offset) const { + if (offset > size) { + throw css::uno::DeploymentException( + "broken UNOIDL file: offset for string too large", + css::uno::Reference< css::uno::XInterface >()); + } + sal_uInt64 end = offset; + for (;; ++end) { + if (end == size) { + throw css::uno::DeploymentException( + "broken UNOIDL file: string misses trailing NUL", + css::uno::Reference< css::uno::XInterface >()); + } + if (static_cast< char const * >(address)[end] == 0) { + break; + } + } + if (end - offset > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + "broken UNOIDL file: string too long", + css::uno::Reference< css::uno::XInterface >()); + } + rtl::OUString name; + if (!rtl_convertStringToUString( + &name.pData, static_cast< char const * >(address) + offset, + end - offset, RTL_TEXTENCODING_ASCII_US, + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + throw css::uno::DeploymentException( + "broken UNOIDL file: name is not ASCII", + css::uno::Reference< css::uno::XInterface >()); + } + return name; +} + +rtl::OUString MappedFile::readNameLen(sal_uInt32 offset, sal_uInt32 * newOffset) + const +{ + sal_uInt32 len = read32(offset); + if (len > SAL_MAX_INT32 || len > size - offset - 4) { + throw css::uno::DeploymentException( + "broken UNOIDL file: size of name is too large", + css::uno::Reference< css::uno::XInterface >()); + } + rtl::OUString name; + if (!rtl_convertStringToUString( + &name.pData, static_cast< char const * >(address) + offset + 4, len, + RTL_TEXTENCODING_ASCII_US, + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR + | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + throw css::uno::DeploymentException( + "broken UNOIDL file: name is not ASCII", + css::uno::Reference< css::uno::XInterface >()); + } + if (newOffset != 0) { + *newOffset = offset + 4 + len; + } + return name; +} + +MappedFile::~MappedFile() { + oslFileError e = osl_unmapMappedFile(handle, address, size); + SAL_WARN_IF(e != osl_File_E_None, "cppuhelper", "cannot unmap: " << +e); + e = osl_closeFile(handle); + SAL_WARN_IF(e != osl_File_E_None, "cppuhelper", "cannot close: " << +e); +} + +sal_uInt8 MappedFile::get8(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 1); + return static_cast< char const * >(address)[offset]; +} + +sal_uInt16 MappedFile::get16(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 2); + return reinterpret_cast< UInt16 const * >( + static_cast< char const * >(address) + offset)->get(); +} + +sal_uInt32 MappedFile::get32(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 4); + return reinterpret_cast< UInt32 const * >( + static_cast< char const * >(address) + offset)->get(); +} + +sal_uInt64 MappedFile::get64(sal_uInt32 offset) const { + assert(size >= 8); + assert(offset <= size - 8); + return reinterpret_cast< UInt64 const * >( + static_cast< char const * >(address) + offset)->get(); +} + +css::uno::Reference< css::reflection::XTypeDescription > resolve( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name) +{ + assert(context.is()); + try { + return css::uno::Reference< css::reflection::XTypeDescription >( + (css::uno::Reference< css::container::XHierarchicalNameAccess >( + context->getValueByName( + "/singletons/" + "com.sun.star.reflection.theTypeDescriptionManager"), + css::uno::UNO_QUERY_THROW)-> + getByHierarchicalName(name)), + css::uno::UNO_QUERY_THROW); + } catch (css::container::NoSuchElementException & e) { + throw css::uno::DeploymentException( + ("cannot resolve type \"" + name + "\"; NoSuchElementException: " + + e.Message), + e.Context); + } +} + +class PublishableDescription: + public cppu::WeakImplHelper1< css::reflection::XPublished >, + private boost::noncopyable +{ +protected: + PublishableDescription(bool published): published_(published) {} + + virtual ~PublishableDescription() {} + +private: + virtual sal_Bool SAL_CALL isPublished() throw (css::uno::RuntimeException) + { return published_; } + + bool published_; +}; + +class ModuleDescription: + public cppu::WeakImplHelper1< css::reflection::XModuleTypeDescription >, + private boost::noncopyable +{ +public: + ModuleDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, + std::vector< rtl::OUString > const & items): + context_(context), name_(name), items_(items) + {} + +private: + virtual ~ModuleDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_MODULE; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getMembers() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + std::vector< rtl::OUString > items_; +}; + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +ModuleDescription::getMembers() throw (css::uno::RuntimeException) { + assert(items_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(items_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = resolve(context_, name_ + "." + items_[i]); + } + return s; +} + +class EnumTypeDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XEnumTypeDescription > +{ +public: + struct Member { + Member(rtl::OUString const & theName, sal_Int32 theValue): + name(theName), value(theValue) + {} + + rtl::OUString name; + sal_Int32 value; + }; + + EnumTypeDescription( + rtl::OUString const & name, bool published, + std::vector< Member > const & members): + ImplInheritanceHelper1(published), name_(name), members_(members) + { assert(!members_.empty()); } + +private: + virtual ~EnumTypeDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_ENUM; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual sal_Int32 SAL_CALL getDefaultEnumValue() + throw (css::uno::RuntimeException) + { return members_[0].value; } + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getEnumNames() + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< sal_Int32 > SAL_CALL getEnumValues() + throw (css::uno::RuntimeException); + + rtl::OUString name_; + std::vector< Member > members_; +}; + +css::uno::Sequence< rtl::OUString > EnumTypeDescription::getEnumNames() + throw (css::uno::RuntimeException) +{ + assert(members_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(members_.size()); + css::uno::Sequence< rtl::OUString > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = members_[i].name; + } + return s; +} + +css::uno::Sequence< sal_Int32 > EnumTypeDescription::getEnumValues() + throw (css::uno::RuntimeException) +{ + assert(members_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(members_.size()); + css::uno::Sequence< sal_Int32 > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = members_[i].value; + } + return s; +} + +class PlainStructTypeDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XStructTypeDescription > +{ +public: + struct Member { + Member(rtl::OUString const & theName, rtl::OUString const & theType): + name(theName), type(theType) + {} + + rtl::OUString name; + rtl::OUString type; + }; + + PlainStructTypeDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, rtl::OUString const & base, + std::vector< Member > const & directMembers): + ImplInheritanceHelper1(published), context_(context), name_(name), + base_(base), directMembers_(directMembers) + {} + +private: + virtual ~PlainStructTypeDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_STRUCT; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getBaseType() throw (css::uno::RuntimeException) { + return base_.isEmpty() + ? css::uno::Reference< css::reflection::XTypeDescription >() + : resolve(context_, base_); + } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getMemberTypes() throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getMemberNames() + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getTypeParameters() + throw (css::uno::RuntimeException) + { return css::uno::Sequence< rtl::OUString >(); } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getTypeArguments() throw (css::uno::RuntimeException) { + return css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > >(); + } + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + rtl::OUString base_; + std::vector< Member > directMembers_; +}; + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +PlainStructTypeDescription::getMemberTypes() throw (css::uno::RuntimeException) +{ + assert(directMembers_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(directMembers_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = resolve(context_, directMembers_[i].type); + } + return s; +} + +css::uno::Sequence< rtl::OUString > PlainStructTypeDescription::getMemberNames() + throw (css::uno::RuntimeException) +{ + assert(directMembers_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(directMembers_.size()); + css::uno::Sequence< rtl::OUString > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = directMembers_[i].name; + } + return s; +} + +class ParameterizedMemberTypeDescription: + public cppu::WeakImplHelper1< css::reflection::XTypeDescription >, + private boost::noncopyable +{ +public: + explicit ParameterizedMemberTypeDescription( + rtl::OUString const & typeParameterName): + typeParameterName_(typeParameterName) + {} + +private: + virtual ~ParameterizedMemberTypeDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_UNKNOWN; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return typeParameterName_; } + + rtl::OUString typeParameterName_; +}; + +class PolymorphicStructTypeTemplateDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XStructTypeDescription > +{ +public: + struct Member { + Member( + rtl::OUString const & theName, rtl::OUString const & theType, + bool theParameterized): + name(theName), type(theType), parameterized(theParameterized) + {} + + rtl::OUString name; + rtl::OUString type; + bool parameterized; + }; + + PolymorphicStructTypeTemplateDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, + std::vector< rtl::OUString > const & typeParameters, + std::vector< Member > const & members): + ImplInheritanceHelper1(published), context_(context), name_(name), + typeParameters_(typeParameters), members_(members) + {} + +private: + virtual ~PolymorphicStructTypeTemplateDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_STRUCT; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getBaseType() throw (css::uno::RuntimeException) + { return css::uno::Reference< css::reflection::XTypeDescription >(); } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getMemberTypes() throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getMemberNames() + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getTypeParameters() + throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getTypeArguments() throw (css::uno::RuntimeException) { + return css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > >(); + } + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + std::vector< rtl::OUString > typeParameters_; + std::vector< Member > members_; +}; + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +PolymorphicStructTypeTemplateDescription::getMemberTypes() + throw (css::uno::RuntimeException) +{ + assert(members_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(members_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = members_[i].parameterized + ? new ParameterizedMemberTypeDescription(members_[i].type) + : resolve(context_, members_[i].type); + } + return s; +} + +css::uno::Sequence< rtl::OUString > +PolymorphicStructTypeTemplateDescription::getMemberNames() + throw (css::uno::RuntimeException) +{ + assert(members_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(members_.size()); + css::uno::Sequence< rtl::OUString > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = members_[i].name; + } + return s; +} + +css::uno::Sequence< rtl::OUString > +PolymorphicStructTypeTemplateDescription::getTypeParameters() + throw (css::uno::RuntimeException) +{ + assert(typeParameters_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(typeParameters_.size()); + css::uno::Sequence< rtl::OUString > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = typeParameters_[i]; + } + return s; +} + +class ExceptionTypeDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XCompoundTypeDescription > +{ +public: + struct Member { + Member(rtl::OUString const & theName, rtl::OUString const & theType): + name(theName), type(theType) + {} + + rtl::OUString name; + rtl::OUString type; + }; + + ExceptionTypeDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, rtl::OUString const & base, + std::vector< Member > const & directMembers): + ImplInheritanceHelper1(published), context_(context), name_(name), + base_(base), directMembers_(directMembers) + {} + +private: + virtual ~ExceptionTypeDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_EXCEPTION; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getBaseType() throw (css::uno::RuntimeException) { + return base_.isEmpty() + ? css::uno::Reference< css::reflection::XTypeDescription >() + : resolve(context_, base_); + } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getMemberTypes() throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getMemberNames() + throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + rtl::OUString base_; + std::vector< Member > directMembers_; +}; + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +ExceptionTypeDescription::getMemberTypes() throw (css::uno::RuntimeException) { + assert(directMembers_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(directMembers_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = resolve(context_, directMembers_[i].type); + } + return s; +} + +css::uno::Sequence< rtl::OUString > ExceptionTypeDescription::getMemberNames() + throw (css::uno::RuntimeException) +{ + assert(directMembers_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(directMembers_.size()); + css::uno::Sequence< rtl::OUString > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = directMembers_[i].name; + } + return s; +} + +css::uno::Reference< css::reflection::XTypeDescription > resolveTypedefs( + css::uno::Reference< css::reflection::XTypeDescription > const & type) +{ + css::uno::Reference< css::reflection::XTypeDescription > resolved(type); + while (resolved->getTypeClass() == css::uno::TypeClass_TYPEDEF) { + resolved + = (css::uno::Reference< css::reflection::XIndirectTypeDescription >( + resolved, css::uno::UNO_QUERY_THROW)-> + getReferencedType()); + } + return resolved; +} + +class BaseOffset: private boost::noncopyable { +public: + BaseOffset( + css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > + const & description); + + sal_Int32 get() const { return offset_; } + +private: + void calculateBases( + css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > + const & description); + + void calculate( + css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > + const & description); + + std::set< rtl::OUString > set_; + sal_Int32 offset_; +}; + +BaseOffset::BaseOffset( + css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > const & + description): + offset_(0) +{ + calculateBases(description); +} + +void BaseOffset::calculateBases( + css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > const & + description) +{ + css::uno::Sequence< + css::uno::Reference < css::reflection::XTypeDescription > > bases( + description->getBaseTypes()); + for (sal_Int32 i = 0; i != bases.getLength(); ++i) { + calculate( + css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >( + resolveTypedefs(bases[i]), css::uno::UNO_QUERY_THROW)); + } +} + +void BaseOffset::calculate( + css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > const & + description) +{ + if (set_.insert(description->getName()).second) { + calculateBases(description); + offset_ += description->getMembers().getLength(); + } +} + +struct Attribute { + Attribute( + rtl::OUString const & theName, rtl::OUString const & theType, + bool theBound, bool theReadOnly, + std::vector< rtl::OUString > const & theGetExceptions, + std::vector< rtl::OUString > const & theSetExceptions): + name(theName), type(theType), bound(theBound), readOnly(theReadOnly), + getExceptions(theGetExceptions), setExceptions(theSetExceptions) + {} + + rtl::OUString name; + rtl::OUString type; + bool bound; + bool readOnly; + std::vector< rtl::OUString > getExceptions; + std::vector< rtl::OUString > setExceptions; +}; + +class AttributeDescription: + public cppu::WeakImplHelper1< + css::reflection::XInterfaceAttributeTypeDescription2 >, + private boost::noncopyable +{ +public: + AttributeDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, Attribute attribute, sal_Int32 position): + context_(context), name_(name), attribute_(attribute), + position_(position) + {} + +private: + virtual ~AttributeDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_INTERFACE_ATTRIBUTE; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual rtl::OUString SAL_CALL getMemberName() + throw (css::uno::RuntimeException) + { return attribute_.name; } + + virtual sal_Int32 SAL_CALL getPosition() throw (css::uno::RuntimeException) + { return position_; } + + virtual sal_Bool SAL_CALL isReadOnly() throw (css::uno::RuntimeException) + { return attribute_.readOnly; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getType() throw (css::uno::RuntimeException) + { return resolve(context_, attribute_.type); } + + virtual sal_Bool SAL_CALL isBound() throw (css::uno::RuntimeException) + { return attribute_.bound; } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > + SAL_CALL getGetExceptions() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > + SAL_CALL getSetExceptions() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + Attribute attribute_; + sal_Int32 position_; +}; + +css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > +AttributeDescription::getGetExceptions() throw (css::uno::RuntimeException) { + assert(attribute_.getExceptions.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(attribute_.getExceptions.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i].set( + resolve(context_, attribute_.getExceptions[i]), + css::uno::UNO_QUERY_THROW); + } + return s; +} + +css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > +AttributeDescription::getSetExceptions() throw (css::uno::RuntimeException) { + assert(attribute_.setExceptions.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(attribute_.setExceptions.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i].set( + resolve(context_, attribute_.setExceptions[i]), + css::uno::UNO_QUERY_THROW); + } + return s; +} + +struct Method { + struct Parameter { + enum Direction { DIRECTION_IN, DIRECTION_OUT, DIRECTION_IN_OUT }; + + Parameter( + rtl::OUString const & theName, rtl::OUString const & theType, + Direction theDirection): + name(theName), type(theType), direction(theDirection) + {} + + rtl::OUString name; + rtl::OUString type; + Direction direction; + }; + + Method( + rtl::OUString const & theName, rtl::OUString const & theReturnType, + std::vector< Parameter > const & theParameters, + std::vector< rtl::OUString > const & theExceptions): + name(theName), returnType(theReturnType), parameters(theParameters), + exceptions(theExceptions) + {} + + rtl::OUString name; + rtl::OUString returnType; + std::vector< Parameter > parameters; + std::vector< rtl::OUString > exceptions; +}; + +class MethodParameter: + public cppu::WeakImplHelper1< css::reflection::XMethodParameter >, + private boost::noncopyable +{ +public: + MethodParameter( + css::uno::Reference< css::uno::XComponentContext > const & context, + Method::Parameter parameter, sal_Int32 position): + context_(context), parameter_(parameter), position_(position) + {} + +private: + virtual ~MethodParameter() {} + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return parameter_.name; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getType() throw (css::uno::RuntimeException) + { return resolve(context_, parameter_.type); } + + virtual sal_Bool SAL_CALL isIn() throw (css::uno::RuntimeException) { + return parameter_.direction == Method::Parameter::DIRECTION_IN + || parameter_.direction == Method::Parameter::DIRECTION_IN_OUT; + } + + virtual sal_Bool SAL_CALL isOut() throw (css::uno::RuntimeException) { + return parameter_.direction == Method::Parameter::DIRECTION_OUT + || parameter_.direction == Method::Parameter::DIRECTION_IN_OUT; + } + + virtual sal_Int32 SAL_CALL getPosition() throw (css::uno::RuntimeException) + { return position_; } + + css::uno::Reference< css::uno::XComponentContext > context_; + Method::Parameter parameter_; + sal_Int32 position_; +}; + +class MethodDescription: + public cppu::WeakImplHelper1< + css::reflection::XInterfaceMethodTypeDescription >, + private boost::noncopyable +{ +public: + MethodDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, Method method, sal_Int32 position): + context_(context), name_(name), method_(method), position_(position) + {} + +private: + virtual ~MethodDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_INTERFACE_METHOD; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual rtl::OUString SAL_CALL getMemberName() + throw (css::uno::RuntimeException) + { return method_.name; } + + virtual sal_Int32 SAL_CALL getPosition() throw (css::uno::RuntimeException) + { return position_; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getReturnType() throw (css::uno::RuntimeException) + { return resolve(context_, method_.returnType); } + + virtual sal_Bool SAL_CALL isOneway() throw (css::uno::RuntimeException) + { return false; } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XMethodParameter > > + SAL_CALL getParameters() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getExceptions() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + Method method_; + sal_Int32 position_; +}; + +css::uno::Sequence< css::uno::Reference< css::reflection::XMethodParameter > > +MethodDescription::getParameters() throw (css::uno::RuntimeException) { + assert(method_.parameters.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(method_.parameters.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XMethodParameter > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = new MethodParameter(context_, method_.parameters[i], i); + } + return s; +} + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +MethodDescription::getExceptions() throw (css::uno::RuntimeException) { + assert(method_.exceptions.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(method_.exceptions.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = resolve(context_, method_.exceptions[i]); + } + return s; +} + +class InterfaceTypeDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XInterfaceTypeDescription2 > +{ +public: + InterfaceTypeDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, + std::vector< rtl::OUString > const & mandatoryDirectBases, + std::vector< rtl::OUString > const & optionalDirectBases, + std::vector< Attribute > const & directAttributes, + std::vector< Method > const & directMethods): + ImplInheritanceHelper1(published), context_(context), name_(name), + mandatoryDirectBases_(mandatoryDirectBases), + optionalDirectBases_(optionalDirectBases), + directAttributes_(directAttributes), directMethods_(directMethods) + {} + +private: + virtual ~InterfaceTypeDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_INTERFACE; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getBaseType() throw (css::uno::RuntimeException) { + return mandatoryDirectBases_.empty() + ? css::uno::Reference< css::reflection::XTypeDescription >() + : resolve(context_, mandatoryDirectBases_[0]); + } + + virtual css::uno::Uik SAL_CALL getUik() throw (css::uno::RuntimeException) + { return css::uno::Uik(); } + + virtual + css::uno::Sequence< + css::uno::Reference< + css::reflection::XInterfaceMemberTypeDescription > > + SAL_CALL getMembers() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getBaseTypes() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + SAL_CALL getOptionalBaseTypes() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + std::vector< rtl::OUString > mandatoryDirectBases_; + std::vector< rtl::OUString > optionalDirectBases_; + std::vector< Attribute > directAttributes_; + std::vector< Method > directMethods_; +}; + +css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceMemberTypeDescription > > +InterfaceTypeDescription::getMembers() throw (css::uno::RuntimeException) { + assert( + directAttributes_.size() <= SAL_MAX_INT32 + && directMethods_.size() <= SAL_MAX_INT32 - directAttributes_.size()); + sal_Int32 n1 = static_cast< sal_Int32 >(directAttributes_.size()); + sal_Int32 n2 = static_cast< sal_Int32 >(directMethods_.size()); + css::uno::Sequence< + css::uno::Reference< + css::reflection::XInterfaceMemberTypeDescription > > s(n1 + n2); + sal_Int32 off = BaseOffset(this).get(); + for (sal_Int32 i = 0; i != n1; ++i) { + s[i] = new AttributeDescription( + context_, name_ + "::" + directAttributes_[i].name, + directAttributes_[i], off + i); + } + for (sal_Int32 i = 0; i != n2; ++i) { + s[n1 + i] = new MethodDescription( + context_, name_ + "::" + directMethods_[i].name, + directMethods_[i], off + n1 + i); + } + return s; +} + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +InterfaceTypeDescription::getBaseTypes() throw (css::uno::RuntimeException) { + assert(mandatoryDirectBases_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(mandatoryDirectBases_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = resolve(context_, mandatoryDirectBases_[i]); + } + return s; +} + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +InterfaceTypeDescription::getOptionalBaseTypes() + throw (css::uno::RuntimeException) +{ + assert(optionalDirectBases_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(optionalDirectBases_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = resolve(context_, optionalDirectBases_[i]); + } + return s; +} + +class ConstantDescription: + public cppu::WeakImplHelper1< css::reflection::XConstantTypeDescription >, + private boost::noncopyable +{ +public: + ConstantDescription( + rtl::OUString const & name, css::uno::Any const & value): + name_(name), value_(value) + {} + +private: + virtual ~ConstantDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_CONSTANT; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual css::uno::Any SAL_CALL getConstantValue() + throw (css::uno::RuntimeException) + { return value_; } + + rtl::OUString name_; + css::uno::Any value_; +}; + +class ConstantGroupDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XConstantsTypeDescription > +{ +public: + ConstantGroupDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, + std::vector< rtl::OUString > const & constants): + ImplInheritanceHelper1(published), context_(context), name_(name), + constants_(constants) + {} + +private: + virtual ~ConstantGroupDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_CONSTANTS; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XConstantTypeDescription > > + SAL_CALL getConstants() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + std::vector< rtl::OUString > constants_; +}; + +css::uno::Sequence< + css::uno::Reference< css::reflection::XConstantTypeDescription > > +ConstantGroupDescription::getConstants() throw (css::uno::RuntimeException) { + assert(constants_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(constants_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XConstantTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i].set( + resolve(context_, name_ + "." + constants_[i]), + css::uno::UNO_QUERY_THROW); + } + return s; +} + +class TypedefDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XIndirectTypeDescription > +{ +public: + TypedefDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, rtl::OUString const & type): + ImplInheritanceHelper1(published), context_(context), name_(name), + type_(type) + {} + +private: + virtual ~TypedefDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_TYPEDEF; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getReferencedType() throw (css::uno::RuntimeException) + { return resolve(context_, type_); } + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + rtl::OUString type_; +}; + +struct Constructor { + struct Parameter { + Parameter( + rtl::OUString const & theName, rtl::OUString const & theType, + bool theRest): + name(theName), type(theType), rest(theRest) + {} + + rtl::OUString name; + rtl::OUString type; + bool rest; + }; + + Constructor(): defaultConstructor(true) {} + + Constructor( + rtl::OUString const & theName, + std::vector< Parameter > const & theParameters, + std::vector< rtl::OUString > const & theExceptions): + defaultConstructor(false), name(theName), parameters(theParameters), + exceptions(theExceptions) + {} + + bool defaultConstructor; + rtl::OUString name; + std::vector< Parameter > parameters; + std::vector< rtl::OUString > exceptions; +}; + +class ConstructorParameter: + public cppu::WeakImplHelper1< css::reflection::XParameter >, + private boost::noncopyable +{ +public: + ConstructorParameter( + css::uno::Reference< css::uno::XComponentContext > const & context, + Constructor::Parameter parameter, sal_Int32 position): + context_(context), parameter_(parameter), position_(position) + {} + +private: + virtual ~ConstructorParameter() {} + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return parameter_.name; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getType() throw (css::uno::RuntimeException) + { return resolve(context_, parameter_.type); } + + virtual sal_Bool SAL_CALL isIn() throw (css::uno::RuntimeException) + { return true; } + + virtual sal_Bool SAL_CALL isOut() throw (css::uno::RuntimeException) + { return false; } + + virtual sal_Int32 SAL_CALL getPosition() throw (css::uno::RuntimeException) + { return position_; } + + virtual sal_Bool SAL_CALL isRestParameter() + throw (css::uno::RuntimeException) + { return parameter_.rest; } + + css::uno::Reference< css::uno::XComponentContext > context_; + Constructor::Parameter parameter_; + sal_Int32 position_; +}; + +class ConstructorDescription: + public cppu::WeakImplHelper1< + css::reflection::XServiceConstructorDescription >, + private boost::noncopyable +{ +public: + ConstructorDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + Constructor const & constructor): + context_(context), constructor_(constructor) + {} + +private: + virtual ~ConstructorDescription() {} + + virtual sal_Bool SAL_CALL isDefaultConstructor() + throw (css::uno::RuntimeException) + { return constructor_.defaultConstructor; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return constructor_.name; } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XParameter > > + SAL_CALL getParameters() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > + SAL_CALL getExceptions() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; + Constructor constructor_; +}; + +css::uno::Sequence< css::uno::Reference< css::reflection::XParameter > > +ConstructorDescription::getParameters() throw (css::uno::RuntimeException) { + assert(constructor_.parameters.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(constructor_.parameters.size()); + css::uno::Sequence< css::uno::Reference< css::reflection::XParameter > > s( + n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = new ConstructorParameter( + context_, constructor_.parameters[i], i); + } + return s; +} + +css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > +ConstructorDescription::getExceptions() throw (css::uno::RuntimeException) { + assert(constructor_.exceptions.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(constructor_.exceptions.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i].set( + resolve(context_, constructor_.exceptions[i]), + css::uno::UNO_QUERY_THROW); + } + return s; +} + +class SingleInterfaceBasedServiceDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XServiceTypeDescription2 > +{ +public: + SingleInterfaceBasedServiceDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, rtl::OUString const & type, + std::vector< Constructor > const & constructors): + ImplInheritanceHelper1(published), context_(context), name_(name), + type_(type), constructors_(constructors) + {} + +private: + virtual ~SingleInterfaceBasedServiceDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_SERVICE; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > > + SAL_CALL getMandatoryServices() throw (css::uno::RuntimeException) + { + return css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > >(); + } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > > + SAL_CALL getOptionalServices() throw (css::uno::RuntimeException) + { + return css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > >(); + } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceTypeDescription > > + SAL_CALL getMandatoryInterfaces() throw (css::uno::RuntimeException) + { + return css::uno::Sequence< + css::uno::Reference< + css::reflection::XInterfaceTypeDescription > >(); + } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceTypeDescription > > + SAL_CALL getOptionalInterfaces() throw (css::uno::RuntimeException) + { + return css::uno::Sequence< + css::uno::Reference< + css::reflection::XInterfaceTypeDescription > >(); + } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XPropertyTypeDescription > > + SAL_CALL getProperties() throw (css::uno::RuntimeException) + { + return css::uno::Sequence< + css::uno::Reference< + css::reflection::XPropertyTypeDescription > >(); + } + + virtual sal_Bool SAL_CALL isSingleInterfaceBased() + throw (css::uno::RuntimeException) + { return true; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getInterface() throw (css::uno::RuntimeException) + { return resolve(context_, type_); } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceConstructorDescription > > + SAL_CALL getConstructors() throw (css::uno::RuntimeException); + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + rtl::OUString type_; + std::vector< Constructor > constructors_; +}; + +css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceConstructorDescription > > +SingleInterfaceBasedServiceDescription::getConstructors() + throw (css::uno::RuntimeException) +{ + assert(constructors_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(constructors_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceConstructorDescription > > + s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = new ConstructorDescription(context_, constructors_[i]); + } + return s; +} + +struct Property { + Property( + rtl::OUString const & theName, rtl::OUString const & theType, + sal_uInt16 theAttributes): + name(theName), type(theType), attributes(theAttributes) + {} + + rtl::OUString name; + rtl::OUString type; + sal_Int16 attributes; +}; + +class PropertyDescription: + public cppu::WeakImplHelper1< css::reflection::XPropertyTypeDescription >, + private boost::noncopyable +{ +public: + PropertyDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + Property const & property): + context_(context), property_(property) + {} + +private: + virtual ~PropertyDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_PROPERTY; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return property_.name; } + + virtual sal_Int16 SAL_CALL getPropertyFlags() + throw (css::uno::RuntimeException) + { return property_.attributes; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getPropertyTypeDescription() throw (css::uno::RuntimeException) + { return resolve(context_, property_.type); } + + css::uno::Reference< css::uno::XComponentContext > context_; + Property property_; +}; + +class AccumulationBasedServiceDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XServiceTypeDescription2 > +{ +public: + AccumulationBasedServiceDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, + std::vector< rtl::OUString > const & mandatoryDirectBaseServices, + std::vector< rtl::OUString > const & optionalDirectBaseServices, + std::vector< rtl::OUString > const & mandatoryDirectBaseInterfaces, + std::vector< rtl::OUString > const & optionalDirectBaseInterfaces, + std::vector< Property > const & directProperties): + ImplInheritanceHelper1(published), context_(context), name_(name), + mandatoryDirectBaseServices_(mandatoryDirectBaseServices), + optionalDirectBaseServices_(optionalDirectBaseServices), + mandatoryDirectBaseInterfaces_(mandatoryDirectBaseInterfaces), + optionalDirectBaseInterfaces_(optionalDirectBaseInterfaces), + directProperties_(directProperties) + {} + +private: + virtual ~AccumulationBasedServiceDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_SERVICE; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > > + SAL_CALL getMandatoryServices() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > > + SAL_CALL getOptionalServices() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceTypeDescription > > + SAL_CALL getMandatoryInterfaces() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceTypeDescription > > + SAL_CALL getOptionalInterfaces() throw (css::uno::RuntimeException); + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XPropertyTypeDescription > > + SAL_CALL getProperties() throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isSingleInterfaceBased() + throw (css::uno::RuntimeException) + { return false; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getInterface() throw (css::uno::RuntimeException) + { return css::uno::Reference< css::reflection::XTypeDescription >(); } + + virtual + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceConstructorDescription > > + SAL_CALL getConstructors() throw (css::uno::RuntimeException) + { + return css::uno::Sequence< + css::uno::Reference< + css::reflection::XServiceConstructorDescription > >(); + } + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + std::vector< rtl::OUString > mandatoryDirectBaseServices_; + std::vector< rtl::OUString > optionalDirectBaseServices_; + std::vector< rtl::OUString > mandatoryDirectBaseInterfaces_; + std::vector< rtl::OUString > optionalDirectBaseInterfaces_; + std::vector< Property > directProperties_; +}; + +css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > > +AccumulationBasedServiceDescription::getMandatoryServices() + throw (css::uno::RuntimeException) +{ + assert(mandatoryDirectBaseServices_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(mandatoryDirectBaseServices_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i].set( + resolve(context_, mandatoryDirectBaseServices_[i]), + css::uno::UNO_QUERY_THROW); + } + return s; +} + +css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > > +AccumulationBasedServiceDescription::getOptionalServices() + throw (css::uno::RuntimeException) +{ + assert(optionalDirectBaseServices_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(optionalDirectBaseServices_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XServiceTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i].set( + resolve(context_, optionalDirectBaseServices_[i]), + css::uno::UNO_QUERY_THROW); + } + return s; +} + +css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceTypeDescription > > +AccumulationBasedServiceDescription::getMandatoryInterfaces() + throw (css::uno::RuntimeException) +{ + assert(mandatoryDirectBaseInterfaces_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >( + mandatoryDirectBaseInterfaces_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceTypeDescription > > s( + n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i].set( + resolveTypedefs( + resolve(context_, mandatoryDirectBaseInterfaces_[i])), + css::uno::UNO_QUERY_THROW); + } + return s; +} + +css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceTypeDescription > > +AccumulationBasedServiceDescription::getOptionalInterfaces() + throw (css::uno::RuntimeException) +{ + assert(optionalDirectBaseInterfaces_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >( + optionalDirectBaseInterfaces_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XInterfaceTypeDescription > > s( + n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i].set( + resolveTypedefs( + resolve(context_, optionalDirectBaseInterfaces_[i])), + css::uno::UNO_QUERY_THROW); + } + return s; +} + +css::uno::Sequence< + css::uno::Reference< css::reflection::XPropertyTypeDescription > > +AccumulationBasedServiceDescription::getProperties() + throw (css::uno::RuntimeException) +{ + assert(directProperties_.size() <= SAL_MAX_INT32); + sal_Int32 n = static_cast< sal_Int32 >(directProperties_.size()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XPropertyTypeDescription > > s(n); + for (sal_Int32 i = 0; i != n; ++i) { + s[i] = new PropertyDescription(context_, directProperties_[i]); + } + return s; +} + +class InterfaceBasedSingletonDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XSingletonTypeDescription2 > +{ +public: + InterfaceBasedSingletonDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, rtl::OUString const & type): + ImplInheritanceHelper1(published), context_(context), name_(name), + type_(type) + {} + +private: + virtual ~InterfaceBasedSingletonDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_SINGLETON; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual css::uno::Reference< css::reflection::XServiceTypeDescription > + SAL_CALL getService() throw (css::uno::RuntimeException) + { + return + css::uno::Reference< css::reflection::XServiceTypeDescription >(); + } + + virtual sal_Bool SAL_CALL isInterfaceBased() + throw (css::uno::RuntimeException) + { return true; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > + SAL_CALL getInterface() throw (css::uno::RuntimeException) + { return resolve(context_, type_); } + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + rtl::OUString type_; +}; + +class ServiceBasedSingletonDescription: + public cppu::ImplInheritanceHelper1< + PublishableDescription, css::reflection::XSingletonTypeDescription2 > +{ +public: + ServiceBasedSingletonDescription( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & name, bool published, rtl::OUString const & type): + ImplInheritanceHelper1(published), context_(context), name_(name), + type_(type) + {} + +private: + virtual ~ServiceBasedSingletonDescription() {} + + virtual css::uno::TypeClass SAL_CALL getTypeClass() + throw (css::uno::RuntimeException) + { return css::uno::TypeClass_SINGLETON; } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return name_; } + + virtual css::uno::Reference< css::reflection::XServiceTypeDescription > + SAL_CALL getService() throw (css::uno::RuntimeException) + { + return css::uno::Reference< css::reflection::XServiceTypeDescription >( + resolve(context_, type_), css::uno::UNO_QUERY_THROW); + } + + virtual sal_Bool SAL_CALL isInterfaceBased() + throw (css::uno::RuntimeException) + { return false; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > + SAL_CALL getInterface() throw (css::uno::RuntimeException) + { return css::uno::Reference< css::reflection::XTypeDescription >(); } + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::OUString name_; + rtl::OUString type_; +}; + +// sizeof (MapEntry) == 8 +struct MapEntry { + UInt32 name; + UInt32 data; +}; + +class Enumeration: + public cppu::WeakImplHelper1< + css::reflection::XTypeDescriptionEnumeration >, + private boost::noncopyable +{ +public: + Enumeration( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::Reference< MappedFile > const & file, rtl::OUString const & prefix, + MapEntry const * mapBegin, sal_uInt32 mapSize, + css::uno::Sequence< css::uno::TypeClass > const & types, bool deep): + context_(context), file_(file), types_(types), deep_(deep) + { + positions_.push(Position(prefix, mapBegin, mapSize, false)); + findMatch(); + } + +private: + virtual ~Enumeration() {} + + virtual sal_Bool SAL_CALL hasMoreElements() + throw (css::uno::RuntimeException) + { return !positions_.empty(); } + + virtual css::uno::Any SAL_CALL nextElement() + throw ( + css::container::NoSuchElementException, + css::lang::WrappedTargetException, css::uno::RuntimeException) + { return css::uno::makeAny(nextTypeDescription()); } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + nextTypeDescription() + throw ( + css::container::NoSuchElementException, css::uno::RuntimeException); + + bool matches(css::uno::TypeClass tc) const; + + void proceed(); + + void findMatch(); + + struct Position { + Position( + rtl::OUString const & thePrefix, MapEntry const * mapBegin, + sal_uInt32 mapSize, bool theConstantGroup): + prefix(thePrefix), position(mapBegin), end(mapBegin + mapSize), + constantGroup(theConstantGroup) + {} + + rtl::OUString prefix; + MapEntry const * position; + MapEntry const * end; + bool constantGroup; + }; + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::Reference< MappedFile > file_; + css::uno::Sequence< css::uno::TypeClass > types_; + bool deep_; + + osl::Mutex mutex_; + std::stack< Position > positions_; + rtl::OUString current_; +}; + +css::uno::Reference< css::reflection::XTypeDescription > +Enumeration::nextTypeDescription() + throw (css::container::NoSuchElementException, css::uno::RuntimeException) +{ + rtl::OUString name; + { + osl::MutexGuard g(mutex_); + if (positions_.empty()) { + throw css::container::NoSuchElementException( + "exhausted XTypeDescriptionEnumeration", + static_cast< cppu::OWeakObject * >(this)); + } + name = current_; + proceed(); + findMatch(); + } + return resolve(context_, name); +} + +bool Enumeration::matches(css::uno::TypeClass tc) const { + if (types_.getLength() == 0) { + return true; + } + for (sal_Int32 i = 0; i != types_.getLength(); ++i) { + if (types_[i] == tc) { + return true; + } + } + return false; +} + +void Enumeration::proceed() { + assert(!positions_.empty()); + assert(positions_.top().position < positions_.top().end); + if (deep_) { + sal_uInt32 off = positions_.top().position->data.get(); + int v = file_->read8(off); + bool recurse; + bool cgroup; + if (v == 0) { + recurse = true; + cgroup = false; + } else if ((v & 0x3F) == 7 && matches(css::uno::TypeClass_CONSTANT)) { + recurse = true; + cgroup = true; + } else { + recurse = false; + } + if (recurse) { + rtl::OUString prefix( + positions_.top().prefix + + file_->readNameNul(positions_.top().position->name.get()) + + "."); + sal_uInt32 mapSize = file_->read32(off + 1); + if (8 * mapSize > file_->size - off - 5) { //TODO: overflow + throw css::uno::DeploymentException( + "broken UNOIDL file: map offset + size too large", + css::uno::Reference< css::uno::XInterface >()); + } + MapEntry const * mapBegin = reinterpret_cast< MapEntry const * >( + static_cast< char const * >(file_->address) + off + 5); + ++positions_.top().position; + positions_.push(Position(prefix, mapBegin, mapSize, cgroup)); + return; + } + } + ++positions_.top().position; +} + +void Enumeration::findMatch() { + assert(!positions_.empty()); + for (;; proceed()) { + while (positions_.top().position == positions_.top().end) { + positions_.pop(); + if (positions_.empty()) { + return; + } + } + bool match; + if (positions_.top().constantGroup) { + assert(matches(css::uno::TypeClass_CONSTANT)); + match = true; + } else { + sal_uInt32 off = positions_.top().position->data.get(); + int v = file_->read8(off); + css::uno::TypeClass tc; + switch (v & 0x1F) { + case 0: // module + tc = css::uno::TypeClass_MODULE; + break; + case 1: // enum type + tc = css::uno::TypeClass_ENUM; + break; + case 2: // plain struct type (with or without base) + case 3: // polymorphic struct type template + tc = css::uno::TypeClass_STRUCT; + break; + case 4: // exception type (with or without base) + tc = css::uno::TypeClass_EXCEPTION; + break; + case 5: // interface type + tc = css::uno::TypeClass_INTERFACE; + break; + case 6: // typedef + tc = css::uno::TypeClass_TYPEDEF; + break; + case 7: // constant group + tc = css::uno::TypeClass_CONSTANTS; + break; + case 8: // single-interface--based service (with or without default + // constructor) + case 9: // accumulation-based service + tc = css::uno::TypeClass_SERVICE; + break; + case 10: // interface-based singleton + case 11: // service-based singleton + tc = css::uno::TypeClass_SINGLETON; + break; + default: + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad type byte " + + rtl::OUString::number(v)), + css::uno::Reference< css::uno::XInterface >()); + } + match = matches(tc); + } + if (match) { + current_ = positions_.top().prefix + + file_->readNameNul(positions_.top().position->name.get()); + return; + } + } +} + +class Provider: + private osl::Mutex, + public cppu::WeakComponentImplHelper2< + css::container::XHierarchicalNameAccess, + css::reflection::XTypeDescriptionEnumerationAccess >, + private boost::noncopyable +{ +public: + Provider( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & uri); + + using WeakComponentImplHelper2::acquire; + using WeakComponentImplHelper2::release; + +private: + enum Compare { COMPARE_LESS, COMPARE_GREATER, COMPARE_EQUAL }; + + virtual ~Provider() {} + + virtual void SAL_CALL disposing() {} //TODO + + virtual css::uno::Any SAL_CALL getByHierarchicalName( + rtl::OUString const & aName) + throw ( + css::container::NoSuchElementException, css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL hasByHierarchicalName( + rtl::OUString const & aName) throw (css::uno::RuntimeException) + { return find(aName) != 0; } + + virtual css::uno::Reference< css::reflection::XTypeDescriptionEnumeration > + SAL_CALL createTypeDescriptionEnumeration( + rtl::OUString const & moduleName, + css::uno::Sequence< css::uno::TypeClass > const & types, + css::reflection::TypeDescriptionSearchDepth depth) + throw( + css::reflection::NoSuchTypeNameException, + css::reflection::InvalidTypeNameException, + css::uno::RuntimeException); + + sal_uInt32 find(rtl::OUString const & name, bool * constant = 0) const; + + sal_uInt32 findInMap( + rtl::OUString const & name, sal_Int32 nameOffset, sal_Int32 nameLength, + MapEntry const * mapBegin, sal_uInt32 mapSize) const; + + Compare compare( + rtl::OUString const & name, sal_Int32 nameOffset, sal_Int32 nameLength, + MapEntry const * entry) const; + + css::uno::Reference< css::uno::XComponentContext > context_; + rtl::Reference< MappedFile > file_; + MapEntry const * mapBegin_; + sal_uInt32 mapSize_; +}; + +Provider::Provider( + css::uno::Reference< css::uno::XComponentContext > const & context, + rtl::OUString const & uri): + WeakComponentImplHelper2(*static_cast< osl::Mutex * >(this)), + context_(context), file_(new MappedFile(uri)) +{ + if (file_->size < 8 || std::memcmp(file_->address, "UNOIDL\0\xFF", 8) != 0) + { + throw css::registry::InvalidRegistryException( + uri, css::uno::Reference< css::uno::XInterface >()); + } + sal_uInt32 off = file_->read32(8); + mapSize_ = file_->read32(12); + if (off + 8 * mapSize_ > file_->size) { //TODO: overflow + throw css::uno::DeploymentException( + "broken UNOIDL file: root map offset + size too large", + css::uno::Reference< css::uno::XInterface >()); + } + mapBegin_ = reinterpret_cast< MapEntry const * >( + static_cast< char const * >(file_->address) + off); +} + +css::uno::Any Provider::getByHierarchicalName(rtl::OUString const & aName) + throw (css::container::NoSuchElementException, css::uno::RuntimeException) +{ + bool cnst; + sal_uInt32 off = find(aName, &cnst); + if (off == 0) { + throw css::container::NoSuchElementException( + aName, static_cast< cppu::OWeakObject * >(this)); + } + if (cnst) { + int v = file_->read8(off); + int type = v & 0x7F; + bool deprecated = (v & 0x80) != 0; (void)deprecated;//TODO + css::uno::Any any; + switch (type) { + case 0: // BOOLEAN + v = file_->read8(off + 1); + switch (v) { + case 0: + any <<= false; + break; + case 1: + any <<= true; + break; + default: + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad boolean constant value " + + rtl::OUString::number(v)), + css::uno::Reference< css::uno::XInterface >()); + } + break; + case 1: // BYTE + any <<= static_cast< sal_Int8 >(file_->read8(off + 1)); + //TODO: implementation-defined behavior of conversion from + // sal_uInt8 to sal_Int8 relies on two's complement + // representation + break; + case 2: // SHORT + any <<= static_cast< sal_Int16 >(file_->read16(off + 1)); + //TODO: implementation-defined behavior of conversion from + // sal_uInt16 to sal_Int16 relies on two's complement + // representation + break; + case 3: // UNSIGNED SHORT + any <<= file_->read16(off + 1); + break; + case 4: // LONG + any <<= static_cast< sal_Int32 >(file_->read32(off + 1)); + //TODO: implementation-defined behavior of conversion from + // sal_uInt32 to sal_Int32 relies on two's complement + // representation + break; + case 5: // UNSIGNED LONG + any <<= file_->read32(off + 1); + break; + case 6: // HYPER + any <<= static_cast< sal_Int64 >(file_->read64(off + 1)); + //TODO: implementation-defined behavior of conversion from + // sal_uInt64 to sal_Int64 relies on two's complement + // representation + break; + case 7: // UNSIGNED HYPER + any <<= file_->read64(off + 1); + break; + case 8: // FLOAT + //TODO + case 9: // DOUBLE + //TODO + default: + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad constant type byte " + + rtl::OUString::number(v)), + css::uno::Reference< css::uno::XInterface >()); + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new ConstantDescription(aName, any)); + } else { + int v = file_->read8(off); + int type = v & 0x3F; + bool published = (v & 0x80) != 0; + bool deprecated = (v & 0x40) != 0; (void)deprecated;//TODO + bool flag = (v & 0x20) != 0; + switch (type) { + case 0: // module + { + if (v != 0) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad module type byte " + + rtl::OUString::number(v)), + css::uno::Reference< css::uno::XInterface >()); + } + sal_uInt32 n = file_->read32(off + 1); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many items in module " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 5; + std::vector< rtl::OUString > items; + for (sal_uInt32 i = 0; i != n; ++i) { + items.push_back(file_->readNameNul(file_->read32(off))); + off += 8; + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new ModuleDescription(context_, aName, items)); + } + case 1: // enum type + { + sal_uInt32 n = file_->read32(off + 1); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many members of enum type " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 5; + std::vector< EnumTypeDescription::Member > mems; + for (sal_uInt32 i = 0; i != n; ++i) { + rtl::OUString memName(file_->readNameLen(off, &off)); + sal_Int32 memValue = static_cast< sal_Int32 >( + file_->read32(off)); + //TODO: implementation-defined behavior of conversion + // from sal_uInt32 to sal_Int32 relies on two's + // complement representation + off += 4; + mems.push_back( + EnumTypeDescription::Member(memName, memValue)); + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new EnumTypeDescription(aName, published, mems)); + } + case 2: // plain struct type without base + case 2 | 0x20: // plain struct type with base + { + ++off; + rtl::OUString base; + if (flag) { + base = file_->readNameLen(off, &off); + if (base.isEmpty()) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: empty base type name of plain" + " struct type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + } + sal_uInt32 n = file_->read32(off); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many direct members of plain" + " struct type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< PlainStructTypeDescription::Member > mems; + for (sal_uInt32 i = 0; i != n; ++i) { + rtl::OUString memName(file_->readNameLen(off, &off)); + rtl::OUString memType(file_->readNameLen(off, &off)); + mems.push_back( + PlainStructTypeDescription::Member(memName, memType)); + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new PlainStructTypeDescription( + context_, aName, published, base, mems)); + } + case 3: // polymorphic struct type template + { + sal_uInt32 n = file_->read32(off + 1); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many type parameters of" + " polymorphic struct type template " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 5; + std::vector< rtl::OUString > params; + for (sal_uInt32 i = 0; i != n; ++i) { + params.push_back(file_->readNameLen(off, &off)); + } + std::vector< PolymorphicStructTypeTemplateDescription::Member > + mems; + for (sal_uInt32 i = 0; i != n; ++i) { + v = file_->read8(off); + ++off; + rtl::OUString memName(file_->readNameLen(off, &off)); + rtl::OUString memType(file_->readNameLen(off, &off)); + if (v > 1) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad flags " + + rtl::OUString::number(v) + " for member " + + memName + " of polymorphic struct type template " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + mems.push_back( + PolymorphicStructTypeTemplateDescription::Member( + memName, memType, v == 1)); + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new PolymorphicStructTypeTemplateDescription( + context_, aName, published, params, mems)); + } + case 4: // exception type without base + case 4 | 0x20: // exception type with base + { + ++off; + rtl::OUString base; + if (flag) { + base = file_->readNameLen(off, &off); + if (base.isEmpty()) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: empty base type name of" + " exception type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + } + sal_uInt32 n = file_->read32(off); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many direct members of" + " exception type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< ExceptionTypeDescription::Member > mems; + for (sal_uInt32 i = 0; i != n; ++i) { + rtl::OUString memName(file_->readNameLen(off, &off)); + rtl::OUString memType(file_->readNameLen(off, &off)); + mems.push_back( + ExceptionTypeDescription::Member(memName, memType)); + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new ExceptionTypeDescription( + context_, aName, published, base, mems)); + } + case 5: // interface type + { + sal_uInt32 n = file_->read32(off + 1); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many mandatory direct bases" + " of interface type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 5; + std::vector< rtl::OUString > mandBases; + for (sal_uInt32 i = 0; i != n; ++i) { + mandBases.push_back(file_->readNameLen(off, &off)); + } + n = file_->read32(off); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many optional direct bases of" + " interface type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< rtl::OUString > optBases; + for (sal_uInt32 i = 0; i != n; ++i) { + optBases.push_back(file_->readNameLen(off, &off)); + } + sal_uInt32 nAttrs = file_->read32(off); + if (nAttrs > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many direct attributes of" + " interface type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< Attribute > attrs; + for (sal_uInt32 i = 0; i != nAttrs; ++i) { + v = file_->read8(off); + ++off; + rtl::OUString attrName(file_->readNameLen(off, &off)); + rtl::OUString attrType(file_->readNameLen(off, &off)); + if (v > 0x03) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad flags for direct" + " attribute " + attrName + " of interface type " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + std::vector< rtl::OUString > getExcs; + sal_uInt32 m = file_->read32(off); + if (m > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many getter exceptions" + " for direct attribute " + attrName + + " of interface type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + for (sal_uInt32 j = 0; j != m; ++j) { + getExcs.push_back(file_->readNameLen(off, &off)); + } + std::vector< rtl::OUString > setExcs; + if ((v & 0x02) != 0) { + m = file_->read32(off); + if (m > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many setter" + " exceptions for direct attribute " + attrName + + " of interface type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + for (sal_uInt32 j = 0; j != m; ++j) { + setExcs.push_back(file_->readNameLen(off, &off)); + } + } + attrs.push_back( + Attribute( + attrName, attrType, (v & 0x01) != 0, + (v & 0x02) != 0, getExcs, setExcs)); + } + sal_uInt32 nMeths = file_->read32(off); + if (nMeths > SAL_MAX_INT32 - nAttrs) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many direct attributes and" + " methods of interface type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< Method > meths; + for (sal_uInt32 i = 0; i != nMeths; ++i) { + rtl::OUString methName(file_->readNameLen(off, &off)); + rtl::OUString methType(file_->readNameLen(off, &off)); + sal_uInt32 m = file_->read32(off); + if (m > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many parameters for" + " method " + methName + " of interface type " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< Method::Parameter > params; + for (sal_uInt32 j = 0; j != m; ++j) { + v = file_->read8(off); + ++off; + rtl::OUString paramName(file_->readNameLen(off, &off)); + rtl::OUString paramType(file_->readNameLen(off, &off)); + Method::Parameter::Direction dir; + switch (v) { + case 0: + dir = Method::Parameter::DIRECTION_IN; + break; + case 1: + dir = Method::Parameter::DIRECTION_OUT; + break; + case 2: + dir = Method::Parameter::DIRECTION_IN_OUT; + break; + default: + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad direction " + + rtl::OUString::number(v) + " of parameter " + + paramName + " for method " + methName + + " of interface type " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + params.push_back( + Method::Parameter(paramName, paramType, dir)); + } + std::vector< rtl::OUString > excs; + m = file_->read32(off); + if (m > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many exceptions for" + " method " + methName + " of interface type " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + for (sal_uInt32 j = 0; j != m; ++j) { + excs.push_back(file_->readNameLen(off, &off)); + } + meths.push_back(Method(methName, methType, params, excs)); + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new InterfaceTypeDescription( + context_, aName, published, mandBases, optBases, + attrs, meths)); + } + case 6: // typedef + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new TypedefDescription( + context_, aName, published, + file_->readNameLen(off + 1))); + case 7: // constant group + { + sal_uInt32 n = file_->read32(off + 1); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many constants in constant" + " group " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 5; + std::vector< rtl::OUString > consts; + for (sal_uInt32 i = 0; i != n; ++i) { + consts.push_back(file_->readNameNul(file_->read32(off))); + off += 8; + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new ConstantGroupDescription( + context_, aName, published, consts)); + } + case 8: // single-interface--based service without default constructor + case 8 | 0x20: + // single-interface--based service with default constructor + { + rtl::OUString base(file_->readNameLen(off + 1, &off)); + std::vector< Constructor > ctors; + if (flag) { + ctors.push_back(Constructor()); + } else { + sal_uInt32 n = file_->read32(off); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many constructors of" + " single-interface--based service " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + for (sal_uInt32 i = 0; i != n; ++i) { + rtl::OUString ctorName(file_->readNameLen(off, &off)); + sal_uInt32 m = file_->read32(off); + if (m > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many parameters for" + " constructor " + ctorName + + " of single-interface--based service " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< Constructor::Parameter > params; + for (sal_uInt32 j = 0; j != m; ++j) { + v = file_->read8(off); + ++off; + rtl::OUString paramName( + file_->readNameLen(off, &off)); + rtl::OUString paramType( + file_->readNameLen(off, &off)); + bool rest; + switch (v) { + case 0: + rest = false; + break; + case 0x04: + rest = true; + break; + default: + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad mode " + + rtl::OUString::number(v) + + " of parameter " + paramName + + " for constructor " + ctorName + + " of single-interface--based service " + + aName), + css::uno::Reference< + css::uno::XInterface >()); + } + params.push_back( + Constructor::Parameter( + paramName, paramType, rest)); + } + std::vector< rtl::OUString > excs; + m = file_->read32(off); + if (m > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many exceptions for" + " constructor " + ctorName + + " of single-interface--based service " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + for (sal_uInt32 j = 0; j != m; ++j) { + excs.push_back(file_->readNameLen(off, &off)); + } + ctors.push_back(Constructor(ctorName, params, excs)); + } + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new SingleInterfaceBasedServiceDescription( + context_, aName, published, base, ctors)); + } + case 9: // accumulation-based service + { + sal_uInt32 n = file_->read32(off + 1); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many mandatory direct service" + " bases of accumulation-based service " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 5; + std::vector< rtl::OUString > mandServs; + for (sal_uInt32 i = 0; i != n; ++i) { + mandServs.push_back(file_->readNameLen(off, &off)); + } + n = file_->read32(off); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many optional direct service" + " bases of accumulation-based servcie " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< rtl::OUString > optServs; + for (sal_uInt32 i = 0; i != n; ++i) { + optServs.push_back(file_->readNameLen(off, &off)); + } + n = file_->read32(off); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many mandatory direct" + " interface bases of accumulation-based servcie " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< rtl::OUString > mandIfcs; + for (sal_uInt32 i = 0; i != n; ++i) { + mandIfcs.push_back(file_->readNameLen(off, &off)); + } + n = file_->read32(off); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many optional direct" + " interface bases of accumulation-based servcie " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< rtl::OUString > optIfcs; + for (sal_uInt32 i = 0; i != n; ++i) { + optIfcs.push_back(file_->readNameLen(off, &off)); + } + n = file_->read32(off); + if (n > SAL_MAX_INT32) { + throw css::uno::DeploymentException( + ("broken UNOIDL file: too many direct properties of" + " accumulation-based servcie " + aName), + css::uno::Reference< css::uno::XInterface >()); + } + off += 4; + std::vector< Property > props; + for (sal_uInt32 i = 0; i != n; ++i) { + sal_uInt16 attrs = file_->read16(off); + off += 2; + rtl::OUString propName(file_->readNameLen(off, &off)); + rtl::OUString propType(file_->readNameLen(off, &off)); + if (attrs > 0x01FF) { // see css.beans.PropertyAttribute + throw css::uno::DeploymentException( + ("broken UNOIDL file: bad mode " + + rtl::OUString::number(v) + " of property " + + propName + " for accumulation-based servcie " + + aName), + css::uno::Reference< css::uno::XInterface >()); + } + props.push_back( + Property( + propName, propType, + static_cast< sal_Int32 >(attrs))); + } + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new AccumulationBasedServiceDescription( + context_, aName, published, mandServs, optServs, + mandIfcs, optIfcs, props)); + } + case 10: // interface-based singleton + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new InterfaceBasedSingletonDescription( + context_, aName, published, + file_->readNameLen(off + 1))); + case 11: // service-based singleton + return css::uno::makeAny< + css::uno::Reference< css::reflection::XTypeDescription > >( + new ServiceBasedSingletonDescription( + context_, aName, published, + file_->readNameLen(off + 1))); + default: + throw css::uno::DeploymentException( + "broken UNOIDL file: bad type byte " + rtl::OUString::number(v), + css::uno::Reference< css::uno::XInterface >()); + } + } +} + +css::uno::Reference< css::reflection::XTypeDescriptionEnumeration > +Provider::createTypeDescriptionEnumeration( + rtl::OUString const & moduleName, + css::uno::Sequence< css::uno::TypeClass > const & types, + css::reflection::TypeDescriptionSearchDepth depth) + throw( + css::reflection::NoSuchTypeNameException, + css::reflection::InvalidTypeNameException, css::uno::RuntimeException) +{ + rtl::OUString prefix; + MapEntry const * mapBegin; + sal_uInt32 mapSize; + if (moduleName.isEmpty()) { + mapBegin = mapBegin_; + mapSize = mapSize_; + } else { + prefix = moduleName + "."; + bool cnst; + sal_uInt32 off = find(moduleName, &cnst); + if (off == 0) { + throw css::reflection::NoSuchTypeNameException( + moduleName, static_cast< cppu::OWeakObject * >(this)); + } + if (cnst || file_->read8(off) != 0) { // module + throw css::reflection::InvalidTypeNameException( + moduleName, static_cast< cppu::OWeakObject * >(this)); + } + mapSize = file_->read32(off + 1); + if (8 * mapSize > file_->size - off - 5) { //TODO: overflow + throw css::uno::DeploymentException( + "broken UNOIDL file: map offset + size too large", + css::uno::Reference< css::uno::XInterface >()); + } + mapBegin = reinterpret_cast< MapEntry const * >( + static_cast< char const * >(file_->address) + off + 5); + } + return new Enumeration( + context_, file_, prefix, mapBegin, mapSize, types, + depth == css::reflection::TypeDescriptionSearchDepth_INFINITE); +} + +sal_uInt32 Provider::find(rtl::OUString const & name, bool * constant) const { + MapEntry const * mapBegin = mapBegin_; + sal_uInt32 mapSize = mapSize_; + bool cgroup = false; + for (sal_Int32 i = 0;;) { + sal_Int32 j = name.indexOf('.', i); + if (j == -1) { + j = name.getLength(); + } + sal_Int32 off = findInMap(name, i, j - i, mapBegin, mapSize); + if (off == 0) { + return 0; + } + if (j == name.getLength()) { + if (constant != 0) { + *constant = cgroup; + } + return off; + } + if (cgroup) { + return 0; + //TODO: throw an exception instead here, where the segments of a + // constant's name are a prefix of the requested name's + // segments? + } + int v = file_->read8(off); + if (v != 0) { // module + if ((v & 0x3F) == 7) { // constant group + cgroup = true; + } else { + return 0; + //TODO: throw an exception instead here, where the segments + // of a non-module, non-constant-group entity's name are a + // prefix of the requested name's segments? + } + } + mapSize = file_->read32(off + 1); + if (8 * mapSize > file_->size - off - 5) { //TODO: overflow + throw css::uno::DeploymentException( + "broken UNOIDL file: map offset + size too large", + css::uno::Reference< css::uno::XInterface >()); + } + mapBegin = reinterpret_cast< MapEntry const * >( + static_cast< char const * >(file_->address) + off + 5); + i = j + 1; + } +} + +sal_uInt32 Provider::findInMap( + rtl::OUString const & name, sal_Int32 nameOffset, sal_Int32 nameLength, + MapEntry const * mapBegin, sal_uInt32 mapSize) const +{ + if (mapSize == 0) { + return 0; + } + sal_uInt32 n = mapSize / 2; + MapEntry const * p = mapBegin + n; + switch (compare(name, nameOffset, nameLength, p)) { + case COMPARE_LESS: + return findInMap(name, nameOffset, nameLength, mapBegin, n); + case COMPARE_GREATER: + return findInMap(name, nameOffset, nameLength, p + 1, mapSize - n - 1); + default: // COMPARE_EQUAL + break; + } + sal_uInt32 off = mapBegin[n].data.get(); + if (off == 0) { + throw css::uno::DeploymentException( + "broken UNOIDL file: map entry data offset is null", + css::uno::Reference< css::uno::XInterface >()); + } + return off; +} + +Provider::Compare Provider::compare( + rtl::OUString const & name, sal_Int32 nameOffset, sal_Int32 nameLength, + MapEntry const * entry) const +{ + assert(entry != 0); + sal_uInt32 off = entry->name.get(); + if (off > file_->size - 1) { // at least a trailing NUL + throw css::uno::DeploymentException( + "broken UNOIDL file: string offset too large", + css::uno::Reference< css::uno::XInterface >()); + } + assert(nameLength >= 0); + sal_uInt64 min = std::min( + static_cast< sal_uInt64 >(nameLength), file_->size - off); + for (sal_uInt64 i = 0; i != min; ++i) { + sal_Unicode c1 = name[nameOffset + i]; + sal_Unicode c2 = static_cast< unsigned char const * >(file_->address)[ + off + i]; + if (c1 < c2) { + return COMPARE_LESS; + } else if (c1 > c2 || c2 == 0) { + // ...the "|| c2 == 0" is for the odd case where name erroneously + // contains NUL characters + return COMPARE_GREATER; + } + } + if (static_cast< sal_uInt64 >(nameLength) == min) { + if (file_->size - off == min) { + throw css::uno::DeploymentException( + "broken UNOIDL file: string misses trailing NUL", + css::uno::Reference< css::uno::XInterface >()); + } + return + static_cast< unsigned char const * >(file_->address)[off + min] == 0 + ? COMPARE_EQUAL : COMPARE_LESS; + } else { + return COMPARE_GREATER; + } +} + +css::uno::Reference< css::container::XHierarchicalNameAccess > +readLegacyRdbFile( + rtl::OUString const & uri, css::uno::Reference< css::lang::XMultiComponentFactory > const & serviceManager, - css::uno::Reference< css::uno::XComponentContext > const & context, - std::vector< - css::uno::Reference< css::container::XHierarchicalNameAccess > > * - providers) + css::uno::Reference< css::uno::XComponentContext > const & context) { assert(serviceManager.is()); - assert(providers != 0); css::uno::Reference< css::registry::XSimpleRegistry > reg( serviceManager->createInstanceWithContext( "com.sun.star.comp.stoc.SimpleRegistry", context), @@ -48,25 +3051,48 @@ void readTypeRdbFile( try { reg->open(uri, true, false); } catch (css::registry::InvalidRegistryException & e) { + throw css::uno::DeploymentException( + "Invalid registry " + uri + ":" + e.Message, + css::uno::Reference< css::uno::XInterface >()); + } + css::uno::Sequence< css::uno::Any > arg(1); + arg[0] <<= reg; + return css::uno::Reference< css::container::XHierarchicalNameAccess >( + serviceManager->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.stoc.RegistryTypeDescriptionProvider", arg, + context), + css::uno::UNO_QUERY_THROW); +} + +void readRdbFile( + rtl::OUString const & uri, bool optional, + css::uno::Reference< css::lang::XMultiComponentFactory > const & + serviceManager, + css::uno::Reference< css::uno::XComponentContext > const & context, + std::vector< + css::uno::Reference< css::container::XHierarchicalNameAccess > > * + providers) +{ + assert(providers != 0); + css::uno::Reference< css::container::XHierarchicalNameAccess > prov; + try { + prov = new Provider(context, uri); + } catch (css::container::NoSuchElementException &) { if (optional) { SAL_INFO("cppuhelper", "Ignored optional " << uri); return; } throw css::uno::DeploymentException( - "Invalid registry " + uri + ":" + e.Message, + uri + ": no such file", css::uno::Reference< css::uno::XInterface >()); + } catch (css::registry::InvalidRegistryException &) { + prov = readLegacyRdbFile(uri, serviceManager, context); } - css::uno::Sequence< css::uno::Any > arg(1); - arg[0] <<= reg; - providers->push_back( - css::uno::Reference< css::container::XHierarchicalNameAccess >( - serviceManager->createInstanceWithArgumentsAndContext( - "com.sun.star.comp.stoc.RegistryTypeDescriptionProvider", arg, - context), - css::uno::UNO_QUERY_THROW)); + assert(prov.is()); + providers->push_back(prov); } -void readTypeRdbDirectory( +void readRdbDirectory( rtl::OUString const & uri, bool optional, css::uno::Reference< css::lang::XMultiComponentFactory > const & serviceManager, @@ -95,7 +3121,7 @@ void readTypeRdbDirectory( if (!cppu::nextDirectoryItem(dir, &fileUri)) { break; } - readTypeRdbFile(fileUri, optional, serviceManager, context, providers); + readRdbFile(fileUri, optional, serviceManager, context, providers); } } @@ -120,10 +3146,9 @@ cppuhelper::createTypeDescriptionProviders( bool directory; cppu::decodeRdbUri(&uri, &optional, &directory); if (directory) { - readTypeRdbDirectory( - uri, optional, serviceManager, context, &provs); + readRdbDirectory(uri, optional, serviceManager, context, &provs); } else { - readTypeRdbFile(uri, optional, serviceManager, context, &provs); + readRdbFile(uri, optional, serviceManager, context, &provs); } } css::uno::Sequence< |