Kaydet (Commit) 36e8d5d1 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

Insert type rdbs individually into theTypeDescriptionManager

...to make it easier in the future to replace the binary rdb format with
something else, but also keep support for the old format for backwards
compatibility (extensions).

This should have no performance impact, as the type description manager (a)
caches information about requested type descriptions, and (b) has been changed
to process the bootstrap rdbs en bloc without doing costly consistency checks
(which are useful though when inserting an rdb when installing an extension, but
which would exhaustively read all type descriptions from the inserted rdb, so
would negate any benefit of constructing any type descriptions on demand only).

Change-Id: I80b22770bd9a5e0ab686f04d9c70295f2e3d0bf6
üst eed249f5
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "com/sun/star/container/XHierarchicalNameAccess.hpp" #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
#include "com/sun/star/container/XSet.hpp" #include "com/sun/star/container/XSet.hpp"
#include "com/sun/star/uno/DeploymentException.hpp" #include "com/sun/star/uno/DeploymentException.hpp"
#include "com/sun/star/uno/Any.hxx"
#include "com/sun/star/uno/Reference.hxx" #include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/XComponentContext.hpp" #include "com/sun/star/uno/XComponentContext.hpp"
#include "cppuhelper/bootstrap.hxx" #include "cppuhelper/bootstrap.hxx"
...@@ -117,7 +118,7 @@ cppu::defaultBootstrap_InitialComponentContext(rtl::OUString const & iniUri) ...@@ -117,7 +118,7 @@ cppu::defaultBootstrap_InitialComponentContext(rtl::OUString const & iniUri)
tdmgr, css::uno::UNO_QUERY_THROW)-> tdmgr, css::uno::UNO_QUERY_THROW)->
insert( insert(
css::uno::makeAny( css::uno::makeAny(
cppuhelper::createTypeDescriptionProvider( cppuhelper::createTypeDescriptionProviders(
getBootstrapVariable(bs, "UNO_TYPES"), smgr.get(), getBootstrapVariable(bs, "UNO_TYPES"), smgr.get(),
context))); context)));
cppu::installTypeDescriptionManager(tdmgr); cppu::installTypeDescriptionManager(tdmgr);
......
...@@ -10,13 +10,16 @@ ...@@ -10,13 +10,16 @@
#include "sal/config.h" #include "sal/config.h"
#include <cassert> #include <cassert>
#include <vector>
#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
#include "com/sun/star/lang/XInitialization.hpp" #include "com/sun/star/lang/XInitialization.hpp"
#include "com/sun/star/lang/XMultiComponentFactory.hpp" #include "com/sun/star/lang/XMultiComponentFactory.hpp"
#include "com/sun/star/registry/InvalidRegistryException.hpp" #include "com/sun/star/registry/InvalidRegistryException.hpp"
#include "com/sun/star/registry/XSimpleRegistry.hpp" #include "com/sun/star/registry/XSimpleRegistry.hpp"
#include "com/sun/star/uno/DeploymentException.hpp" #include "com/sun/star/uno/DeploymentException.hpp"
#include "com/sun/star/uno/Reference.hxx" #include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/XComponentContext.hpp" #include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hpp" #include "com/sun/star/uno/XInterface.hpp"
#include "osl/file.hxx" #include "osl/file.hxx"
...@@ -27,52 +30,50 @@ ...@@ -27,52 +30,50 @@
namespace { namespace {
css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbFile( void readTypeRdbFile(
rtl::OUString const & uri, bool optional, rtl::OUString const & uri, bool optional,
css::uno::Reference< css::registry::XSimpleRegistry > const & lastRegistry,
css::uno::Reference< css::lang::XMultiComponentFactory > const & css::uno::Reference< css::lang::XMultiComponentFactory > const &
serviceManager, serviceManager,
css::uno::Reference< css::uno::XComponentContext > const & context) css::uno::Reference< css::uno::XComponentContext > const & context,
std::vector<
css::uno::Reference< css::container::XHierarchicalNameAccess > > *
providers)
{ {
assert(serviceManager.is()); assert(serviceManager.is());
assert(providers != 0);
css::uno::Reference< css::registry::XSimpleRegistry > reg(
serviceManager->createInstanceWithContext(
"com.sun.star.comp.stoc.SimpleRegistry", context),
css::uno::UNO_QUERY_THROW);
try { try {
css::uno::Reference< css::registry::XSimpleRegistry > simple( reg->open(uri, true, false);
serviceManager->createInstanceWithContext(
"com.sun.star.comp.stoc.SimpleRegistry", context),
css::uno::UNO_QUERY_THROW);
simple->open(uri, true, false);
if (lastRegistry.is()) {
css::uno::Reference< css::registry::XSimpleRegistry > nested(
serviceManager->createInstanceWithContext(
"com.sun.star.comp.stoc.NestedRegistry", context),
css::uno::UNO_QUERY_THROW);
css::uno::Sequence< css::uno::Any > args(2);
args[0] <<= lastRegistry;
args[1] <<= simple;
css::uno::Reference< css::lang::XInitialization >(
nested, css::uno::UNO_QUERY_THROW)->
initialize(args);
return nested;
} else {
return simple;
}
} catch (css::registry::InvalidRegistryException & e) { } catch (css::registry::InvalidRegistryException & e) {
if (!optional) { if (optional) {
throw css::uno::DeploymentException( SAL_INFO("cppuhelper", "Ignored optional " << uri);
"Invalid registry " + uri + ":" + e.Message, return;
css::uno::Reference< css::uno::XInterface >());
} }
SAL_INFO("cppuhelper", "Ignored optional " << uri); throw css::uno::DeploymentException(
return lastRegistry; "Invalid registry " + uri + ":" + e.Message,
css::uno::Reference< css::uno::XInterface >());
} }
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));
} }
css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbDirectory( void readTypeRdbDirectory(
rtl::OUString const & uri, bool optional, rtl::OUString const & uri, bool optional,
css::uno::Reference< css::registry::XSimpleRegistry > const & lastRegistry,
css::uno::Reference< css::lang::XMultiComponentFactory > const & css::uno::Reference< css::lang::XMultiComponentFactory > const &
serviceManager, serviceManager,
css::uno::Reference< css::uno::XComponentContext > const & context) css::uno::Reference< css::uno::XComponentContext > const & context,
std::vector<
css::uno::Reference< css::container::XHierarchicalNameAccess > > *
providers)
{ {
osl::Directory dir(uri); osl::Directory dir(uri);
switch (dir.open()) { switch (dir.open()) {
...@@ -81,7 +82,7 @@ css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbDirectory( ...@@ -81,7 +82,7 @@ css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbDirectory(
case osl::FileBase::E_NOENT: case osl::FileBase::E_NOENT:
if (optional) { if (optional) {
SAL_INFO("cppuhelper", "Ignored optional " << uri); SAL_INFO("cppuhelper", "Ignored optional " << uri);
return lastRegistry; return;
} }
// fall through // fall through
default: default:
...@@ -89,25 +90,27 @@ css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbDirectory( ...@@ -89,25 +90,27 @@ css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbDirectory(
"Cannot open directory " + uri, "Cannot open directory " + uri,
css::uno::Reference< css::uno::XInterface >()); css::uno::Reference< css::uno::XInterface >());
} }
css::uno::Reference< css::registry::XSimpleRegistry > last(lastRegistry);
for (;;) { for (;;) {
rtl::OUString fileUri; rtl::OUString fileUri;
if (!cppu::nextDirectoryItem(dir, &fileUri)) { if (!cppu::nextDirectoryItem(dir, &fileUri)) {
break; break;
} }
last = readTypeRdbFile( readTypeRdbFile(fileUri, optional, serviceManager, context, providers);
fileUri, optional, last, serviceManager, context);
} }
return last;
} }
css::uno::Reference< css::registry::XSimpleRegistry > createTypeRegistry( }
css::uno::Sequence<
css::uno::Reference< css::container::XHierarchicalNameAccess > >
cppuhelper::createTypeDescriptionProviders(
rtl::OUString const & uris, rtl::OUString const & uris,
css::uno::Reference< css::lang::XMultiComponentFactory > const & css::uno::Reference< css::lang::XMultiComponentFactory > const &
serviceManager, serviceManager,
css::uno::Reference< css::uno::XComponentContext > const & context) css::uno::Reference< css::uno::XComponentContext > const & context)
{ {
css::uno::Reference< css::registry::XSimpleRegistry > reg; std::vector<
css::uno::Reference< css::container::XHierarchicalNameAccess > > provs;
for (sal_Int32 i = 0; i != -1;) { for (sal_Int32 i = 0; i != -1;) {
rtl::OUString uri(uris.getToken(0, ' ', i)); rtl::OUString uri(uris.getToken(0, ' ', i));
if (uri.isEmpty()) { if (uri.isEmpty()) {
...@@ -116,35 +119,24 @@ css::uno::Reference< css::registry::XSimpleRegistry > createTypeRegistry( ...@@ -116,35 +119,24 @@ css::uno::Reference< css::registry::XSimpleRegistry > createTypeRegistry(
bool optional; bool optional;
bool directory; bool directory;
cppu::decodeRdbUri(&uri, &optional, &directory); cppu::decodeRdbUri(&uri, &optional, &directory);
reg = directory if (directory) {
? readTypeRdbDirectory(uri, optional, reg, serviceManager, context) readTypeRdbDirectory(
: readTypeRdbFile(uri, optional, reg, serviceManager, context); uri, optional, serviceManager, context, &provs);
} else {
readTypeRdbFile(uri, optional, serviceManager, context, &provs);
}
} }
return reg; css::uno::Sequence<
} css::uno::Reference< css::container::XHierarchicalNameAccess > > provs2(
static_cast< sal_Int32 >(provs.size())); //TODO: check overflow
} std::vector<
css::uno::Reference<
css::uno::Reference< css::uno::XInterface > css::container::XHierarchicalNameAccess > >::iterator i(
cppuhelper::createTypeDescriptionProvider( provs.begin());
rtl::OUString const & uris, for (sal_Int32 j = 0; j != provs2.getLength(); ++j) {
css::uno::Reference< css::lang::XMultiComponentFactory > const & provs2[j] = *i++;
serviceManager,
css::uno::Reference< css::uno::XComponentContext > const & context)
{
assert(serviceManager.is());
css::uno::Sequence< css::uno::Any > args;
css::uno::Reference< css::registry::XSimpleRegistry > typereg(
createTypeRegistry(uris, serviceManager, context));
if (typereg.is()) {
args.realloc(1);
args[0] <<= typereg;
} }
return css::uno::Reference< css::uno::XInterface >( return provs2;
serviceManager->createInstanceWithArgumentsAndContext(
"com.sun.star.comp.stoc.RegistryTypeDescriptionProvider",
args, context),
css::uno::UNO_SET_THROW);
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -13,19 +13,20 @@ ...@@ -13,19 +13,20 @@
#include "sal/config.h" #include "sal/config.h"
#include "com/sun/star/uno/Reference.hxx" #include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/Sequence.hxx"
namespace com { namespace sun { namespace star { namespace com { namespace sun { namespace star {
namespace container { class XHierarchicalNameAccess; }
namespace lang { class XMultiComponentFactory; } namespace lang { class XMultiComponentFactory; }
namespace uno { namespace uno { class XComponentContext; }
class XComponentContext;
class XInterface;
}
} } } } } }
namespace rtl { class OUString; } namespace rtl { class OUString; }
namespace cppuhelper { namespace cppuhelper {
css::uno::Reference< css::uno::XInterface > createTypeDescriptionProvider( css::uno::Sequence<
css::uno::Reference< css::container::XHierarchicalNameAccess > >
createTypeDescriptionProviders(
rtl::OUString const & uris, rtl::OUString const & uris,
css::uno::Reference< css::lang::XMultiComponentFactory > const & css::uno::Reference< css::lang::XMultiComponentFactory > const &
serviceManager, serviceManager,
......
...@@ -392,112 +392,133 @@ sal_Bool SAL_CALL ManagerImpl::has( const Any & rElement ) ...@@ -392,112 +392,133 @@ sal_Bool SAL_CALL ManagerImpl::has( const Any & rElement )
void SAL_CALL ManagerImpl::insert( const Any & rElement ) void SAL_CALL ManagerImpl::insert( const Any & rElement )
throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException)
{ {
Reference< XHierarchicalNameAccess > xElem; // Passing in a sequence of type providers instead of a single one bypasses
if (! (rElement >>= xElem) || !xElem.is()) // the consistency checks; it is used during bootstrap:
{ bool doCheck = false;
throw IllegalArgumentException( css::uno::Sequence<
OUString( RTL_CONSTASCII_USTRINGPARAM("no valid type description provider given!") ), css::uno::Reference< css::container::XHierarchicalNameAccess > > provs;
(XWeak *)(OWeakObject *)this, 0 ); if (!(rElement >>= provs)) {
css::uno::Reference< css::container::XHierarchicalNameAccess > prov;
if (!(rElement >>= prov)) {
throw css::lang::IllegalArgumentException(
"no type description provider (or sequence thereof)",
static_cast< cppu::OWeakObject * >(this), 0);
}
doCheck = true;
provs.realloc(1);
provs[0] = prov;
} }
MutexGuard aGuard( _aComponentMutex ); MutexGuard aGuard( _aComponentMutex );
if (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end()) ProviderVector newProvs(_aProviders);
{ for (sal_Int32 i = 0; i != provs.getLength(); ++i) {
throw ElementExistException( Reference< XHierarchicalNameAccess > xElem(provs[i]);
OUString( RTL_CONSTASCII_USTRINGPARAM("provider already inserted!") ), if (!xElem.is()) {
(XWeak *)(OWeakObject *)this ); throw css::lang::IllegalArgumentException(
} "null type description provider",
static_cast< cppu::OWeakObject * >(this), 0);
}
if (! _aProviders.empty()) if (doCheck) {
{ if (find( newProvs.begin(), newProvs.end(), xElem ) != newProvs.end())
// check whether all types are compatible, if possible:
Reference<reflection::XTypeDescriptionEnumerationAccess> xTDEnumAccess(
xElem, UNO_QUERY );
OSL_ENSURE( xTDEnumAccess.is(),
"### providers ought to implement "
"reflection::XTypeDescriptionEnumerationAccess!" );
if (xTDEnumAccess.is())
{
try
{ {
TypeClass ar [] = { throw ElementExistException(
TypeClass_ENUM, TypeClass_TYPEDEF, TypeClass_SEQUENCE, OUString( RTL_CONSTASCII_USTRINGPARAM("provider already inserted!") ),
TypeClass_STRUCT, TypeClass_EXCEPTION, (XWeak *)(OWeakObject *)this );
/* TypeClass_UNION, TypeClass_ARRAY not supported */ }
TypeClass_INTERFACE,
TypeClass_SERVICE, // check whether all types are compatible, if possible:
TypeClass_INTERFACE_METHOD, TypeClass_INTERFACE_ATTRIBUTE, Reference<reflection::XTypeDescriptionEnumerationAccess> xTDEnumAccess(
TypeClass_PROPERTY, TypeClass_CONSTANT, TypeClass_CONSTANTS, xElem, UNO_QUERY );
TypeClass_SINGLETON OSL_ENSURE( xTDEnumAccess.is(),
}; "### providers ought to implement "
Reference<reflection::XTypeDescriptionEnumeration> xTDEnum( "reflection::XTypeDescriptionEnumerationAccess!" );
xTDEnumAccess->createTypeDescriptionEnumeration( if (xTDEnumAccess.is())
OUString() /* all modules */, {
Sequence<TypeClass>( ar, ARLEN(ar) ), try
reflection::TypeDescriptionSearchDepth_INFINITE ) );
while (xTDEnum->hasMoreElements())
{ {
Reference<reflection::XTypeDescription> xNewTD; TypeClass ar [] = {
try TypeClass_ENUM, TypeClass_TYPEDEF, TypeClass_SEQUENCE,
TypeClass_STRUCT, TypeClass_EXCEPTION,
/* TypeClass_UNION, TypeClass_ARRAY not supported */
TypeClass_INTERFACE,
TypeClass_SERVICE,
TypeClass_INTERFACE_METHOD, TypeClass_INTERFACE_ATTRIBUTE,
TypeClass_PROPERTY, TypeClass_CONSTANT, TypeClass_CONSTANTS,
TypeClass_SINGLETON
};
Reference<reflection::XTypeDescriptionEnumeration> xTDEnum(
xTDEnumAccess->createTypeDescriptionEnumeration(
OUString() /* all modules */,
Sequence<TypeClass>( ar, ARLEN(ar) ),
reflection::TypeDescriptionSearchDepth_INFINITE ) );
while (xTDEnum->hasMoreElements())
{ {
xNewTD = xTDEnum->nextTypeDescription(); Reference<reflection::XTypeDescription> xNewTD;
} try
catch (const container::NoSuchElementException & exc) {
{ xNewTD = xTDEnum->nextTypeDescription();
throw lang::IllegalArgumentException( }
OUSTR("NoSuchElementException occurred: ") + catch (const container::NoSuchElementException & exc)
exc.Message, static_cast<OWeakObject *>(this), {
-1 /* unknown */ ); throw lang::IllegalArgumentException(
} OUSTR("NoSuchElementException occurred: ") +
exc.Message, static_cast<OWeakObject *>(this),
-1 /* unknown */ );
}
try try
{
OUString newName( xNewTD->getName() );
Reference<reflection::XTypeDescription> xExistingTD(
getByHierarchicalName( newName ), UNO_QUERY );
OSL_ASSERT( xExistingTD.is() );
// existing, check whether compatible:
if (xExistingTD.is())
{ {
try OUString newName( xNewTD->getName() );
Reference<reflection::XTypeDescription> xExistingTD(
getByHierarchicalName( newName ), UNO_QUERY );
OSL_ASSERT( xExistingTD.is() );
// existing, check whether compatible:
if (xExistingTD.is())
{ {
check( xNewTD, xExistingTD ); try
} {
catch (const IncompatibleTypeException & exc) check( xNewTD, xExistingTD );
{ }
throw lang::IllegalArgumentException( catch (const IncompatibleTypeException & exc)
OUSTR("Rejecting types due to " {
"incompatibility! ") + exc.m_cause, throw lang::IllegalArgumentException(
static_cast<OWeakObject *>(this), 0 ); OUSTR("Rejecting types due to "
"incompatibility! ") + exc.m_cause,
static_cast<OWeakObject *>(this), 0 );
}
} }
} }
} catch (container::NoSuchElementException &)
catch (container::NoSuchElementException &) {
{ // type not in: ok
// type not in: ok }
} }
} }
catch (const reflection::NoSuchTypeNameException & exc)
{
throw lang::IllegalArgumentException(
OUSTR("NoSuchTypeNameException occurred: ") + exc.Message,
static_cast<OWeakObject *>(this), -1 /* unknown */ );
} }
catch (const reflection::NoSuchTypeNameException & exc) catch (const reflection::InvalidTypeNameException & exc)
{ {
throw lang::IllegalArgumentException( throw lang::IllegalArgumentException(
OUSTR("NoSuchTypeNameException occurred: ") + exc.Message, OUSTR("InvalidTypeNameException occurred: ") + exc.Message,
static_cast<OWeakObject *>(this), -1 /* unknown */ ); static_cast<OWeakObject *>(this), -1 /* unknown */ );
} }
catch (const reflection::InvalidTypeNameException & exc)
{
throw lang::IllegalArgumentException(
OUSTR("InvalidTypeNameException occurred: ") + exc.Message,
static_cast<OWeakObject *>(this), -1 /* unknown */ );
} }
} }
newProvs.push_back( xElem );
} }
_aProviders.push_back( xElem ); _aProviders = newProvs;
Reference< XComponent > xComp( xElem, UNO_QUERY ); for (sal_Int32 i = 0; i != provs.getLength(); ++i) {
if (xComp.is()) Reference< XComponent > xComp( provs[i], UNO_QUERY );
xComp->addEventListener( &_aEventListener ); if (xComp.is())
xComp->addEventListener( &_aEventListener );
}
} }
//__________________________________________________________________________________________________ //__________________________________________________________________________________________________
void SAL_CALL ManagerImpl::remove( const Any & rElement ) void SAL_CALL ManagerImpl::remove( const Any & rElement )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment