summaryrefslogtreecommitdiff
path: root/cppuhelper
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2012-04-20 22:46:42 +0200
committerStephan Bergmann <sbergman@redhat.com>2012-04-20 22:57:32 +0200
commitc2fd9b533cfad18735df212cc7fd61443628dc0c (patch)
tree92417b3365012a8e405982302d5fcffd4f03e4e9 /cppuhelper
parentb2fdaed46509127ec3ac2fb87404bc1b51d77778 (diff)
New cppu::defaultBootstrap_InitialComponentContext implementation
...that no longer uses XSimpleRegistry structures for the service data and thus is potentially more performant. * Registry-based functions from cppuhelper/bootstrap are deprecated now, client code should always use defaultBootstrap_InitialComponentContext. * References to the obsolete UNO_WRITERDB have been removed. * Some of the functions in cppuhelper/source that are used from multiple .cxx but had not been properly placed into .hxx have been cleaned up. * css.lang.ServiceManager XSet insert/remove now support special sequence<NamedValue> to improve live deployment/removal of XML-based extension components data. * 09524d410bbaad2a0b9b39811cb5cc16621b1396 "stoc: accelerate opening of multiple XML .rdb files in a directory" and its follow-up cb5c881a7f179391ee853f76e159254c97d776a3 "avoid using the new rdb reading logic for empty/non-existent directories" have been obsoleted by this change and have been reverted again.
Diffstat (limited to 'cppuhelper')
-rw-r--r--cppuhelper/Library_cppuhelper.mk4
-rw-r--r--cppuhelper/inc/cppuhelper/bootstrap.hxx32
-rw-r--r--cppuhelper/prj/build.lst2
-rw-r--r--cppuhelper/source/bootstrap.cxx470
-rw-r--r--cppuhelper/source/defaultbootstrap.cxx1980
-rw-r--r--cppuhelper/source/macro_expander.cxx26
-rw-r--r--cppuhelper/source/paths.cxx84
-rw-r--r--cppuhelper/source/paths.hxx46
-rw-r--r--cppuhelper/source/servicefactory.cxx7
-rw-r--r--cppuhelper/source/servicefactory_detail.hxx64
10 files changed, 2226 insertions, 489 deletions
diff --git a/cppuhelper/Library_cppuhelper.mk b/cppuhelper/Library_cppuhelper.mk
index 18837acf315e..aa8c3fd95708 100644
--- a/cppuhelper/Library_cppuhelper.mk
+++ b/cppuhelper/Library_cppuhelper.mk
@@ -44,8 +44,10 @@ $(eval $(call gb_Library_add_defs,cppuhelper,\
$(eval $(call gb_Library_use_libraries,cppuhelper,\
cppu \
+ reg \
sal \
salhelper \
+ xmlreader \
$(gb_STDLIBS) \
))
@@ -58,6 +60,7 @@ $(eval $(call gb_Library_add_exception_objects,cppuhelper,\
cppuhelper/source/bootstrap \
cppuhelper/source/component_context \
cppuhelper/source/component \
+ cppuhelper/source/defaultbootstrap \
cppuhelper/source/exc_thrower \
cppuhelper/source/factory \
cppuhelper/source/implbase \
@@ -65,6 +68,7 @@ $(eval $(call gb_Library_add_exception_objects,cppuhelper,\
cppuhelper/source/implementationentry \
cppuhelper/source/interfacecontainer \
cppuhelper/source/macro_expander \
+ cppuhelper/source/paths \
cppuhelper/source/propertysetmixin \
cppuhelper/source/propshlp \
cppuhelper/source/servicefactory \
diff --git a/cppuhelper/inc/cppuhelper/bootstrap.hxx b/cppuhelper/inc/cppuhelper/bootstrap.hxx
index 319854a14960..5d83d263d8de 100644
--- a/cppuhelper/inc/cppuhelper/bootstrap.hxx
+++ b/cppuhelper/inc/cppuhelper/bootstrap.hxx
@@ -48,6 +48,10 @@ namespace cppu
@rBootstrapPath optional bootstrap path for initial components
@return simple registry service instance
+
+ @deprecated Registry-based type/service information is successively
+ replaced with more modern formats; client code should exclusively use
+ ::cppu::defaultBootstrap_InitialComponentContext (or ::cppu::bootstrap).
*/
CPPUHELPER_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::registry::XSimpleRegistry >
SAL_CALL createSimpleRegistry(
@@ -58,6 +62,10 @@ SAL_CALL createSimpleRegistry(
@rBootstrapPath optional bootstrap path for initial components
@return nested registry service instance
+
+ @deprecated Registry-based type/service information is successively
+ replaced with more modern formats; client code should exclusively use
+ ::cppu::defaultBootstrap_InitialComponentContext (or ::cppu::bootstrap).
*/
CPPUHELPER_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::registry::XSimpleRegistry >
SAL_CALL createNestedRegistry(
@@ -83,6 +91,10 @@ CPPUHELPER_DLLPUBLIC sal_Bool SAL_CALL installTypeDescriptionManager(
@param xRegistry registry for service manager and singleton objects of context (may be null)
@param rBootstrapPath optional bootstrap path for initial components
@return component context
+
+ @deprecated Registry-based type/service information is successively
+ replaced with more modern formats; client code should exclusively use
+ ::cppu::defaultBootstrap_InitialComponentContext (or ::cppu::bootstrap).
*/
CPPUHELPER_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > SAL_CALL
bootstrap_InitialComponentContext(
@@ -91,19 +103,13 @@ bootstrap_InitialComponentContext(
SAL_THROW( (::com::sun::star::uno::Exception) );
-/** Bootstraps an initial component context with service manager upon default types and
- services registry.
- This includes insertion of initial services:
- - (registry) service manager, shared lib loader,
- - simple registry, nested registry,
- - implementation registration
- - registry typedescription provider, typedescription manager (also installs it into cppu core)
+/** Bootstraps an initial component context with service manager upon
+ information from bootstrap variables.
This function tries to find its parameters via these bootstrap variables:
- UNO_TYPES -- a space separated list of file urls of type rdbs
- UNO_SERVICES -- a space separated list of file urls of service rdbs
- - UNO_WRITERDB -- a file url of a write rdb (e.g. user.rdb)
Please look at http://udk.openoffice.org/common/man/concept/uno_default_bootstrapping.html
for further info.
@@ -114,19 +120,13 @@ CPPUHELPER_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::uno::XC
defaultBootstrap_InitialComponentContext() SAL_THROW( (::com::sun::star::uno::Exception) );
-/** Bootstraps an initial component context with service manager upon default types and
- services registry.
- This includes insertion of initial services:
- - (registry) service manager, shared lib loader,
- - simple registry, nested registry,
- - implementation registration
- - registry typedescription provider, typedescription manager (also installs it into cppu core)
+/** Bootstraps an initial component context with service manager upon
+ information from an ini file.
This function tries to find its parameters via these bootstrap variables:
- UNO_TYPES -- a space separated list of file urls of type rdbs
- UNO_SERVICES -- a space separated list of file urls of service rdbs
- - UNO_WRITERDB -- a file url of a write rdb (e.g. user.rdb)
Please look at http://udk.openoffice.org/common/man/concept/uno_default_bootstrapping.html
for further info.
diff --git a/cppuhelper/prj/build.lst b/cppuhelper/prj/build.lst
index 6e10408c92a8..96c20b6debfc 100644
--- a/cppuhelper/prj/build.lst
+++ b/cppuhelper/prj/build.lst
@@ -1,3 +1,3 @@
-ch cppuhelper : BOOST:boost LIBXSLT:libxslt DESKTOP:codemaker cppu offapi NULL
+ch cppuhelper : BOOST:boost LIBXSLT:libxslt DESKTOP:codemaker cppu offapi registry salhelper xmlreader NULL
ch cppuhelper\prj nmake - all ch_prj NULL
ch cppuhelper\qa\propertysetmixin nmake - all ch_qa_propertysetmixin ch_prj NULL
diff --git a/cppuhelper/source/bootstrap.cxx b/cppuhelper/source/bootstrap.cxx
index 783f647d9c3f..87e58deb08f2 100644
--- a/cppuhelper/source/bootstrap.cxx
+++ b/cppuhelper/source/bootstrap.cxx
@@ -26,9 +26,9 @@
*
************************************************************************/
+#include "sal/config.h"
-#include <string.h>
-#include <vector>
+#include <cstring>
#include "rtl/process.h"
#include "rtl/bootstrap.hxx"
@@ -38,27 +38,14 @@
#include "rtl/uri.hxx"
#include "osl/diagnose.h"
#include "osl/file.hxx"
-#include "osl/module.hxx"
#include "osl/security.hxx"
#include "osl/thread.hxx"
-#include "cppuhelper/shlib.hxx"
#include "cppuhelper/bootstrap.hxx"
-#include "cppuhelper/component_context.hxx"
-#include "cppuhelper/access_control.hxx"
#include "cppuhelper/findsofficepath.h"
#include "com/sun/star/uno/XComponentContext.hpp"
-#include "com/sun/star/uno/XCurrentContext.hpp"
-
-#include "com/sun/star/lang/XSingleServiceFactory.hpp"
-#include "com/sun/star/lang/XSingleComponentFactory.hpp"
-#include "com/sun/star/lang/XInitialization.hpp"
-#include "com/sun/star/lang/XServiceInfo.hpp"
-#include "com/sun/star/registry/XSimpleRegistry.hpp"
-#include "com/sun/star/container/XSet.hpp"
-#include "com/sun/star/beans/PropertyValue.hpp"
-#include "com/sun/star/io/IOException.hpp"
+
#include "com/sun/star/bridge/UnoUrlResolver.hpp"
#include "com/sun/star/bridge/XUnoUrlResolver.hpp"
@@ -73,458 +60,9 @@ using namespace ::osl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
-namespace css = com::sun::star;
-
namespace cppu
{
-OUString const & get_this_libpath()
-{
- static OUString s_path;
- if (s_path.isEmpty())
- {
- OUString path;
- Module::getUrlFromAddress( reinterpret_cast<oslGenericFunction>(get_this_libpath), path );
- path = path.copy( 0, path.lastIndexOf( '/' ) );
- MutexGuard guard( Mutex::getGlobalMutex() );
- if (s_path.isEmpty())
- s_path = path;
- }
- return s_path;
-}
-
-Bootstrap const & get_unorc() SAL_THROW(())
-{
- static rtlBootstrapHandle s_bstrap = 0;
- if (! s_bstrap)
- {
-#ifdef ANDROID
- // Wouldn't it be lovely to avoid this fugly hard-coding.
- // The problem is that the 'create_bootstrap_macro_expander_factory()'
- // required for bootstrapping services, calls cppu::get_unorc directly
- // instead of re-using the BoostrapHandle from:
- // defaultBootstrap_InitialComponentContext
- // and since rtlBootstrapHandle is not ref-counted doing anything
- // clean here is hardish.
- OUString iniName( RTL_CONSTASCII_USTRINGPARAM( "file:///assets/program/unorc" ) );
-#else
- OUString iniName(
- get_this_libpath() + OUSTR("/" SAL_CONFIGFILE("uno")) );
-#endif
- rtlBootstrapHandle bstrap = rtl_bootstrap_args_open( iniName.pData );
-
- ClearableMutexGuard guard( Mutex::getGlobalMutex() );
- if (s_bstrap)
- {
- guard.clear();
- rtl_bootstrap_args_close( bstrap );
- }
- else
- {
- s_bstrap = bstrap;
- }
- }
- return *(Bootstrap const *)&s_bstrap;
-}
-
-// private forward decl
-Reference< lang::XMultiComponentFactory > bootstrapInitialSF(
- OUString const & rBootstrapPath )
- SAL_THROW( (Exception) );
-
-Reference< XComponentContext > bootstrapInitialContext(
- Reference< lang::XMultiComponentFactory > const & xSF,
- Reference< registry::XSimpleRegistry > const & types_xRegistry,
- Reference< registry::XSimpleRegistry > const & services_xRegistry,
- OUString const & rBootstrapPath, Bootstrap const & bootstrap )
- SAL_THROW( (Exception) );
-
-Reference< XComponentContext > SAL_CALL createInitialCfgComponentContext(
- ContextEntry_Init const * pEntries, sal_Int32 nEntries,
- Reference< XComponentContext > const & xDelegate )
- SAL_THROW(());
-
-Reference< registry::XSimpleRegistry > SAL_CALL createRegistryWrapper(
- const Reference< XComponentContext >& xContext );
-
-namespace {
-
-template< class T >
-inline beans::PropertyValue createPropertyValue(
- OUString const & name, T const & value )
- SAL_THROW(())
-{
- return beans::PropertyValue(
- name, -1, makeAny( value ), beans::PropertyState_DIRECT_VALUE );
-}
-
-OUString findBootstrapArgument(
- const Bootstrap & bootstrap,
- const OUString & arg_name,
- sal_Bool * pFallenBack )
- SAL_THROW(())
-{
- OUString result;
-
- OUString prefixed_arg_name = OUSTR("UNO_");
- prefixed_arg_name += arg_name.toAsciiUpperCase();
-
- // environment not set -> try relative to executable
- if(!bootstrap.getFrom(prefixed_arg_name, result))
- {
- if(pFallenBack)
- *pFallenBack = sal_True;
-
- OUString fileName;
- bootstrap.getIniName(fileName);
-
- // cut the rc extension
- OUStringBuffer result_buf( 64 );
- result_buf.append(
- fileName.copy(
- 0, fileName.getLength() - strlen(SAL_CONFIGFILE(""))) );
- result_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("_") );
- result_buf.append( arg_name.toAsciiLowerCase() );
- result_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(".rdb") );
- result = result_buf.makeStringAndClear();
-
- OSL_TRACE(
- (OSL_LOG_PREFIX "findBootstrapArgument, setting \"%s\" relative to"
- " executable \"%s\""),
- OUStringToOString(arg_name, RTL_TEXTENCODING_UTF8).getStr(),
- OUStringToOString(result, RTL_TEXTENCODING_UTF8).getStr());
- }
- else
- {
- if(pFallenBack)
- *pFallenBack = sal_False;
-
- OSL_TRACE(
- OSL_LOG_PREFIX "findBootstrapArgument, found \"%s\" in env \"%s\"",
- (OUStringToOString(prefixed_arg_name, RTL_TEXTENCODING_UTF8).
- getStr()),
- OUStringToOString(result, RTL_TEXTENCODING_UTF8).getStr());
- }
-
- return result;
-}
-
-css::uno::Reference< css::registry::XSimpleRegistry > readRdbFile(
- rtl::OUString const & url, bool fatalErrors,
- css::uno::Reference< css::registry::XSimpleRegistry > const & lastRegistry,
- css::uno::Reference< css::lang::XSingleServiceFactory > const &
- simpleRegistryFactory,
- css::uno::Reference< css::lang::XSingleServiceFactory > const &
- nestedRegistryFactory)
-{
- OSL_ASSERT(simpleRegistryFactory.is() && nestedRegistryFactory.is());
- try {
- css::uno::Reference< css::registry::XSimpleRegistry > simple(
- simpleRegistryFactory->createInstance(), css::uno::UNO_QUERY_THROW);
- simple->open(url, true, false);
- if (lastRegistry.is()) {
- css::uno::Reference< css::registry::XSimpleRegistry > nested(
- nestedRegistryFactory->createInstance(),
- 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) {
- (void) e; // avoid warnings
- OSL_TRACE(
- OSL_LOG_PREFIX "warning, could not open \"%s\": \"%s\"",
- rtl::OUStringToOString(url, RTL_TEXTENCODING_UTF8).getStr(),
- rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
- if (fatalErrors) {
- throw;
- }
- return lastRegistry;
- }
-}
-
-Reference< registry::XSimpleRegistry > readRdbDirectory(
- rtl::OUString const & url, bool fatalErrors,
- css::uno::Reference< css::registry::XSimpleRegistry > const & lastRegistry,
- css::uno::Reference< css::lang::XSingleServiceFactory > const &
- simpleRegistryFactory,
- css::uno::Reference< css::lang::XSingleServiceFactory > const &
- nestedRegistryFactory)
-{
- OSL_ASSERT(simpleRegistryFactory.is() && nestedRegistryFactory.is());
- osl::Directory dir(url);
- switch (dir.open()) {
- case osl::FileBase::E_None:
- break;
- case osl::FileBase::E_NOENT:
- if (!fatalErrors) {
- return lastRegistry;
- }
- // fall through
- default:
- throw css::uno::RuntimeException(
- (rtl::OUString(
- RTL_CONSTASCII_USTRINGPARAM("cannot open directory ")) +
- url),
- css::uno::Reference< css::uno::XInterface >());
- }
- std::vector<rtl::OUString> aURLs;
- css::uno::Reference< css::registry::XSimpleRegistry > last(lastRegistry);
- for (;;)
- {
- osl::DirectoryItem i;
- osl::FileBase::RC eResult;
- eResult = dir.getNextItem(i, SAL_MAX_UINT32);
- if (eResult == osl::FileBase::E_NOENT)
- break;
- if (eResult != osl::FileBase::E_None)
- {
- throw css::uno::RuntimeException(
- (rtl::OUString(
- RTL_CONSTASCII_USTRINGPARAM("cannot iterate directory ")) +
- url),
- css::uno::Reference< css::uno::XInterface >());
- }
- osl::FileStatus stat(
- osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |
- osl_FileStatus_Mask_FileURL);
- if (i.getFileStatus(stat) != osl::FileBase::E_None) {
- throw css::uno::RuntimeException(
- (rtl::OUString(
- RTL_CONSTASCII_USTRINGPARAM("cannot stat in directory ")) +
- url),
- css::uno::Reference< css::uno::XInterface >());
- }
- rtl::OUString aName = stat.getFileName();
-
- // Ignore backup files - to allow people to edit their
- // services/ without extremely confusing behaviour
- if (aName.toChar() == '.' || aName.endsWithAsciiL("~", 1))
- continue;
-
- if (stat.getFileType() != osl::FileStatus::Directory) //TODO: symlinks
- aURLs.push_back(stat.getFileURL());
- }
-
- size_t nXML = 0;
- for (std::vector<rtl::OUString>::iterator it = aURLs.begin(); it != aURLs.end(); it++)
- {
- // Read / sniff the nasty files ...
- osl::File aIn( *it );
- if (aIn.open(osl_File_OpenFlag_Read) != osl::FileBase::E_None)
- continue;
-
- sal_uInt64 nRead = 0;
- char buffer[6];
- bool bIsXML = aIn.read(buffer, 6, nRead) == osl::FileBase::E_None &&
- nRead == 6 && !strncmp(buffer, "<?xml ", 6);
- aIn.close();
- if (!bIsXML)
- {
- OSL_TRACE (OSL_LOG_PREFIX "rdb '%s' is a legacy format\n",
- rtl::OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr());
- break;
- }
- nXML++;
- }
- if (nXML > 0 && nXML == aURLs.size())
- {
- OSL_TRACE (OSL_LOG_PREFIX "no legacy rdbs in directory '%s'\n",
- rtl::OUStringToOString( url, RTL_TEXTENCODING_UTF8 ).getStr());
- // read whole directory...
- last = readRdbFile( url, fatalErrors, last,
- simpleRegistryFactory, nestedRegistryFactory);
- }
- else
- {
- for (std::vector<rtl::OUString>::iterator it = aURLs.begin(); it != aURLs.end(); it++)
- {
- // Read / sniff the nasty files ...
- last = readRdbFile(*it, fatalErrors, last,
- simpleRegistryFactory, nestedRegistryFactory);
- }
- }
- return last;
-}
-
-Reference< registry::XSimpleRegistry > nestRegistries(
- const OUString &baseDir,
- const Reference< lang::XSingleServiceFactory > & xSimRegFac,
- const Reference< lang::XSingleServiceFactory > & xNesRegFac,
- OUString csl_rdbs,
- const OUString & write_rdb,
- sal_Bool forceWrite_rdb,
- sal_Bool bFallenBack )
- SAL_THROW((Exception))
-{
- sal_Int32 index;
- Reference< registry::XSimpleRegistry > lastRegistry;
-
- if(!write_rdb.isEmpty()) // is there a write registry given?
- {
- lastRegistry.set(xSimRegFac->createInstance(), UNO_QUERY);
-
- try
- {
- lastRegistry->open(write_rdb, sal_False, forceWrite_rdb);
- }
- catch (registry::InvalidRegistryException & e)
- {
- (void) e; // avoid warnings
- OSL_TRACE(
- OSL_LOG_PREFIX "warning, could not open \"%s\": \"%s\"",
- OUStringToOString(write_rdb, RTL_TEXTENCODING_UTF8).getStr(),
- OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
- }
-
- if(!lastRegistry->isValid())
- lastRegistry.clear();
- }
-
- do
- {
- index = csl_rdbs.indexOf((sal_Unicode)' ');
- OUString rdb_name = (index == -1) ? csl_rdbs : csl_rdbs.copy(0, index);
- csl_rdbs = (index == -1) ? OUString() : csl_rdbs.copy(index + 1);
-
- if (rdb_name.isEmpty()) {
- continue;
- }
-
- bool fatalErrors = !bFallenBack;
- if (rdb_name[0] == '?') {
- rdb_name = rdb_name.copy(1);
- fatalErrors = false;
- }
-
- bool directory = rdb_name.getLength() >= 3 && rdb_name[0] == '<' &&
- rdb_name[rdb_name.getLength() - 2] == '>' &&
- rdb_name[rdb_name.getLength() -1] == '*';
- if (directory) {
- rdb_name = rdb_name.copy(1, rdb_name.getLength() - 3);
- }
-
- osl::FileBase::getAbsoluteFileURL(baseDir, rdb_name, rdb_name);
-
- lastRegistry = directory
- ? readRdbDirectory(
- rdb_name, fatalErrors, lastRegistry, xSimRegFac, xNesRegFac)
- : readRdbFile(
- rdb_name, fatalErrors, lastRegistry, xSimRegFac, xNesRegFac);
- }
- while(index != -1 && csl_rdbs.getLength()); // are there more rdbs in list?
-
- return lastRegistry;
-}
-
-Reference< XComponentContext >
-SAL_CALL defaultBootstrap_InitialComponentContext(
- Bootstrap const & bootstrap )
- SAL_THROW( (Exception) )
-{
- OUString bootstrapPath;
- if (!bootstrap.getFrom(
- rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URE_INTERNAL_LIB_DIR")),
- bootstrapPath))
- {
- bootstrapPath = get_this_libpath();
- }
-
- OUString iniDir;
- osl_getProcessWorkingDir(&iniDir.pData);
-
- Reference<lang::XMultiComponentFactory> smgr_XMultiComponentFactory(
- bootstrapInitialSF(bootstrapPath) );
- Reference<lang::XMultiServiceFactory> smgr_XMultiServiceFactory(
- smgr_XMultiComponentFactory, UNO_QUERY );
-
- Reference<registry::XRegistryKey> xEmptyKey;
- Reference<lang::XSingleServiceFactory> xSimRegFac(
- loadSharedLibComponentFactory(
- OUSTR("bootstrap.uno" SAL_DLLEXTENSION), bootstrapPath,
- OUSTR("com.sun.star.comp.stoc.SimpleRegistry"),
- smgr_XMultiServiceFactory,
- xEmptyKey),
- UNO_QUERY);
-
- Reference<lang::XSingleServiceFactory> xNesRegFac(
- loadSharedLibComponentFactory(
- OUSTR("bootstrap.uno" SAL_DLLEXTENSION), bootstrapPath,
- OUSTR("com.sun.star.comp.stoc.NestedRegistry"),
- smgr_XMultiServiceFactory,
- xEmptyKey),
- UNO_QUERY);
-
- sal_Bool bFallenback_types;
- OUString cls_uno_types =
- findBootstrapArgument( bootstrap, OUSTR("TYPES"), &bFallenback_types );
-
- Reference<registry::XSimpleRegistry> types_xRegistry =
- nestRegistries(
- iniDir, xSimRegFac, xNesRegFac, cls_uno_types,
- OUString(), sal_False, bFallenback_types );
-
- // ==== bootstrap from services registry ====
-
- sal_Bool bFallenback_services;
- OUString cls_uno_services = findBootstrapArgument(
- bootstrap, OUSTR("SERVICES"), &bFallenback_services );
-
- sal_Bool fallenBackWriteRegistry;
- OUString write_rdb = findBootstrapArgument(
- bootstrap, OUSTR("WRITERDB"), &fallenBackWriteRegistry );
- if (fallenBackWriteRegistry)
- {
- // no standard write rdb anymore
- write_rdb = OUString();
- }
-
- Reference<registry::XSimpleRegistry> services_xRegistry = nestRegistries(
- iniDir, xSimRegFac, xNesRegFac, cls_uno_services, write_rdb,
- !fallenBackWriteRegistry, bFallenback_services );
-
- Reference< XComponentContext > xContext(
- bootstrapInitialContext(
- smgr_XMultiComponentFactory, types_xRegistry, services_xRegistry,
- bootstrapPath, bootstrap ) );
-
- // initialize sf
- Reference< lang::XInitialization > xInit(
- smgr_XMultiComponentFactory, UNO_QUERY );
- OSL_ASSERT( xInit.is() );
- Sequence< Any > aSFInit( 1 );
- aSFInit[ 0 ] <<= services_xRegistry;
- xInit->initialize( aSFInit );
-
- return xContext;
-}
-
-}
-
-Reference< XComponentContext >
-SAL_CALL defaultBootstrap_InitialComponentContext(
- OUString const & iniFile )
- SAL_THROW( (Exception) )
-{
- Bootstrap bootstrap( iniFile );
- if (bootstrap.getHandle() == 0)
- throw io::IOException(OUSTR("Cannot open for reading: ") + iniFile, 0);
- return defaultBootstrap_InitialComponentContext( bootstrap );
-}
-
-Reference< XComponentContext >
-SAL_CALL defaultBootstrap_InitialComponentContext()
- SAL_THROW( (Exception) )
-{
- return defaultBootstrap_InitialComponentContext( get_unorc() );
-}
-
BootstrapException::BootstrapException()
{
}
@@ -567,7 +105,7 @@ Reference< XComponentContext > SAL_CALL bootstrap()
}
rtl::OUString p2;
if (!rtl_convertStringToUString(
- &p2.pData, p1, strlen(p1), osl_getThreadTextEncoding(),
+ &p2.pData, p1, std::strlen(p1), osl_getThreadTextEncoding(),
(RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx
new file mode 100644
index 000000000000..8698f25b5695
--- /dev/null
+++ b/cppuhelper/source/defaultbootstrap.cxx
@@ -0,0 +1,1980 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ * [ Copyright (C) 2012 Red Hat, Inc., Stephan Bergmann <sbergman@redhat.com>
+ * (initial developer) ]
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#include "sal/config.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <map>
+#include <vector>
+
+#include "boost/noncopyable.hpp"
+#include "boost/shared_ptr.hpp"
+#include "com/sun/star/beans/NamedValue.hpp"
+#include "com/sun/star/beans/PropertyAttribute.hpp"
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/container/ElementExistException.hpp"
+#include "com/sun/star/container/XContentEnumerationAccess.hpp"
+#include "com/sun/star/container/XEnumeration.hpp"
+#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
+#include "com/sun/star/container/XNameContainer.hpp"
+#include "com/sun/star/container/XSet.hpp"
+#include "com/sun/star/lang/XInitialization.hpp"
+#include "com/sun/star/lang/XServiceInfo.hpp"
+#include "com/sun/star/lang/XSingleComponentFactory.hpp"
+#include "com/sun/star/lang/XSingleServiceFactory.hpp"
+#include "com/sun/star/loader/XImplementationLoader.hpp"
+#include "com/sun/star/registry/InvalidRegistryException.hpp"
+#include "com/sun/star/registry/XSimpleRegistry.hpp"
+#include "com/sun/star/uno/DeploymentException.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "cppuhelper/bootstrap.hxx"
+#include "cppuhelper/compbase8.hxx"
+#include "cppuhelper/component_context.hxx"
+#include "cppuhelper/implbase1.hxx"
+#include "cppuhelper/shlib.hxx"
+#include "osl/file.hxx"
+#include "registry/registry.hxx"
+#include "rtl/bootstrap.hxx"
+#include "rtl/ref.hxx"
+#include "rtl/uri.hxx"
+#include "rtl/ustring.hxx"
+#include "xmlreader/xmlreader.hxx"
+
+#include "macro_expander.hxx"
+#include "paths.hxx"
+#include "servicefactory_detail.hxx"
+
+namespace {
+
+namespace css = com::sun::star;
+
+bool nextDirectoryItem(osl::Directory & directory, rtl::OUString * url) {
+ assert(url != 0);
+ for (;;) {
+ osl::DirectoryItem i;
+ switch (directory.getNextItem(i, SAL_MAX_UINT32)) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ return false;
+ default:
+ throw css::uno::DeploymentException(
+ "Cannot iterate directory",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ osl::FileStatus stat(
+ osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName |
+ osl_FileStatus_Mask_FileURL);
+ if (i.getFileStatus(stat) != osl::FileBase::E_None) {
+ throw css::uno::DeploymentException(
+ "Cannot stat in directory",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (stat.getFileType() != osl::FileStatus::Directory) { //TODO: symlinks
+ // Ignore backup files:
+ rtl::OUString name(stat.getFileName());
+ if (!(name.match(".") || name.endsWith("~"))) {
+ *url = stat.getFileURL();
+ return true;
+ }
+ }
+ }
+}
+
+void decodeRdbUri(rtl::OUString * uri, bool * optional, bool * directory) {
+ assert(uri != 0 && optional != 0 && directory != 0);
+ *optional = (*uri)[0] == '?';
+ if (*optional) {
+ *uri = uri->copy(1);
+ }
+ *directory = uri->getLength() >= 3 && (*uri)[0] == '<'
+ && (*uri)[uri->getLength() - 2] == '>'
+ && (*uri)[uri->getLength() - 1] == '*';
+ if (*directory) {
+ *uri = uri->copy(1, uri->getLength() - 3);
+ }
+}
+
+struct Implementation: private boost::noncopyable {
+ Implementation(
+ rtl::OUString const & theName, rtl::OUString const & theLoader,
+ rtl::OUString const & theUri,
+ rtl::OUString const & thePrefix = rtl::OUString(),
+ css::uno::Reference< css::uno::XComponentContext > const &
+ theAlienContext
+ = css::uno::Reference< css::uno::XComponentContext >()):
+ name(theName), loader(theLoader), uri(theUri), prefix(thePrefix),
+ alienContext(theAlienContext), loaded(false)
+ {}
+
+ Implementation(
+ rtl::OUString const & theName,
+ css::uno::Reference< css::lang::XSingleComponentFactory > const &
+ theFactory1,
+ css::uno::Reference< css::lang::XSingleServiceFactory > const &
+ theFactory2,
+ css::uno::Reference< css::lang::XComponent > const & theComponent):
+ name(theName), factory1(theFactory1), factory2(theFactory2),
+ component(theComponent), loaded(true)
+ {}
+
+ rtl::OUString const name;
+ rtl::OUString const loader;
+ rtl::OUString const uri;
+ rtl::OUString const prefix;
+ css::uno::Reference< css::uno::XComponentContext > const alienContext;
+ std::vector< rtl::OUString > services;
+ std::vector< rtl::OUString > singletons;
+ css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
+ css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
+ css::uno::Reference< css::lang::XComponent > component;
+ bool loaded;
+};
+
+typedef std::map< rtl::OUString, boost::shared_ptr< Implementation > >
+NamedImplementations;
+
+typedef
+ std::map<
+ css::uno::Reference< css::lang::XServiceInfo >,
+ boost::shared_ptr< Implementation > >
+ DynamicImplementations;
+
+typedef
+ std::map<
+ rtl::OUString, std::vector< boost::shared_ptr< Implementation > > >
+ ImplementationMap;
+
+void insertImplementationMap(
+ ImplementationMap * destination, ImplementationMap const & source)
+{
+ assert(destination != 0);
+ for (ImplementationMap::const_iterator i(source.begin()); i != source.end();
+ ++i)
+ {
+ std::vector< boost::shared_ptr< Implementation > > & impls
+ = (*destination)[i->first];
+ impls.insert(impls.end(), i->second.begin(), i->second.end());
+ }
+}
+
+void removeFromImplementationMap(
+ ImplementationMap * map, std::vector< rtl::OUString > const & elements,
+ boost::shared_ptr< Implementation > const & implementation)
+{
+ // The underlying data structures make this function somewhat inefficient,
+ // but the assumption is that it is rarely called:
+ assert(map != 0);
+ for (std::vector< rtl::OUString >::const_iterator i(elements.begin());
+ i != elements.end(); ++i)
+ {
+ ImplementationMap::iterator j(map->find(*i));
+ assert(j != map->end());
+ std::vector< boost::shared_ptr< Implementation > >::iterator k(
+ std::find(j->second.begin(), j->second.end(), implementation));
+ assert(k != j->second.end());
+ j->second.erase(k);
+ if (j->second.empty()) {
+ map->erase(j);
+ }
+ }
+}
+
+struct Data: private boost::noncopyable {
+ NamedImplementations namedImplementations;
+ DynamicImplementations dynamicImplementations;
+ ImplementationMap services;
+ ImplementationMap singletons;
+};
+
+// This is largely a copy from stoc/source/simpleregistry/textualservices.cxx
+// (which it obsoletes); cppuhelper's published interface concept makes it
+// difficult to make both places use a shared Parser implementation, so I
+// created a copy for now (until the whole stoc/source/simpleregistry stuff can
+// be removed in an incompatible LibreOffice version). For simplicity, this
+// code keeps throwing css::registry::InvalidRegistryException for invalid XML
+// rdbs (even though that does not fit the exception's name):
+class Parser: private boost::noncopyable {
+public:
+ Parser(
+ rtl::OUString const & uri,
+ css::uno::Reference< css::uno::XComponentContext > const & alienContext,
+ Data * data);
+
+private:
+ void handleComponent();
+
+ void handleImplementation();
+
+ void handleService();
+
+ void handleSingleton();
+
+ rtl::OUString getNameAttribute();
+
+ xmlreader::XmlReader reader_;
+ css::uno::Reference< css::uno::XComponentContext > alienContext_;
+ Data * data_;
+ rtl::OUString attrLoader_;
+ rtl::OUString attrUri_;
+ rtl::OUString attrPrefix_;
+ rtl::OUString attrImplementation_;
+ boost::shared_ptr< Implementation > implementation_;
+};
+
+Parser::Parser(
+ rtl::OUString const & uri,
+ css::uno::Reference< css::uno::XComponentContext > const & alienContext,
+ Data * data):
+ reader_(uri), alienContext_(alienContext), data_(data)
+{
+ assert(data != 0);
+ int ucNsId = reader_.registerNamespaceIri(
+ xmlreader::Span(
+ RTL_CONSTASCII_STRINGPARAM(
+ "http://openoffice.org/2010/uno-components")));
+ enum State {
+ STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL,
+ STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON };
+ for (State state = STATE_BEGIN;;) {
+ xmlreader::Span name;
+ int nsId;
+ xmlreader::XmlReader::Result res = reader_.nextItem(
+ xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
+ switch (state) {
+ case STATE_BEGIN:
+ if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("components")))
+ {
+ state = STATE_COMPONENTS;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in outer level",
+ css::uno::Reference< css::uno::XInterface >());
+ case STATE_END:
+ if (res == xmlreader::XmlReader::RESULT_DONE) {
+ return;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in outer level",
+ css::uno::Reference< css::uno::XInterface >());
+ case STATE_COMPONENTS:
+ if (res == xmlreader::XmlReader::RESULT_END) {
+ state = STATE_END;
+ break;
+ }
+ if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
+ {
+ handleComponent();
+ state = STATE_COMPONENT_INITIAL;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <components>",
+ css::uno::Reference< css::uno::XInterface >());
+ case STATE_COMPONENT:
+ if (res == xmlreader::XmlReader::RESULT_END) {
+ state = STATE_COMPONENTS;
+ break;
+ }
+ // fall through
+ case STATE_COMPONENT_INITIAL:
+ if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("implementation")))
+ {
+ handleImplementation();
+ state = STATE_IMPLEMENTATION;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <component>",
+ css::uno::Reference< css::uno::XInterface >());
+ case STATE_IMPLEMENTATION:
+ if (res == xmlreader::XmlReader::RESULT_END) {
+ state = STATE_COMPONENT;
+ break;
+ }
+ if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("service")))
+ {
+ handleService();
+ state = STATE_SERVICE;
+ break;
+ }
+ if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("singleton")))
+ {
+ handleSingleton();
+ state = STATE_SINGLETON;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <implementation>",
+ css::uno::Reference< css::uno::XInterface >());
+ case STATE_SERVICE:
+ if (res == xmlreader::XmlReader::RESULT_END) {
+ state = STATE_IMPLEMENTATION;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <service>",
+ css::uno::Reference< css::uno::XInterface >());
+ case STATE_SINGLETON:
+ if (res == xmlreader::XmlReader::RESULT_END) {
+ state = STATE_IMPLEMENTATION;
+ break;
+ }
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": unexpected item in <service>",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+}
+
+void Parser::handleComponent() {
+ attrLoader_ = rtl::OUString();
+ attrUri_ = rtl::OUString();
+ attrPrefix_ = rtl::OUString();
+ xmlreader::Span name;
+ int nsId;
+ while (reader_.nextAttribute(&nsId, &name)) {
+ if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("loader")))
+ {
+ if (!attrLoader_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": <component> has multiple \"loader\" attributes"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrLoader_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": <component> has empty \"loader\" attribute"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("uri")))
+ {
+ if (!attrUri_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": <component> has multiple \"uri\" attributes"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ attrUri_ = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrUri_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": <component> has empty \"uri\" attribute"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("prefix")))
+ {
+ if (!attrPrefix_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl() +
+ ": <component> has multiple \"prefix\" attributes"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ attrPrefix_ = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrPrefix_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl() +
+ ": <component> has empty \"prefix\" attribute"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl() + ": unexpected attribute \""
+ + name.convertFromUtf8() + "\" in <component>"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ if (attrLoader_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": <component> is missing \"loader\" attribute",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ if (attrUri_.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": <component> is missing \"uri\" attribute",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ try {
+ attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_);
+ } catch (const rtl::MalformedUriException & e) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": bad \"uri\" attribute: " + e.getMessage(),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+void Parser::handleImplementation() {
+ attrImplementation_ = getNameAttribute();
+ implementation_.reset(
+ new Implementation(
+ attrImplementation_, attrLoader_, attrUri_, attrPrefix_,
+ alienContext_));
+ if (!data_->namedImplementations.insert(
+ NamedImplementations::value_type(
+ attrImplementation_, implementation_)).
+ second)
+ {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl() + ": duplicate <implementation name=\""
+ + attrImplementation_ + "\">"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+}
+
+void Parser::handleService() {
+ rtl::OUString name(getNameAttribute());
+ implementation_->services.push_back(name);
+ data_->services[name].push_back(implementation_);
+}
+
+void Parser::handleSingleton() {
+ rtl::OUString name(getNameAttribute());
+ implementation_->singletons.push_back(name);
+ data_->singletons[name].push_back(implementation_);
+}
+
+rtl::OUString Parser::getNameAttribute() {
+ rtl::OUString attrName;
+ xmlreader::Span name;
+ int nsId;
+ while (reader_.nextAttribute(&nsId, &name)) {
+ if (nsId == xmlreader::XmlReader::NAMESPACE_NONE
+ && name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
+ {
+ if (!attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ (reader_.getUrl()
+ + ": element has multiple \"name\" attributes"),
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ attrName = reader_.getAttributeValue(false).convertFromUtf8();
+ if (attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": element has empty \"name\" attribute",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ } else {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": expected element attribute \"name\"",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+ if (attrName.isEmpty()) {
+ throw css::registry::InvalidRegistryException(
+ reader_.getUrl() + ": element is missing \"name\" attribute",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return attrName;
+}
+
+class ContentEnumeration:
+ public cppu::WeakImplHelper1< css::container::XEnumeration >,
+ private boost::noncopyable
+{
+public:
+ explicit ContentEnumeration(std::vector< css::uno::Any > const & factories):
+ factories_(factories), iterator_(factories_.begin()) {}
+
+private:
+ virtual ~ContentEnumeration() {}
+
+ virtual sal_Bool SAL_CALL hasMoreElements()
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Any SAL_CALL nextElement()
+ throw (
+ css::container::NoSuchElementException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException);
+
+ osl::Mutex mutex_;
+ std::vector< css::uno::Any > factories_;
+ std::vector< css::uno::Any >::const_iterator iterator_;
+};
+
+sal_Bool ContentEnumeration::hasMoreElements()
+ throw (css::uno::RuntimeException)
+{
+ osl::MutexGuard g(mutex_);
+ return iterator_ != factories_.end();
+}
+
+css::uno::Any ContentEnumeration::nextElement()
+ throw (
+ css::container::NoSuchElementException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException)
+{
+ osl::MutexGuard g(mutex_);
+ if (iterator_ == factories_.end()) {
+ throw css::container::NoSuchElementException(
+ "Bootstrap service manager service enumerator has no more elements",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return *iterator_++;
+}
+
+css::beans::Property getDefaultContextProperty() {
+ return css::beans::Property(
+ "DefaultContext", -1,
+ cppu::UnoType< css::uno::XComponentContext >::get(),
+ css::beans::PropertyAttribute::READONLY);
+}
+
+typedef cppu::WeakComponentImplHelper8<
+ css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
+ css::lang::XMultiComponentFactory, css::container::XSet,
+ css::container::XContentEnumerationAccess, css::beans::XPropertySet,
+ css::beans::XPropertySetInfo, css::lang::XEventListener >
+ServiceManagerBase;
+
+class ServiceManager:
+ private osl::Mutex, public ServiceManagerBase, private boost::noncopyable
+{
+public:
+ explicit ServiceManager(rtl::OUString const & rdbUris):
+ ServiceManagerBase(*static_cast< osl::Mutex * >(this))
+ { readRdbs(rdbUris); }
+
+ using ServiceManagerBase::acquire;
+ using ServiceManagerBase::release;
+
+ void setContext(
+ css::uno::Reference< css::uno::XComponentContext > const & context)
+ {
+ assert(context.is());
+ assert(!context_.is());
+ context_ = context;
+ }
+
+ Data const & getData() const { return data_; }
+
+ virtual rtl::OUString SAL_CALL getImplementationName()
+ throw (css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< rtl::OUString > SAL_CALL
+ getSupportedServiceNames() throw (css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(
+ rtl::OUString const & aServiceSpecifier)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArguments(
+ rtl::OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< rtl::OUString > SAL_CALL
+ getAvailableServiceNames() throw (css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithContext(
+ rtl::OUString const & aServiceSpecifier,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+ createInstanceWithArgumentsAndContext(
+ rtl::OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException);
+
+ css::uno::Type SAL_CALL getElementType() throw (css::uno::RuntimeException);
+
+ sal_Bool SAL_CALL hasElements() throw (css::uno::RuntimeException);
+
+ css::uno::Reference< css::container::XEnumeration > SAL_CALL
+ createEnumeration() throw (css::uno::RuntimeException);
+
+ sal_Bool SAL_CALL has(css::uno::Any const & aElement)
+ throw (css::uno::RuntimeException);
+
+ void SAL_CALL insert(css::uno::Any const & aElement)
+ throw (
+ css::lang::IllegalArgumentException,
+ css::container::ElementExistException, css::uno::RuntimeException);
+
+ void SAL_CALL remove(css::uno::Any const & aElement)
+ throw (
+ css::lang::IllegalArgumentException,
+ css::container::NoSuchElementException, css::uno::RuntimeException);
+
+ css::uno::Reference< css::container::XEnumeration > SAL_CALL
+ createContentEnumeration(rtl::OUString const & aServiceName)
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL
+ getPropertySetInfo() throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL setPropertyValue(
+ rtl::OUString const & aPropertyName, css::uno::Any const & aValue)
+ throw (
+ css::beans::UnknownPropertyException,
+ css::beans::PropertyVetoException,
+ css::lang::IllegalArgumentException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException);
+
+ virtual css::uno::Any SAL_CALL getPropertyValue(
+ rtl::OUString const & PropertyName)
+ throw (
+ css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL addPropertyChangeListener(
+ rtl::OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ xListener)
+ throw (
+ css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL removePropertyChangeListener(
+ rtl::OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL addVetoableChangeListener(
+ rtl::OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException);
+
+ virtual void SAL_CALL removeVetoableChangeListener(
+ rtl::OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException,
+ css::lang::WrappedTargetException, css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties()
+ throw (css::uno::RuntimeException);
+
+ virtual css::beans::Property SAL_CALL getPropertyByName(
+ rtl::OUString const & aName)
+ throw (
+ css::beans::UnknownPropertyException, css::uno::RuntimeException);
+
+ virtual sal_Bool SAL_CALL hasPropertyByName(rtl::OUString const & Name)
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL disposing(css::lang::EventObject const & Source)
+ throw (css::uno::RuntimeException);
+
+private:
+ virtual ~ServiceManager() {}
+
+ virtual void SAL_CALL disposing();
+
+ // needs to be called with rBHelper.rMutex locked:
+ bool isDisposed() { return rBHelper.bDisposed || rBHelper.bInDispose; }
+
+ void removeEventListenerFromComponent(
+ css::uno::Reference< css::lang::XComponent > const & component);
+
+ void readRdbs(rtl::OUString const & uris);
+
+ void readRdbDirectory(rtl::OUString const & uri, bool optional);
+
+ void readRdbFile(rtl::OUString const & uri, bool optional);
+
+ bool readLegacyRdbFile(rtl::OUString const & uri);
+
+ rtl::OUString readLegacyRdbString(
+ rtl::OUString const & uri, RegistryKey & key,
+ rtl::OUString const & path);
+
+ void readLegacyRdbStrings(
+ rtl::OUString const & uri, RegistryKey & key,
+ rtl::OUString const & path, std::vector< rtl::OUString > * strings);
+
+ void insertRdbFiles(
+ std::vector< rtl::OUString > const & uris,
+ css::uno::Reference< css::uno::XComponentContext > const &
+ alientContext);
+
+ void insertLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo);
+
+ bool insertExtraData(Data const & extra);
+
+ void removeRdbFiles(std::vector< rtl::OUString > const & uris);
+
+ bool removeLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
+ bool removeListener);
+
+ void removeImplementation(rtl::OUString name);
+
+ boost::shared_ptr< Implementation > findServiceImplementation(
+ rtl::OUString const & specifier);
+
+ void loadImplementation(Implementation * implementation);
+
+ css::uno::Reference< css::uno::XComponentContext > context_;
+ Data data_;
+};
+
+rtl::OUString ServiceManager::getImplementationName()
+ throw (css::uno::RuntimeException)
+{
+ return rtl::OUString(
+ "com.sun.star.comp.cppuhelper.bootstrap.ServiceManager");
+}
+
+sal_Bool ServiceManager::supportsService(rtl::OUString const & ServiceName)
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Sequence< rtl::OUString > names(getSupportedServiceNames());
+ for (sal_Int32 i = 0; i != names.getLength(); ++i) {
+ if (ServiceName == names[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+css::uno::Sequence< rtl::OUString > ServiceManager::getSupportedServiceNames()
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Sequence< rtl::OUString > names(2);
+ names[0] = "com.sun.star.lang.MultiServiceFactory";
+ names[1] = "com.sun.star.lang.ServiceManager";
+ return names;
+}
+
+css::uno::Reference< css::uno::XInterface > ServiceManager::createInstance(
+ rtl::OUString const & aServiceSpecifier)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ assert(context_.is());
+ return createInstanceWithContext(aServiceSpecifier, context_);
+}
+
+css::uno::Reference< css::uno::XInterface >
+ServiceManager::createInstanceWithArguments(
+ rtl::OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ assert(context_.is());
+ return createInstanceWithArgumentsAndContext(
+ ServiceSpecifier, Arguments, context_);
+}
+
+css::uno::Sequence< rtl::OUString > ServiceManager::getAvailableServiceNames()
+ throw (css::uno::RuntimeException)
+{
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (isDisposed()) {
+ return css::uno::Sequence< rtl::OUString >();
+ }
+ ImplementationMap::size_type n = data_.services.size();
+ if (n > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
+ throw css::uno::RuntimeException(
+ "getAvailableServiceNames: too many services",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ css::uno::Sequence< rtl::OUString > names(static_cast< sal_Int32 >(n));
+ sal_Int32 i = 0;
+ for (ImplementationMap::const_iterator j(data_.services.begin());
+ j != data_.services.end(); ++j)
+ {
+ names[i++] = j->first;
+ }
+ assert(i == names.getLength());
+ return names;
+}
+
+css::uno::Reference< css::uno::XInterface >
+ServiceManager::createInstanceWithContext(
+ rtl::OUString const & aServiceSpecifier,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ boost::shared_ptr< Implementation > impl(
+ findServiceImplementation(aServiceSpecifier));
+ if (impl.get() == 0) {
+ return css::uno::Reference< css::uno::XInterface >();
+ }
+ if (impl->factory1.is()) {
+ return impl->factory1->createInstanceWithContext(Context);
+ }
+ if (impl->factory2.is()) {
+ return impl->factory2->createInstance();
+ }
+ throw css::uno::DeploymentException(
+ "Implementation " + impl->name + " does not provide a factory",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Reference< css::uno::XInterface >
+ServiceManager::createInstanceWithArgumentsAndContext(
+ rtl::OUString const & ServiceSpecifier,
+ css::uno::Sequence< css::uno::Any > const & Arguments,
+ css::uno::Reference< css::uno::XComponentContext > const & Context)
+ throw (css::uno::Exception, css::uno::RuntimeException)
+{
+ boost::shared_ptr< Implementation > impl(
+ findServiceImplementation(ServiceSpecifier));
+ if (impl.get() == 0) {
+ return css::uno::Reference< css::uno::XInterface >();
+ }
+ if (impl->factory1.is()) {
+ return impl->factory1->createInstanceWithArgumentsAndContext(
+ Arguments, Context);
+ }
+ if (impl->factory2.is()) {
+ return impl->factory2->createInstanceWithArguments(Arguments);
+ }
+ throw css::uno::DeploymentException(
+ "Implementation " + impl->name + " does not provide a factory",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+css::uno::Type ServiceManager::getElementType()
+ throw (css::uno::RuntimeException)
+{
+ return css::uno::Type();
+}
+
+sal_Bool ServiceManager::hasElements() throw (css::uno::RuntimeException) {
+ return
+ !(data_.namedImplementations.empty()
+ && data_.dynamicImplementations.empty());
+}
+
+css::uno::Reference< css::container::XEnumeration >
+ServiceManager::createEnumeration() throw (css::uno::RuntimeException) {
+ throw css::uno::RuntimeException(
+ "ServiceManager createEnumeration: method not supported",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+sal_Bool ServiceManager::has(css::uno::Any const &)
+ throw (css::uno::RuntimeException)
+{
+ throw css::uno::RuntimeException(
+ "ServiceManager has: method not supported",
+ static_cast< cppu::OWeakObject * >(this));
+}
+
+void ServiceManager::insert(css::uno::Any const & aElement)
+ throw (
+ css::lang::IllegalArgumentException,
+ css::container::ElementExistException, css::uno::RuntimeException)
+{
+ css::uno::Sequence< css::beans::NamedValue > args;
+ if (aElement >>= args) {
+ std::vector< rtl::OUString > uris;
+ css::uno::Reference< css::uno::XComponentContext > alienContext;
+ for (sal_Int32 i = 0; i < args.getLength(); ++i) {
+ if (args[i].Name == "uri") {
+ rtl::OUString uri;
+ if (!(args[i].Value >>= uri)) {
+ throw css::lang::IllegalArgumentException(
+ "Bad uri argument",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ uris.push_back(uri);
+ } else if (args[i].Name == "component-context") {
+ if (alienContext.is()) {
+ throw css::lang::IllegalArgumentException(
+ "Multiple component-context arguments",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ if (!(args[i].Value >>= alienContext) || !alienContext.is()) {
+ throw css::lang::IllegalArgumentException(
+ "Bad component-context argument",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ } else {
+ throw css::lang::IllegalArgumentException(
+ "Bad argument " + args[i].Name,
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ }
+ insertRdbFiles(uris, alienContext);
+ return;
+ }
+ css::uno::Reference< css::lang::XServiceInfo > info;
+ if ((aElement >>= info) && info.is()) {
+ insertLegacyFactory(info);
+ return;
+ }
+ throw css::lang::IllegalArgumentException(
+ "Bad insert element", static_cast< cppu::OWeakObject * >(this), 0);
+}
+
+void ServiceManager::remove(css::uno::Any const & aElement)
+ throw (
+ css::lang::IllegalArgumentException,
+ css::container::NoSuchElementException, css::uno::RuntimeException)
+{
+ css::uno::Sequence< css::beans::NamedValue > args;
+ if (aElement >>= args) {
+ std::vector< rtl::OUString > uris;
+ for (sal_Int32 i = 0; i < args.getLength(); ++i) {
+ if (args[i].Name == "uri") {
+ rtl::OUString uri;
+ if (!(args[i].Value >>= uri)) {
+ throw css::lang::IllegalArgumentException(
+ "Bad uri argument",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ uris.push_back(uri);
+ } else {
+ throw css::lang::IllegalArgumentException(
+ "Bad argument " + args[i].Name,
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ }
+ removeRdbFiles(uris);
+ return;
+ }
+ css::uno::Reference< css::lang::XServiceInfo > info;
+ if ((aElement >>= info) && info.is()) {
+ if (!removeLegacyFactory(info, true)) {
+ throw css::container::NoSuchElementException(
+ "Remove non-inserted factory object",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return;
+ }
+ rtl::OUString impl;
+ if (aElement >>= impl) {
+ // For live-removal of extensions:
+ removeImplementation(impl);
+ return;
+ }
+ throw css::lang::IllegalArgumentException(
+ "Bad remove element", static_cast< cppu::OWeakObject * >(this), 0);
+}
+
+css::uno::Reference< css::container::XEnumeration >
+ServiceManager::createContentEnumeration(rtl::OUString const & aServiceName)
+ throw (css::uno::RuntimeException)
+{
+ std::vector< boost::shared_ptr< Implementation > > impls;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ ImplementationMap::const_iterator i(data_.services.find(aServiceName));
+ if (i != data_.services.end()) {
+ impls = i->second;
+ }
+ }
+ std::vector< css::uno::Any > factories;
+ for (std::vector< boost::shared_ptr< Implementation > >::const_iterator i(
+ impls.begin());
+ i != impls.end(); ++i)
+ {
+ Implementation * impl = i->get();
+ assert(impl != 0);
+ bool loaded;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (isDisposed()) {
+ factories.clear();
+ break;
+ }
+ loaded = impl->loaded;
+ }
+ //TODO: There is a race here, as the relevant service factory can be
+ // removed while the mutex is unlocked and loading can thus fail, as the
+ // entity from which to load can disappear once the service factory is
+ // removed.
+ if (!loaded) {
+ loadImplementation(impl);
+ }
+ if (impl->factory1.is()) {
+ factories.push_back(css::uno::makeAny(impl->factory1));
+ } else if (impl->factory2.is()) {
+ factories.push_back(css::uno::makeAny(impl->factory2));
+ } else {
+ throw css::uno::DeploymentException(
+ "Implementation " + impl->name + " does not provide a factory",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ }
+ return new ContentEnumeration(factories);
+}
+
+css::uno::Reference< css::beans::XPropertySetInfo >
+ServiceManager::getPropertySetInfo() throw (css::uno::RuntimeException) {
+ return this;
+}
+
+void ServiceManager::setPropertyValue(
+ rtl::OUString const & aPropertyName, css::uno::Any const &)
+ throw (
+ css::beans::UnknownPropertyException, css::beans::PropertyVetoException,
+ css::lang::IllegalArgumentException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ if (aPropertyName == "DefaultContext") {
+ throw css::beans::PropertyVetoException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ } else {
+ throw css::beans::UnknownPropertyException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+}
+
+css::uno::Any ServiceManager::getPropertyValue(
+ rtl::OUString const & PropertyName)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ if (PropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ PropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ assert(context_.is());
+ return css::uno::makeAny(context_);
+}
+
+void ServiceManager::addPropertyChangeListener(
+ rtl::OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ xListener)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ // DefaultContext does not change, so just treat it as an event listener:
+ return addEventListener(xListener.get());
+}
+
+void ServiceManager::removePropertyChangeListener(
+ rtl::OUString const & aPropertyName,
+ css::uno::Reference< css::beans::XPropertyChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ if (!aPropertyName.isEmpty() && aPropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ aPropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ // DefaultContext does not change, so just treat it as an event listener:
+ return removeEventListener(aListener.get());
+}
+
+void ServiceManager::addVetoableChangeListener(
+ rtl::OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ PropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ // DefaultContext does not change, so just treat it as an event listener:
+ return addEventListener(aListener.get());
+}
+
+void ServiceManager::removeVetoableChangeListener(
+ rtl::OUString const & PropertyName,
+ css::uno::Reference< css::beans::XVetoableChangeListener > const &
+ aListener)
+ throw (
+ css::beans::UnknownPropertyException, css::lang::WrappedTargetException,
+ css::uno::RuntimeException)
+{
+ if (!PropertyName.isEmpty() && PropertyName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ PropertyName, static_cast< cppu::OWeakObject * >(this));
+ }
+ // DefaultContext does not change, so just treat it as an event listener:
+ return removeEventListener(aListener.get());
+}
+
+css::uno::Sequence< css::beans::Property > ServiceManager::getProperties()
+ throw (css::uno::RuntimeException)
+{
+ css::uno::Sequence< css::beans::Property > props(1);
+ props[0] = getDefaultContextProperty();
+ return props;
+}
+
+css::beans::Property ServiceManager::getPropertyByName(
+ rtl::OUString const & aName)
+ throw (css::beans::UnknownPropertyException, css::uno::RuntimeException)
+{
+ if (aName != "DefaultContext") {
+ throw css::beans::UnknownPropertyException(
+ aName, static_cast< cppu::OWeakObject * >(this));
+ }
+ return getDefaultContextProperty();
+}
+
+sal_Bool ServiceManager::hasPropertyByName(rtl::OUString const & Name)
+ throw (css::uno::RuntimeException)
+{
+ return Name == "DefaultContext";
+}
+
+void ServiceManager::disposing(css::lang::EventObject const & Source)
+ throw (css::uno::RuntimeException)
+{
+ removeLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo >(
+ Source.Source, css::uno::UNO_QUERY_THROW),
+ false);
+}
+
+void ServiceManager::disposing() {
+ std::vector< css::uno::Reference< css::lang::XComponent > > comps;
+ css::uno::Reference< css::lang::XEventListener > listener;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ for (DynamicImplementations::const_iterator i(
+ data_.dynamicImplementations.begin());
+ i != data_.dynamicImplementations.end(); ++i)
+ {
+ assert(i->second.get() != 0);
+ if (i->second->component.is()) {
+ comps.push_back(i->second->component);
+ }
+ }
+ data_.namedImplementations.clear();
+ data_.dynamicImplementations.clear();
+ data_.services.clear();
+ data_.singletons.clear();
+ }
+ for (std::vector<
+ css::uno::Reference< css::lang::XComponent > >::const_iterator i(
+ comps.begin());
+ i != comps.end(); ++i)
+ {
+ removeEventListenerFromComponent(*i);
+ }
+}
+
+void ServiceManager::removeEventListenerFromComponent(
+ css::uno::Reference< css::lang::XComponent > const & component)
+{
+ assert(component.is());
+ try {
+ component->removeEventListener(this);
+ } catch (css::uno::RuntimeException & e) {
+ SAL_INFO(
+ "cppuhelper",
+ "Ignored removeEventListener RuntimeException " + e.Message);
+ }
+}
+
+void ServiceManager::readRdbs(rtl::OUString const & uris) {
+ for (sal_Int32 i = 0; i != -1;) {
+ rtl::OUString uri(uris.getToken(0, ' ', i));
+ if (uri.isEmpty()) {
+ continue;
+ }
+ bool optional;
+ bool directory;
+ decodeRdbUri(&uri, &optional, &directory);
+ if (directory) {
+ readRdbDirectory(uri, optional);
+ } else {
+ readRdbFile(uri, optional);
+ }
+ }
+}
+
+void ServiceManager::readRdbDirectory(rtl::OUString const & uri, bool optional)
+{
+ osl::Directory dir(uri);
+ switch (dir.open()) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ if (optional) {
+ SAL_INFO("cppuhelper", "Ignored optional " << uri);
+ return;
+ }
+ // fall through
+ default:
+ throw css::uno::DeploymentException(
+ "Cannot open directory " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ for (;;) {
+ rtl::OUString url;
+ if (!nextDirectoryItem(dir, &url)) {
+ break;
+ }
+ readRdbFile(url, false);
+ }
+}
+
+void ServiceManager::readRdbFile(rtl::OUString const & uri, bool optional) {
+ try {
+ Parser(
+ uri, css::uno::Reference< css::uno::XComponentContext >(), &data_);
+ } catch (css::container::NoSuchElementException &SB) {
+ if (!optional) {
+ throw css::uno::DeploymentException(
+ uri + ": no such file",
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ SAL_INFO("cppuhelper", "Ignored optional " << uri);
+ } catch (css::registry::InvalidRegistryException & e) {
+ throw css::uno::DeploymentException(
+ "InvalidRegistryException: " + e.Message,
+ static_cast< cppu::OWeakObject * >(this));
+ } catch (css::uno::RuntimeException &SB) {
+ if (!readLegacyRdbFile(uri)) {
+ throw;
+ }
+ }
+}
+
+bool ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
+ Registry reg;
+ switch (reg.open(uri, REG_READONLY)) {
+ case REG_NO_ERROR:
+ break;
+ case REG_REGISTRY_NOT_EXISTS:
+ case REG_INVALID_REGISTRY:
+ {
+ // Ignore empty rdb files (which are at least seen by subordinate
+ // uno processes during extension registration; Registry::open can
+ // fail on them if mmap(2) returns EINVAL for a zero length):
+ osl::DirectoryItem item;
+ if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
+ osl::FileStatus status(osl_FileStatus_Mask_FileSize);
+ if (item.getFileStatus(status) == osl::FileBase::E_None
+ && status.getFileSize() == 0)
+ {
+ return true;
+ }
+ }
+ }
+ // fall through
+ default:
+ return false;
+ }
+ RegistryKey rootKey;
+ if (reg.openRootKey(rootKey) != REG_NO_ERROR) {
+ throw css::uno::DeploymentException(
+ "Failure reading legacy rdb file " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ RegistryKeyArray impls;
+ if (rootKey.openSubKeys("IMPLEMENTATIONS", impls) != REG_NO_ERROR) {
+ throw css::uno::DeploymentException(
+ "Failure reading legacy rdb file " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ for (sal_uInt32 i = 0; i != impls.getLength(); ++i) {
+ RegistryKey implKey(impls.getElement(i));
+ assert(implKey.getName().match("/IMPLEMENTATIONS/"));
+ rtl::OUString name(
+ implKey.getName().copy(RTL_CONSTASCII_LENGTH("/IMPLEMENTATIONS/")));
+ boost::shared_ptr< Implementation > impl(
+ new Implementation(
+ name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"),
+ readLegacyRdbString(uri, implKey, "UNO/LOCATION")));
+ if (!data_.namedImplementations.insert(
+ NamedImplementations::value_type(name, impl)).
+ second)
+ {
+ throw css::registry::InvalidRegistryException(
+ uri + ": duplicate <implementation name=\"" + name + "\">",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ readLegacyRdbStrings(uri, implKey, "UNO/SERVICES", &impl->services);
+ for (std::vector< rtl::OUString >::const_iterator j(
+ impl->services.begin());
+ j != impl->services.end(); ++j)
+ {
+ data_.services[*j].push_back(impl);
+ }
+ readLegacyRdbStrings(uri, implKey, "UNO/SINGLETONS", &impl->singletons);
+ for (std::vector< rtl::OUString >::const_iterator j(
+ impl->singletons.begin());
+ j != impl->singletons.end(); ++j)
+ {
+ data_.singletons[*j].push_back(impl);
+ }
+ }
+ return true;
+}
+
+rtl::OUString ServiceManager::readLegacyRdbString(
+ rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path)
+{
+ RegistryKey subkey;
+ RegValueType t;
+ sal_uInt32 s;
+ if (key.openKey(path, subkey) != REG_NO_ERROR
+ || subkey.getValueInfo(rtl::OUString(), &t, &s) != REG_NO_ERROR
+ || t != RG_VALUETYPE_STRING
+ || s == 0 || s > static_cast< sal_uInt32 >(SAL_MAX_INT32))
+ {
+ throw css::uno::DeploymentException(
+ "Failure reading legacy rdb file " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ rtl::OUString val;
+ std::vector< char > v(s); // assuming sal_uInt32 fits into vector::size_type
+ if (subkey.getValue(rtl::OUString(), &v[0]) != REG_NO_ERROR
+ || v.back() != '\0'
+ || !rtl_convertStringToUString(
+ &val.pData, &v[0], static_cast< sal_Int32 >(s - 1),
+ RTL_TEXTENCODING_UTF8,
+ (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+ | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
+ {
+ throw css::uno::DeploymentException(
+ "Failure reading legacy rdb file " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ return val;
+}
+
+void ServiceManager::readLegacyRdbStrings(
+ rtl::OUString const & uri, RegistryKey & key, rtl::OUString const & path,
+ std::vector< rtl::OUString > * strings)
+{
+ assert(strings != 0);
+ RegistryKey subkey;
+ switch (key.openKey(path, subkey)) {
+ case REG_NO_ERROR:
+ break;
+ case REG_KEY_NOT_EXISTS:
+ return;
+ default:
+ throw css::uno::DeploymentException(
+ "Failure reading legacy rdb file " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ rtl::OUString prefix(subkey.getName() + "/");
+ RegistryKeyNames names;
+ if (subkey.getKeyNames(rtl::OUString(), names) != REG_NO_ERROR) {
+ throw css::uno::DeploymentException(
+ "Failure reading legacy rdb file " + uri,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
+ assert(names.getElement(i).match(prefix));
+ strings->push_back(names.getElement(i).copy(prefix.getLength()));
+ }
+}
+
+void ServiceManager::insertRdbFiles(
+ std::vector< rtl::OUString > const & uris,
+ css::uno::Reference< css::uno::XComponentContext > const & alienContext)
+{
+ Data extra;
+ for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
+ i != uris.end(); ++i)
+ {
+ try {
+ Parser(*i, alienContext, &extra);
+ } catch (css::container::NoSuchElementException &) {
+ throw css::lang::IllegalArgumentException(
+ *i + ": no such file", static_cast< cppu::OWeakObject * >(this),
+ 0);
+ } catch (css::registry::InvalidRegistryException & e) {
+ throw css::lang::IllegalArgumentException(
+ "InvalidRegistryException: " + e.Message,
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ }
+ insertExtraData(extra);
+}
+
+void ServiceManager::insertLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo)
+{
+ assert(factoryInfo.is());
+ rtl::OUString name(factoryInfo->getImplementationName());
+ css::uno::Reference< css::lang::XSingleComponentFactory > f1(
+ factoryInfo, css::uno::UNO_QUERY);
+ css::uno::Reference< css::lang::XSingleServiceFactory > f2;
+ if (!f1.is()) {
+ f2 = css::uno::Reference< css::lang::XSingleServiceFactory >(
+ factoryInfo, css::uno::UNO_QUERY);
+ }
+ css::uno::Reference< css::lang::XComponent > comp(
+ factoryInfo, css::uno::UNO_QUERY);
+ boost::shared_ptr< Implementation > impl(
+ new Implementation(name, f1, f2, comp));
+ Data extra;
+ if (!name.isEmpty()) {
+ extra.namedImplementations.insert(
+ NamedImplementations::value_type(name, impl));
+ }
+ extra.dynamicImplementations.insert(
+ DynamicImplementations::value_type(factoryInfo, impl));
+ css::uno::Sequence< rtl::OUString > services(
+ factoryInfo->getSupportedServiceNames());
+ for (sal_Int32 i = 0; i != services.getLength(); ++i) {
+ impl->services.push_back(services[i]);
+ extra.services[services[i]].push_back(impl);
+ }
+ if (insertExtraData(extra) && comp.is()) {
+ comp->addEventListener(this);
+ }
+}
+
+bool ServiceManager::insertExtraData(Data const & extra) {
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (isDisposed()) {
+ return false;
+ }
+ for (NamedImplementations::const_iterator i(
+ extra.namedImplementations.begin());
+ i != extra.namedImplementations.end(); ++i)
+ {
+ if (data_.namedImplementations.find(i->first)
+ != data_.namedImplementations.end())
+ {
+ throw css::lang::IllegalArgumentException(
+ "Insert duplicate implementation name " + i->first,
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ }
+ for (DynamicImplementations::const_iterator i(
+ extra.dynamicImplementations.begin());
+ i != extra.dynamicImplementations.end(); ++i)
+ {
+ if (data_.dynamicImplementations.find(i->first)
+ != data_.dynamicImplementations.end())
+ {
+ throw css::lang::IllegalArgumentException(
+ "Insert duplicate factory object",
+ static_cast< cppu::OWeakObject * >(this), 0);
+ }
+ }
+ //TODO: The below leaves data_ in an inconsistent state upon exceptions:
+ data_.namedImplementations.insert(
+ extra.namedImplementations.begin(),
+ extra.namedImplementations.end());
+ data_.dynamicImplementations.insert(
+ extra.dynamicImplementations.begin(),
+ extra.dynamicImplementations.end());
+ insertImplementationMap(&data_.services, extra.services);
+ insertImplementationMap(&data_.singletons, extra.singletons);
+ }
+ //TODO: Updating the component context singleton data should be part of the
+ // atomic service manager update:
+ if (!extra.singletons.empty()) {
+ assert(context_.is());
+ css::uno::Reference< css::container::XNameContainer > cont(
+ context_, css::uno::UNO_QUERY_THROW);
+ for (ImplementationMap::const_iterator i(extra.singletons.begin());
+ i != extra.singletons.end(); ++i)
+ {
+ rtl::OUString name("/singletons/" + i->first);
+ //TODO: Update should be atomic:
+ try {
+ cont->removeByName(name + "/arguments");
+ } catch (const css::container::NoSuchElementException &) {}
+ assert(!i->second.empty());
+ assert(i->second[0].get() != 0);
+ SAL_INFO_IF(
+ i->second.size() > 1, "cppuhelper",
+ "Arbitrarily chosing " << i->second[0]->name
+ << " among multiple implementations for singleton "
+ << i->first);
+ try {
+ cont->insertByName(
+ name + "/service", css::uno::Any(i->second[0]->name));
+ } catch (css::container::ElementExistException &) {
+ cont->replaceByName(
+ name + "/service", css::uno::Any(i->second[0]->name));
+ }
+ try {
+ cont->insertByName(name, css::uno::Any());
+ } catch (css::container::ElementExistException &) {
+ SAL_INFO("cppuhelper", "Overwriting singleton " << i->first);
+ cont->replaceByName(name, css::uno::Any());
+ }
+ }
+ }
+ return true;
+}
+
+void ServiceManager::removeRdbFiles(std::vector< rtl::OUString > const & uris) {
+ // The underlying data structures make this function somewhat inefficient,
+ // but the assumption is that it is rarely called (and that if it is called,
+ // it is called with a uris vector of size one):
+ osl::MutexGuard g(rBHelper.rMutex);
+ for (std::vector< rtl::OUString >::const_iterator i(uris.begin());
+ i != uris.end(); ++i)
+ {
+ for (NamedImplementations::iterator j(
+ data_.namedImplementations.begin());
+ j != data_.namedImplementations.end();)
+ {
+ assert(j->second.get() != 0);
+ if (j->second->uri == *i) {
+ //TODO: The below leaves data_ in an inconsistent state upon
+ // exceptions:
+ removeFromImplementationMap(
+ &data_.services, j->second->services, j->second);
+ removeFromImplementationMap(
+ &data_.singletons, j->second->singletons, j->second);
+ data_.namedImplementations.erase(j++);
+ } else {
+ ++j;
+ }
+ }
+ }
+ //TODO: Update the component context singleton data
+}
+
+bool ServiceManager::removeLegacyFactory(
+ css::uno::Reference< css::lang::XServiceInfo > const & factoryInfo,
+ bool removeListener)
+{
+ assert(factoryInfo.is());
+ css::uno::Reference< css::lang::XComponent > comp;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ DynamicImplementations::const_iterator i(
+ data_.dynamicImplementations.find(factoryInfo));
+ if (i == data_.dynamicImplementations.end()) {
+ return isDisposed();
+ }
+ assert(i->second.get() != 0);
+ //TODO: The below leaves data_ in an inconsistent state upon exceptions:
+ removeFromImplementationMap(
+ &data_.services, i->second->services, i->second);
+ removeFromImplementationMap(
+ &data_.singletons, i->second->singletons, i->second);
+ if (!i->second->name.isEmpty()) {
+ data_.namedImplementations.erase(i->second->name);
+ }
+ data_.dynamicImplementations.erase(i);
+ if (removeListener) {
+ comp = i->second->component;
+ }
+ }
+ if (comp.is()) {
+ removeEventListenerFromComponent(comp);
+ }
+ return true;
+}
+
+void ServiceManager::removeImplementation(rtl::OUString name) {
+ // The underlying data structures make this function somewhat inefficient,
+ // but the assumption is that it is rarely called:
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (isDisposed()) {
+ return;
+ }
+ NamedImplementations::iterator i(data_.namedImplementations.find(name));
+ if (i == data_.namedImplementations.end()) {
+ throw css::container::NoSuchElementException(
+ "Remove non-inserted implementation " + name,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ assert(i->second.get() != 0);
+ //TODO: The below leaves data_ in an inconsistent state upon exceptions:
+ removeFromImplementationMap(
+ &data_.services, i->second->services, i->second);
+ removeFromImplementationMap(
+ &data_.singletons, i->second->singletons, i->second);
+ for (DynamicImplementations::iterator j(
+ data_.dynamicImplementations.begin());
+ j != data_.dynamicImplementations.end(); ++j)
+ {
+ if (j->second == i->second) {
+ data_.dynamicImplementations.erase(j);
+ break;
+ }
+ }
+ data_.namedImplementations.erase(i);
+}
+
+boost::shared_ptr< Implementation > ServiceManager::findServiceImplementation(
+ rtl::OUString const & specifier)
+{
+ boost::shared_ptr< Implementation > impl;
+ bool loaded;
+ {
+ osl::MutexGuard g(rBHelper.rMutex);
+ ImplementationMap::const_iterator i(data_.services.find(specifier));
+ if (i == data_.services.end()) {
+ NamedImplementations::const_iterator j(
+ data_.namedImplementations.find(specifier));
+ if (j == data_.namedImplementations.end()) {
+ SAL_INFO("cppuhelper", "No implementation for " << specifier);
+ return boost::shared_ptr< Implementation >();
+ }
+ impl = j->second;
+ } else {
+ assert(!i->second.empty());
+ SAL_INFO_IF(
+ i->second.size() > 1, "cppuhelper",
+ "Arbitrarily chosing " << i->second[0]->name
+ << " among multiple implementations for " << i->first);
+ impl = i->second[0];
+ }
+ assert(impl.get() != 0);
+ loaded = impl->loaded;
+ }
+ //TODO: There is a race here, as the relevant service factory can be removed
+ // while the mutex is unlocked and loading can thus fail, as the entity from
+ // which to load can disappear once the service factory is removed.
+ if (!loaded) {
+ loadImplementation(impl.get());
+ }
+ return impl;
+}
+
+void ServiceManager::loadImplementation(Implementation * implementation) {
+ assert(implementation != 0);
+ rtl::OUString uri;
+ try {
+ uri = cppu::bootstrap_expandUri(implementation->uri);
+ } catch (css::lang::IllegalArgumentException & e) {
+ throw css::uno::DeploymentException(
+ "Cannot expand URI" + implementation->uri + ": " + e.Message,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ css::uno::Reference< css::uno::XInterface > f0;
+ // Shortcut loading via SharedLibrary loader, to pass in prefix argument
+ // (which the loader's activate implementation would normally obtain through
+ // the legacy xKey argument):
+ if (!implementation->alienContext.is()
+ && implementation->loader == "com.sun.star.loader.SharedLibrary")
+ {
+ rtl::OUString prefix(implementation->prefix);
+ if (!prefix.isEmpty()) {
+ prefix += "_";
+ }
+ try {
+ f0 = cppu::loadSharedLibComponentFactory(
+ uri, rtl::OUString(), implementation->name, this,
+ css::uno::Reference< css::registry::XRegistryKey >(), prefix);
+ } catch (css::loader::CannotActivateFactoryException & e) {
+ throw css::uno::DeploymentException(
+ "Cannot activate implementation " + uri + ": " + e.Message,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ } else {
+ SAL_INFO_IF(
+ !implementation->prefix.isEmpty(), "cppuhelper",
+ "Loader " << implementation->loader << " and non-empty prefix "
+ << implementation->prefix);
+ css::uno::Reference< css::uno::XComponentContext > ctxt;
+ css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
+ if (implementation->alienContext.is()) {
+ ctxt = implementation->alienContext;
+ smgr = css::uno::Reference< css::lang::XMultiComponentFactory >(
+ ctxt->getServiceManager(), css::uno::UNO_SET_THROW);
+ } else {
+ assert(context_.is());
+ ctxt = context_;
+ smgr = this;
+ }
+ css::uno::Reference< css::loader::XImplementationLoader > loader(
+ smgr->createInstanceWithContext(implementation->loader, ctxt),
+ css::uno::UNO_QUERY_THROW);
+ try {
+ f0 = loader->activate(
+ implementation->name, rtl::OUString(), uri,
+ css::uno::Reference< css::registry::XRegistryKey >());
+ } catch (css::loader::CannotActivateFactoryException & e) {
+ throw css::uno::DeploymentException(
+ "Cannot activate implementation " + uri + ": " + e.Message,
+ static_cast< cppu::OWeakObject * >(this));
+ }
+ }
+ css::uno::Reference< css::lang::XSingleComponentFactory > f1(
+ f0, css::uno::UNO_QUERY);
+ css::uno::Reference< css::lang::XSingleServiceFactory > f2;
+ if (!f1.is()) {
+ f2 = css::uno::Reference< css::lang::XSingleServiceFactory >(
+ f0, css::uno::UNO_QUERY);
+ }
+ osl::MutexGuard g(rBHelper.rMutex);
+ if (!(isDisposed() || implementation->loaded)) {
+ implementation->loaded = true;
+ implementation->factory1 = f1;
+ implementation->factory2 = f2;
+ }
+}
+
+css::uno::Reference< css::uno::XComponentContext > bootstrapComponentContext(
+ css::uno::Reference< css::registry::XSimpleRegistry > const & typeRegistry,
+ rtl::OUString const & serviceUris, rtl::Bootstrap const & bootstrap)
+{
+ rtl::Reference< ServiceManager > smgr(new ServiceManager(serviceUris));
+ cppu::ContextEntry_Init entry;
+ std::vector< cppu::ContextEntry_Init > context_values;
+ context_values.push_back(
+ cppu::ContextEntry_Init(
+ "/singletons/com.sun.star.lang.theServiceManager",
+ css::uno::makeAny(
+ css::uno::Reference< css::uno::XInterface >(
+ static_cast< cppu::OWeakObject * >(smgr.get()))),
+ false));
+ context_values.push_back( //TODO: from services.rdb?
+ cppu::ContextEntry_Init(
+ "/singletons/com.sun.star.reflection.theTypeDescriptionManager",
+ css::uno::makeAny(
+ rtl::OUString("com.sun.star.comp.stoc.TypeDescriptionManager")),
+ true /*TODO: false?*/));
+ context_values.push_back( //TODO: from services.rdb?
+ cppu::ContextEntry_Init(
+ "/singletons/com.sun.star.util.theMacroExpander",
+ css::uno::makeAny(
+ cppuhelper::detail::create_bootstrap_macro_expander_factory()),
+ true));
+ Data const & data = smgr->getData();
+ for (ImplementationMap::const_iterator i(data.singletons.begin());
+ i != data.singletons.end(); ++i)
+ {
+ assert(!i->second.empty());
+ assert(i->second[0].get() != 0);
+ SAL_INFO_IF(
+ i->second.size() > 1, "cppuhelper",
+ "Arbitrarily chosing " << i->second[0]->name
+ << " among multiple implementations for " << i->first);
+ context_values.push_back(
+ cppu::ContextEntry_Init(
+ "/singletons/" + i->first,
+ css::uno::makeAny(i->second[0]->name), true));
+ }
+ cppu::add_access_control_entries(&context_values, bootstrap);
+ assert(!context_values.empty());
+ css::uno::Reference< css::uno::XComponentContext > context(
+ createComponentContext(
+ &context_values[0], context_values.size(),
+ css::uno::Reference< css::uno::XComponentContext >()));
+ smgr->setContext(context);
+ css::uno::Reference< css::container::XHierarchicalNameAccess > tdmgr(
+ context->getValueByName(
+ "/singletons/com.sun.star.reflection.theTypeDescriptionManager"),
+ css::uno::UNO_QUERY_THROW);
+ if (typeRegistry.is()) {
+ css::uno::Sequence< css::uno::Any > arg(1);
+ arg[0] <<= typeRegistry;
+ css::uno::Reference< css::container::XSet >(
+ tdmgr, css::uno::UNO_QUERY_THROW)->
+ insert(
+ css::uno::makeAny(
+ smgr->createInstanceWithArgumentsAndContext(
+ ("com.sun.star.comp.stoc"
+ ".RegistryTypeDescriptionProvider"),
+ arg, context)));
+ }
+ cppu::installTypeDescriptionManager(tdmgr);
+ return context;
+}
+
+rtl::OUString getBootstrapVariable(
+ rtl::Bootstrap const & bootstrap, rtl::OUString const & name)
+{
+ rtl::OUString v;
+ if (!bootstrap.getFrom(name, v)) {
+ throw css::uno::DeploymentException(
+ "Cannot obtain " + name + " from uno ini",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return v;
+}
+
+css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbFile(
+ rtl::OUString const & uri, bool optional,
+ css::uno::Reference< css::registry::XSimpleRegistry > const & lastRegistry,
+ css::uno::Reference< css::lang::XSingleServiceFactory > const &
+ simpleRegistryFactory,
+ css::uno::Reference< css::lang::XSingleServiceFactory > const &
+ nestedRegistryFactory)
+{
+ assert(simpleRegistryFactory.is() && nestedRegistryFactory.is());
+ try {
+ css::uno::Reference< css::registry::XSimpleRegistry > simple(
+ simpleRegistryFactory->createInstance(), css::uno::UNO_QUERY_THROW);
+ simple->open(uri, true, false);
+ if (lastRegistry.is()) {
+ css::uno::Reference< css::registry::XSimpleRegistry > nested(
+ nestedRegistryFactory->createInstance(),
+ 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) {
+ if (!optional) {
+ throw css::uno::DeploymentException(
+ "Invalid registry " + uri + ":" + e.Message,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ SAL_INFO("cppuhelper", "Ignored optional " << uri);
+ return lastRegistry;
+ }
+}
+
+css::uno::Reference< css::registry::XSimpleRegistry > readTypeRdbDirectory(
+ rtl::OUString const & uri, bool optional,
+ css::uno::Reference< css::registry::XSimpleRegistry > const & lastRegistry,
+ css::uno::Reference< css::lang::XSingleServiceFactory > const &
+ simpleRegistryFactory,
+ css::uno::Reference< css::lang::XSingleServiceFactory > const &
+ nestedRegistryFactory)
+{
+ assert(simpleRegistryFactory.is() && nestedRegistryFactory.is());
+ osl::Directory dir(uri);
+ switch (dir.open()) {
+ case osl::FileBase::E_None:
+ break;
+ case osl::FileBase::E_NOENT:
+ if (optional) {
+ SAL_INFO("cppuhelper", "Ignored optional " << uri);
+ return lastRegistry;
+ }
+ // fall through
+ default:
+ throw css::uno::DeploymentException(
+ "Cannot open directory " + uri,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ css::uno::Reference< css::registry::XSimpleRegistry > last(lastRegistry);
+ for (;;) {
+ rtl::OUString fileUri;
+ if (!nextDirectoryItem(dir, &fileUri)) {
+ break;
+ }
+ last = readTypeRdbFile(
+ fileUri, optional, last, simpleRegistryFactory,
+ nestedRegistryFactory);
+ }
+ return last;
+}
+
+css::uno::Reference< css::registry::XSimpleRegistry > createTypeRegistry(
+ rtl::OUString const & uris, rtl::OUString const & libraryDirectoryUri)
+{
+ css::uno::Reference< css::lang::XMultiComponentFactory > factory(
+ cppu::bootstrapInitialSF(libraryDirectoryUri));
+ css::uno::Reference< css::lang::XSingleServiceFactory > simpleRegs(
+ cppu::loadSharedLibComponentFactory(
+ "bootstrap.uno" SAL_DLLEXTENSION, libraryDirectoryUri,
+ "com.sun.star.comp.stoc.SimpleRegistry",
+ css::uno::Reference< css::lang::XMultiServiceFactory >(
+ factory, css::uno::UNO_QUERY_THROW),
+ css::uno::Reference< css::registry::XRegistryKey >()),
+ css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::lang::XSingleServiceFactory > nestedRegs(
+ cppu::loadSharedLibComponentFactory(
+ "bootstrap.uno" SAL_DLLEXTENSION, libraryDirectoryUri,
+ "com.sun.star.comp.stoc.NestedRegistry",
+ css::uno::Reference< css::lang::XMultiServiceFactory >(
+ factory, css::uno::UNO_QUERY_THROW),
+ css::uno::Reference< css::registry::XRegistryKey >()),
+ css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::registry::XSimpleRegistry > reg;
+ for (sal_Int32 i = 0; i != -1;) {
+ rtl::OUString uri(uris.getToken(0, ' ', i));
+ if (uri.isEmpty()) {
+ continue;
+ }
+ bool optional;
+ bool directory;
+ decodeRdbUri(&uri, &optional, &directory);
+ reg = directory
+ ? readTypeRdbDirectory(uri, optional, reg, simpleRegs, nestedRegs)
+ : readTypeRdbFile(uri, optional, reg, simpleRegs, nestedRegs);
+ }
+ return reg;
+}
+
+}
+
+css::uno::Reference< css::uno::XComponentContext >
+cppu::defaultBootstrap_InitialComponentContext(rtl::OUString const & iniUri)
+ SAL_THROW((css::uno::Exception))
+{
+ rtl::Bootstrap bs(iniUri);
+ if (bs.getHandle() == 0) {
+ throw css::uno::DeploymentException(
+ "Cannot open uno ini " + iniUri,
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ return bootstrapComponentContext(
+ createTypeRegistry(
+ getBootstrapVariable(bs, "UNO_TYPES"),
+ getBootstrapVariable(bs, "URE_INTERNAL_LIB_DIR")),
+ getBootstrapVariable(bs, "UNO_SERVICES"), bs);
+}
+
+css::uno::Reference< css::uno::XComponentContext >
+cppu::defaultBootstrap_InitialComponentContext()
+ SAL_THROW((css::uno::Exception))
+{
+ return defaultBootstrap_InitialComponentContext(getUnoIniUri());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/macro_expander.cxx b/cppuhelper/source/macro_expander.cxx
index 030e22f81ba7..7a82dd0ce888 100644
--- a/cppuhelper/source/macro_expander.cxx
+++ b/cppuhelper/source/macro_expander.cxx
@@ -40,6 +40,7 @@
#include "com/sun/star/uno/RuntimeException.hpp"
#include "macro_expander.hxx"
+#include "paths.hxx"
#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
#define SERVICE_NAME_A "com.sun.star.lang.MacroExpander"
@@ -54,8 +55,29 @@ using namespace ::com::sun::star::uno;
namespace cppu
{
-//---- private forward -----------------------------------------------------------------------------
-Bootstrap const & get_unorc() SAL_THROW(());
+
+Bootstrap const & get_unorc() SAL_THROW(())
+{
+ static rtlBootstrapHandle s_bstrap = 0;
+ if (! s_bstrap)
+ {
+ OUString iniName(getUnoIniUri());
+ rtlBootstrapHandle bstrap = rtl_bootstrap_args_open( iniName.pData );
+
+ ClearableMutexGuard guard( Mutex::getGlobalMutex() );
+ if (s_bstrap)
+ {
+ guard.clear();
+ rtl_bootstrap_args_close( bstrap );
+ }
+ else
+ {
+ s_bstrap = bstrap;
+ }
+ }
+ return *(Bootstrap const *)&s_bstrap;
+}
+
}
namespace cppuhelper { namespace detail {
diff --git a/cppuhelper/source/paths.cxx b/cppuhelper/source/paths.cxx
new file mode 100644
index 000000000000..d834e25dcab8
--- /dev/null
+++ b/cppuhelper/source/paths.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "sal/config.h"
+
+#include "com/sun/star/uno/DeploymentException.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "com/sun/star/uno/XInterface.hpp"
+#include "osl/module.hxx"
+#include "osl/mutex.hxx"
+#include "rtl/ustring.hxx"
+#include "sal/types.h"
+
+#include "paths.hxx"
+
+namespace {
+
+namespace css = com::sun::star;
+
+}
+
+rtl::OUString cppu::get_this_libpath() {
+ static rtl::OUString s_uri;
+ if (s_uri.isEmpty()) {
+ rtl::OUString uri;
+ osl::Module::getUrlFromAddress(
+ reinterpret_cast< oslGenericFunction >(get_this_libpath), uri);
+ sal_Int32 i = uri.lastIndexOf('/');
+ if (i == -1) {
+ throw css::uno::DeploymentException(
+ "URI " + uri + " is expected to contain a slash",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ uri = uri.copy(0, i);
+ osl::MutexGuard guard(osl::Mutex::getGlobalMutex());
+ if (s_uri.isEmpty()) {
+ s_uri = uri;
+ }
+ }
+ return s_uri;
+}
+
+rtl::OUString cppu::getUnoIniUri() {
+#if defined ANDROID
+ // Wouldn't it be lovely to avoid this fugly hard-coding.
+ // The problem is that the 'create_bootstrap_macro_expander_factory()'
+ // required for bootstrapping services, calls cppu::get_unorc directly
+ // instead of re-using the BoostrapHandle from:
+ // defaultBootstrap_InitialComponentContext
+ // and since rtlBootstrapHandle is not ref-counted doing anything
+ // clean here is hardish.
+ rtl::OUString uri("file:///assets/program");
+#else
+ rtl::OUString uri(get_this_libpath());
+#endif
+ return uri + "/" SAL_CONFIGFILE("uno");
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/paths.hxx b/cppuhelper/source/paths.hxx
new file mode 100644
index 000000000000..6586de9f15ad
--- /dev/null
+++ b/cppuhelper/source/paths.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef CPPUHELPER_SOURCE_PATHS_HXX
+#define CPPUHELPER_SOURCE_PATHS_HXX
+
+#include "sal/config.h"
+
+namespace rtl { class OUString; }
+
+namespace cppu {
+
+rtl::OUString get_this_libpath();
+
+rtl::OUString getUnoIniUri();
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/servicefactory.cxx b/cppuhelper/source/servicefactory.cxx
index 6ac95e76df93..2b7c9ede87c2 100644
--- a/cppuhelper/source/servicefactory.cxx
+++ b/cppuhelper/source/servicefactory.cxx
@@ -59,6 +59,8 @@
#endif
#include "macro_expander.hxx"
+#include "paths.hxx"
+#include "servicefactory_detail.hxx"
#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
@@ -75,9 +77,6 @@ namespace cppu
Reference< security::XAccessController >
createDefaultAccessController() SAL_THROW(());
-OUString const & get_this_libpath();
-
-
static Reference< XInterface > SAL_CALL createInstance(
Reference< XInterface > const & xFactory,
Reference< XComponentContext > const & xContext =
@@ -182,7 +181,7 @@ Reference< registry::XSimpleRegistry > SAL_CALL createNestedRegistry(
UNO_AC_POLICYFILE=<file_url> [optional]
-- read policy out of simple text file
*/
-static void add_access_control_entries(
+void add_access_control_entries(
::std::vector< ContextEntry_Init > * values,
Bootstrap const & bootstrap )
SAL_THROW( (Exception) )
diff --git a/cppuhelper/source/servicefactory_detail.hxx b/cppuhelper/source/servicefactory_detail.hxx
new file mode 100644
index 000000000000..89485b537d94
--- /dev/null
+++ b/cppuhelper/source/servicefactory_detail.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_CPPUHELPER_SOURCE_SERVICEFACTORY_DETAIL_HXX
+#define INCLUDED_CPPUHELPER_SOURCE_SERVICEFACTORY_DETAIL_HXX
+
+#include "sal/config.h"
+
+#include <vector>
+
+#include "com/sun/star/uno/Exception.hpp"
+#include "com/sun/star/uno/Reference.hxx"
+#include "sal/types.h"
+
+namespace com { namespace sun { namespace star { namespace lang {
+ class XMultiComponentFactory;
+} } } }
+namespace cppu { struct ContextEntry_Init; }
+namespace rtl {
+ class Bootstrap;
+ class OUString;
+}
+
+namespace cppu {
+
+void add_access_control_entries(
+ std::vector< cppu::ContextEntry_Init > * values,
+ rtl::Bootstrap const & bootstrap)
+ SAL_THROW((com::sun::star::uno::Exception));
+
+com::sun::star::uno::Reference< com::sun::star::lang::XMultiComponentFactory >
+bootstrapInitialSF(rtl::OUString const & rBootstrapPath)
+ SAL_THROW((com::sun::star::uno::Exception));
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */