diff options
-rw-r--r-- | cppuhelper/Library_cppuhelper.mk | 4 | ||||
-rw-r--r-- | cppuhelper/inc/cppuhelper/bootstrap.hxx | 32 | ||||
-rw-r--r-- | cppuhelper/prj/build.lst | 2 | ||||
-rw-r--r-- | cppuhelper/source/bootstrap.cxx | 470 | ||||
-rw-r--r-- | cppuhelper/source/defaultbootstrap.cxx | 1980 | ||||
-rw-r--r-- | cppuhelper/source/macro_expander.cxx | 26 | ||||
-rw-r--r-- | cppuhelper/source/paths.cxx | 84 | ||||
-rw-r--r-- | cppuhelper/source/paths.hxx | 46 | ||||
-rw-r--r-- | cppuhelper/source/servicefactory.cxx | 7 | ||||
-rw-r--r-- | cppuhelper/source/servicefactory_detail.hxx | 64 | ||||
-rw-r--r-- | desktop/source/deployment/registry/component/dp_component.cxx | 405 | ||||
-rw-r--r-- | stoc/source/simpleregistry/simpleregistry.cxx | 94 | ||||
-rw-r--r-- | stoc/source/simpleregistry/textualservices.cxx | 11 | ||||
-rw-r--r-- | stoc/source/simpleregistry/textualservices.hxx | 3 | ||||
-rw-r--r-- | udkapi/com/sun/star/lang/ServiceManager.idl | 15 |
15 files changed, 2439 insertions, 804 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: */ diff --git a/desktop/source/deployment/registry/component/dp_component.cxx b/desktop/source/deployment/registry/component/dp_component.cxx index 8bfcbd5b44e4..6d5fb619553c 100644 --- a/desktop/source/deployment/registry/component/dp_component.cxx +++ b/desktop/source/deployment/registry/component/dp_component.cxx @@ -132,6 +132,13 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend factories, Reference<XComponentContext> const & xContext ); + void componentLiveInsertion( + ComponentBackendDb::Data const & data, + std::vector< css::uno::Reference< css::uno::XInterface > > const & + factories); + + void componentLiveRemoval(ComponentBackendDb::Data const & data); + virtual void SAL_CALL disposing(); // Package @@ -338,22 +345,6 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend css::uno::Reference< css::registry::XRegistryKey > const & base, rtl::OUString const & path); - void extractComponentData( - css::uno::Reference< css::uno::XComponentContext > const & context, - css::uno::Reference< css::registry::XRegistryKey > const & registry, - ComponentBackendDb::Data * data, - std::vector< css::uno::Reference< css::uno::XInterface > > * factories, - css::uno::Reference< css::loader::XImplementationLoader > const * - componentLoader, - rtl::OUString const * componentUrl); - - void componentLiveInsertion( - ComponentBackendDb::Data const & data, - std::vector< css::uno::Reference< css::uno::XInterface > > const & - factories); - - void componentLiveRemoval(ComponentBackendDb::Data const & data); - css::uno::Reference< css::uno::XComponentContext > getRootContext() const; public: @@ -1173,16 +1164,116 @@ css::uno::Reference< css::registry::XRegistryKey > BackendImpl::openRegistryKey( return key; } -void BackendImpl::extractComponentData( +css::uno::Reference< css::uno::XComponentContext > BackendImpl::getRootContext() + const +{ + css::uno::Reference< css::uno::XComponentContext > rootContext( + getComponentContext()->getValueByName( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_root"))), + css::uno::UNO_QUERY); + return rootContext.is() ? rootContext : getComponentContext(); +} + +//______________________________________________________________________________ +void BackendImpl::releaseObject( OUString const & id ) +{ + const ::osl::MutexGuard guard( getMutex() ); + m_backendObjects.erase( id ); +} + +//______________________________________________________________________________ +Reference<XInterface> BackendImpl::getObject( OUString const & id ) +{ + const ::osl::MutexGuard guard( getMutex() ); + const t_string2object::const_iterator iFind( m_backendObjects.find( id ) ); + if (iFind == m_backendObjects.end()) + return Reference<XInterface>(); + else + return iFind->second; +} + +//______________________________________________________________________________ +Reference<XInterface> BackendImpl::insertObject( + OUString const & id, Reference<XInterface> const & xObject ) +{ + const ::osl::MutexGuard guard( getMutex() ); + const ::std::pair<t_string2object::iterator, bool> insertion( + m_backendObjects.insert( t_string2object::value_type( + id, xObject ) ) ); + return insertion.first->second; +} + +//------------------------------------------------------------------------------ +Reference<XComponentContext> raise_uno_process( + Reference<XComponentContext> const & xContext, + ::rtl::Reference<AbortChannel> const & abortChannel ) +{ + OSL_ASSERT( xContext.is() ); + + ::rtl::OUString url( + Reference<util::XMacroExpander>( + xContext->getValueByName( + OUSTR("/singletons/com.sun.star.util.theMacroExpander") ), + UNO_QUERY_THROW )-> + expandMacros( OUSTR("$URE_BIN_DIR/uno") ) ); + + ::rtl::OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno:pipe,name=") ); + OUString pipeId( generateRandomPipeId() ); + buf.append( pipeId ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM(";urp;uno.ComponentContext") ); + const OUString connectStr( buf.makeStringAndClear() ); + + // raise core UNO process to register/run a component, + // javavm service uses unorc next to executable to retrieve deployed + // jar typelibs + + ::std::vector<OUString> args; +#if OSL_DEBUG_LEVEL == 0 + args.push_back( OUSTR("--quiet") ); +#endif + args.push_back( OUSTR("--singleaccept") ); + args.push_back( OUSTR("-u") ); + args.push_back( connectStr ); + // don't inherit from unorc: + args.push_back( OUSTR("-env:INIFILENAME=") ); + + //now add the bootstrap variables which were supplied on the command line + ::std::vector<OUString> bootvars = getCmdBootstrapVariables(); + args.insert(args.end(), bootvars.begin(), bootvars.end()); + + oslProcess hProcess = raiseProcess( + url, comphelper::containerToSequence(args) ); + try { + return Reference<XComponentContext>( + resolveUnoURL( connectStr, xContext, abortChannel.get() ), + UNO_QUERY_THROW ); + } + catch (...) { + // try to terminate process: + if ( osl_terminateProcess( hProcess ) != osl_Process_E_None ) + { + OSL_ASSERT( false ); + } + throw; + } +} + +//------------------------------------------------------------------------------ +namespace { + +void extractComponentData( css::uno::Reference< css::uno::XComponentContext > const & context, css::uno::Reference< css::registry::XRegistryKey > const & registry, ComponentBackendDb::Data * data, std::vector< css::uno::Reference< css::uno::XInterface > > * factories, - css::uno::Reference< css::loader::XImplementationLoader > const * + css::uno::Reference< css::loader::XImplementationLoader > const & componentLoader, - rtl::OUString const * componentUrl) + rtl::OUString const & componentUrl) { - OSL_ASSERT(context.is() && registry.is() && data != 0); + OSL_ASSERT( + context.is() && registry.is() && data != 0 && componentLoader.is()); rtl::OUString registryName(registry->getKeyName()); sal_Int32 prefix = registryName.getLength(); if (!registryName.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM("/"))) { @@ -1211,51 +1302,56 @@ void BackendImpl::extractComponentData( } } if (factories != 0) { - css::uno::Reference< css::loader::XImplementationLoader > loader; - if (componentLoader == 0) { - rtl::OUString activator( - openRegistryKey( - keys[i], - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("UNO/ACTIVATOR")))-> - getAsciiValue()); - loader.set( - smgr->createInstanceWithContext(activator, context), - css::uno::UNO_QUERY); - if (!loader.is()) { - throw css::deployment::DeploymentException( - (rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "cannot instantiate loader ")) + - activator), - static_cast< OWeakObject * >(this), Any()); - } - } else { - OSL_ASSERT(componentLoader->is()); - loader = *componentLoader; - } factories->push_back( - loader->activate( - name, rtl::OUString(), - (componentUrl == 0 - ? (openRegistryKey( - keys[i], - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("UNO/LOCATION")))-> - getAsciiValue()) - : *componentUrl), - keys[i])); + componentLoader->activate( + name, rtl::OUString(), componentUrl, keys[i])); } } } -void BackendImpl::componentLiveInsertion( +} + +void BackendImpl::ComponentPackageImpl::getComponentInfo( + ComponentBackendDb::Data * data, + std::vector< css::uno::Reference< css::uno::XInterface > > * factories, + Reference<XComponentContext> const & xContext ) +{ + const Reference<loader::XImplementationLoader> xLoader( + xContext->getServiceManager()->createInstanceWithContext( + m_loader, xContext ), UNO_QUERY ); + if (! xLoader.is()) + { + throw css::deployment::DeploymentException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("cannot instantiate loader ")) + + m_loader), + static_cast< OWeakObject * >(this), Any()); + } + + // HACK: highly dependent on stoc/source/servicemanager + // and stoc/source/implreg implementation which rely on the same + // services.rdb format! + // .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by + // writeRegistryInfo, however, but are knwon, fixed values here, so + // can be passed into extractComponentData + rtl::OUString url(getURL()); + const Reference<registry::XSimpleRegistry> xMemReg( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.registry.SimpleRegistry"), xContext ), + UNO_QUERY_THROW ); + xMemReg->open( OUString() /* in mem */, false, true ); + xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url ); + extractComponentData( + xContext, xMemReg->getRootKey(), data, factories, xLoader, url); +} + +void BackendImpl::ComponentPackageImpl::componentLiveInsertion( ComponentBackendDb::Data const & data, std::vector< css::uno::Reference< css::uno::XInterface > > const & factories) { css::uno::Reference< css::uno::XComponentContext > rootContext( - getRootContext()); + getMyBackend()->getRootContext()); css::uno::Reference< css::container::XSet > set( rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW); std::vector< css::uno::Reference< css::uno::XInterface > >::const_iterator @@ -1310,9 +1406,11 @@ void BackendImpl::componentLiveInsertion( } } -void BackendImpl::componentLiveRemoval(ComponentBackendDb::Data const & data) { +void BackendImpl::ComponentPackageImpl::componentLiveRemoval( + ComponentBackendDb::Data const & data) +{ css::uno::Reference< css::uno::XComponentContext > rootContext( - getRootContext()); + getMyBackend()->getRootContext()); css::uno::Reference< css::container::XSet > set( rootContext->getServiceManager(), css::uno::UNO_QUERY_THROW); for (t_stringlist::const_iterator i(data.implementationNames.begin()); @@ -1351,137 +1449,6 @@ void BackendImpl::componentLiveRemoval(ComponentBackendDb::Data const & data) { } } -css::uno::Reference< css::uno::XComponentContext > BackendImpl::getRootContext() - const -{ - css::uno::Reference< css::uno::XComponentContext > rootContext( - getComponentContext()->getValueByName( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_root"))), - css::uno::UNO_QUERY); - return rootContext.is() ? rootContext : getComponentContext(); -} - -//______________________________________________________________________________ -void BackendImpl::releaseObject( OUString const & id ) -{ - const ::osl::MutexGuard guard( getMutex() ); - m_backendObjects.erase( id ); -} - -//______________________________________________________________________________ -Reference<XInterface> BackendImpl::getObject( OUString const & id ) -{ - const ::osl::MutexGuard guard( getMutex() ); - const t_string2object::const_iterator iFind( m_backendObjects.find( id ) ); - if (iFind == m_backendObjects.end()) - return Reference<XInterface>(); - else - return iFind->second; -} - -//______________________________________________________________________________ -Reference<XInterface> BackendImpl::insertObject( - OUString const & id, Reference<XInterface> const & xObject ) -{ - const ::osl::MutexGuard guard( getMutex() ); - const ::std::pair<t_string2object::iterator, bool> insertion( - m_backendObjects.insert( t_string2object::value_type( - id, xObject ) ) ); - return insertion.first->second; -} - -//------------------------------------------------------------------------------ -Reference<XComponentContext> raise_uno_process( - Reference<XComponentContext> const & xContext, - ::rtl::Reference<AbortChannel> const & abortChannel ) -{ - OSL_ASSERT( xContext.is() ); - - ::rtl::OUString url( - Reference<util::XMacroExpander>( - xContext->getValueByName( - OUSTR("/singletons/com.sun.star.util.theMacroExpander") ), - UNO_QUERY_THROW )-> - expandMacros( OUSTR("$URE_BIN_DIR/uno") ) ); - - ::rtl::OUStringBuffer buf; - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno:pipe,name=") ); - OUString pipeId( generateRandomPipeId() ); - buf.append( pipeId ); - buf.appendAscii( - RTL_CONSTASCII_STRINGPARAM(";urp;uno.ComponentContext") ); - const OUString connectStr( buf.makeStringAndClear() ); - - // raise core UNO process to register/run a component, - // javavm service uses unorc next to executable to retrieve deployed - // jar typelibs - - ::std::vector<OUString> args; -#if OSL_DEBUG_LEVEL == 0 - args.push_back( OUSTR("--quiet") ); -#endif - args.push_back( OUSTR("--singleaccept") ); - args.push_back( OUSTR("-u") ); - args.push_back( connectStr ); - // don't inherit from unorc: - args.push_back( OUSTR("-env:INIFILENAME=") ); - - //now add the bootstrap variables which were supplied on the command line - ::std::vector<OUString> bootvars = getCmdBootstrapVariables(); - args.insert(args.end(), bootvars.begin(), bootvars.end()); - - oslProcess hProcess = raiseProcess( - url, comphelper::containerToSequence(args) ); - try { - return Reference<XComponentContext>( - resolveUnoURL( connectStr, xContext, abortChannel.get() ), - UNO_QUERY_THROW ); - } - catch (...) { - // try to terminate process: - if ( osl_terminateProcess( hProcess ) != osl_Process_E_None ) - { - OSL_ASSERT( false ); - } - throw; - } -} - -//------------------------------------------------------------------------------ -void BackendImpl::ComponentPackageImpl::getComponentInfo( - ComponentBackendDb::Data * data, - std::vector< css::uno::Reference< css::uno::XInterface > > * factories, - Reference<XComponentContext> const & xContext ) -{ - const Reference<loader::XImplementationLoader> xLoader( - xContext->getServiceManager()->createInstanceWithContext( - m_loader, xContext ), UNO_QUERY ); - if (! xLoader.is()) - { - throw css::deployment::DeploymentException( - (rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM("cannot instantiate loader ")) + - m_loader), - static_cast< OWeakObject * >(this), Any()); - } - - // HACK: highly dependent on stoc/source/servicemanager - // and stoc/source/implreg implementation which rely on the same - // services.rdb format! - // .../UNO/LOCATION and .../UNO/ACTIVATOR appear not to be written by - // writeRegistryInfo, however, but are knwon, fixed values here, so - // can be passed into extractComponentData - rtl::OUString url(getURL()); - const Reference<registry::XSimpleRegistry> xMemReg( - xContext->getServiceManager()->createInstanceWithContext( - OUSTR("com.sun.star.registry.SimpleRegistry"), xContext ), - UNO_QUERY_THROW ); - xMemReg->open( OUString() /* in mem */, false, true ); - xLoader->writeRegistryInfo( xMemReg->getRootKey(), OUString(), url ); - getMyBackend()->extractComponentData( - xContext, xMemReg->getRootKey(), data, factories, &xLoader, &url); -} - // Package //______________________________________________________________________________ //We could use here BackendImpl::hasActiveEntry. However, this check is just as well. @@ -1608,7 +1575,7 @@ void BackendImpl::ComponentPackageImpl::processPackage_( std::vector< css::uno::Reference< css::uno::XInterface > > factories; getComponentInfo(&data, startup ? 0 : &factories, context); if (!startup) { - that->componentLiveInsertion(data, factories); + componentLiveInsertion(data, factories); } m_registered = REG_REGISTERED; that->addDataToDb(url, data); @@ -1622,7 +1589,7 @@ void BackendImpl::ComponentPackageImpl::processPackage_( context = that->getComponentContext(); } if (!startup) { - that->componentLiveRemoval(data); + componentLiveRemoval(data); } css::uno::Reference< css::registry::XImplementationRegistration >( context->getServiceManager()->createInstanceWithContext( @@ -1913,13 +1880,9 @@ void BackendImpl::ComponentsPackageImpl::processPackage_( BackendImpl * that = getMyBackend(); rtl::OUString url(getURL()); if (doRegisterPackage) { - ComponentBackendDb::Data data; - data.javaTypeLibrary = false; - css::uno::Reference< css::uno::XComponentContext > context; - if (startup) { - context = that->getComponentContext(); - } else { - context.set(that->getObject(url), css::uno::UNO_QUERY); + if (!startup) { + css::uno::Reference< css::uno::XComponentContext > context( + that->getObject(url), css::uno::UNO_QUERY); if (!context.is()) { context.set( that->insertObject( @@ -1928,39 +1891,35 @@ void BackendImpl::ComponentsPackageImpl::processPackage_( that->getComponentContext(), abortChannel)), css::uno::UNO_QUERY_THROW); } + // This relies on the root component context's service manager + // supporting the extended XSet semantics: + css::uno::Sequence< css::beans::NamedValue > args(2); + args[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("uri")); + args[0].Value <<= expandUnoRcUrl(url); + args[1].Name = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("component-context")); + args[1].Value <<= context; + css::uno::Reference< css::container::XSet > smgr( + that->getRootContext()->getServiceManager(), + css::uno::UNO_QUERY_THROW); + smgr->insert(css::uno::makeAny(args)); } - - std::vector< css::uno::Reference< css::uno::XInterface > > factories; - - css::uno::Reference< css::registry::XSimpleRegistry > registry( - css::uno::Reference< css::lang::XMultiComponentFactory >( - that->getComponentContext()->getServiceManager(), - css::uno::UNO_SET_THROW)->createInstanceWithContext( - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.registry.SimpleRegistry")), - that->getComponentContext()), - css::uno::UNO_QUERY_THROW); - registry->open(expandUnoRcUrl(url), true, false); - getMyBackend()->extractComponentData( - context, - that->openRegistryKey( - registry->getRootKey(), - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IMPLEMENTATIONS"))), - &data, startup ? 0 : &factories, 0, 0); - registry->close(); - if (!startup) { - that->componentLiveInsertion(data, factories); - } - that->addDataToDb(url, data); that->addToUnoRc(RCITEM_COMPONENTS, url, xCmdEnv); } else { // revoke that->removeFromUnoRc(RCITEM_COMPONENTS, url, xCmdEnv); if (!startup) { - that->componentLiveRemoval(that->readDataFromDb(url)); + // This relies on the root component context's service manager + // supporting the extended XSet semantics: + css::uno::Sequence< css::beans::NamedValue > args(1); + args[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("uri")); + args[0].Value <<= expandUnoRcUrl(url); + css::uno::Reference< css::container::XSet > smgr( + that->getRootContext()->getServiceManager(), + css::uno::UNO_QUERY_THROW); + smgr->remove(css::uno::makeAny(args)); } that->releaseObject(url); - that->revokeEntryFromDb(url); + that->revokeEntryFromDb(url); // in case it got added with old code } } diff --git a/stoc/source/simpleregistry/simpleregistry.cxx b/stoc/source/simpleregistry/simpleregistry.cxx index 9eebb4f087a1..f09b204e19fb 100644 --- a/stoc/source/simpleregistry/simpleregistry.cxx +++ b/stoc/source/simpleregistry/simpleregistry.cxx @@ -48,7 +48,6 @@ #include "cppuhelper/implbase2.hxx" #include "cppuhelper/weak.hxx" #include "osl/mutex.hxx" -#include "osl/file.hxx" #include "registry/registry.hxx" #include "registry/regtype.h" #include "rtl/ref.hxx" @@ -85,12 +84,6 @@ public: private: virtual rtl::OUString SAL_CALL getURL() throw (css::uno::RuntimeException); - virtual void SAL_CALL openRdb( - rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool bCreate) - throw ( - css::registry::InvalidRegistryException, - css::uno::RuntimeException); - virtual void SAL_CALL open( rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool bCreate) throw ( @@ -1137,17 +1130,27 @@ rtl::OUString Key::getResolvedName(rtl::OUString const & aKeyName) return resolved; } -rtl::OUString SimpleRegistry::getURL() throw (css::uno::RuntimeException) -{ +rtl::OUString SimpleRegistry::getURL() throw (css::uno::RuntimeException) { osl::MutexGuard guard(mutex_); return textual_.get() == 0 ? registry_.getName() : textual_->getUri(); } -void SimpleRegistry::openRdb( +void SimpleRegistry::open( rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool bCreate) throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) { osl::MutexGuard guard(mutex_); + if (textual_.get() != 0) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.open(")) + + rURL + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "): instance already open"))), + static_cast< OWeakObject * >(this)); + } RegError err = (rURL.isEmpty() && bCreate) ? REG_REGISTRY_NOT_EXISTS : registry_.open(rURL, bReadOnly ? REG_READONLY : REG_READWRITE); @@ -1159,10 +1162,7 @@ void SimpleRegistry::openRdb( break; case REG_INVALID_REGISTRY: if (bReadOnly && !bCreate) { - if (!textual_.get()) - textual_.reset(new stoc::simpleregistry::TextualServices(rURL)); - else - textual_->merge(rURL); + textual_.reset(new stoc::simpleregistry::TextualServices(rURL)); break; } // fall through @@ -1180,72 +1180,6 @@ void SimpleRegistry::openRdb( } } -void SimpleRegistry::open( - rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool bCreate) - throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) -{ - osl::MutexGuard guard(mutex_); - - osl::DirectoryItem aItem; - osl::FileBase::RC eErr; - osl::FileStatus aStatus(osl_FileStatus_Mask_Type); - - // FIXME: busts the 'create' mode ... - if ((eErr = osl::DirectoryItem::get( rURL, aItem )) != osl::FileBase::E_None || - (eErr = aItem.getFileStatus( aStatus )) != osl::FileBase::E_None || - !aStatus.isDirectory()) - { - if (textual_.get() != 0) - throw css::registry::InvalidRegistryException( - (rtl::OUString("com.sun.star.registry.SimpleRegistry.open(") + - rURL + rtl::OUString("): instance already open")), - static_cast< OWeakObject * >(this)); - openRdb (rURL, bReadOnly, bCreate); - } - else - { - osl::Directory dir(rURL); - eErr = dir.open(); - if (eErr != osl::FileBase::E_None) - goto err_throw; - - for (;;) { - osl::DirectoryItem i; - if (dir.getNextItem(i, SAL_MAX_UINT32) != osl::FileBase::E_None) - break; - 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("cannot stat in directory ") + rURL ), - 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) - openRdb(stat.getFileURL(), bReadOnly, bCreate); - } - } - return; - -err_throw: - throw css::registry::InvalidRegistryException( - (rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.registry.SimpleRegistry.open(")) + - rURL + - rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM( - "): error statting url = ")) + - rtl::OUString::valueOf(static_cast< sal_Int32 >(eErr))), - static_cast< OWeakObject * >(this)); -} - sal_Bool SimpleRegistry::isValid() throw (css::uno::RuntimeException) { osl::MutexGuard guard(mutex_); return textual_.get() != 0 || registry_.isValid(); diff --git a/stoc/source/simpleregistry/textualservices.cxx b/stoc/source/simpleregistry/textualservices.cxx index 2491f55cb39b..ad24a4454550 100644 --- a/stoc/source/simpleregistry/textualservices.cxx +++ b/stoc/source/simpleregistry/textualservices.cxx @@ -1236,15 +1236,6 @@ css::uno::Sequence< rtl::OUString > Key::getChildren() { TextualServices::TextualServices(rtl::OUString const & uri): uri_(uri), data_(new Data) { - merge(uri); -} - -TextualServices::~TextualServices() {} - -// load and merge registry contents from uri -void TextualServices::merge(const rtl::OUString &uri) - throw (com::sun::star::registry::InvalidRegistryException) -{ try { Parser(uri, data_); } catch (css::container::NoSuchElementException &) { @@ -1256,6 +1247,8 @@ void TextualServices::merge(const rtl::OUString &uri) } } +TextualServices::~TextualServices() {} + css::uno::Reference< css::registry::XRegistryKey > TextualServices::getRootKey() { return new Key(data_, std::vector< rtl::OUString >()); diff --git a/stoc/source/simpleregistry/textualservices.hxx b/stoc/source/simpleregistry/textualservices.hxx index 0341c15d5d34..286eb922a1b4 100644 --- a/stoc/source/simpleregistry/textualservices.hxx +++ b/stoc/source/simpleregistry/textualservices.hxx @@ -53,9 +53,6 @@ public: virtual ~TextualServices(); - void merge(const rtl::OUString &uri) - throw (com::sun::star::registry::InvalidRegistryException); - inline rtl::OUString getUri() { return uri_; } com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > diff --git a/udkapi/com/sun/star/lang/ServiceManager.idl b/udkapi/com/sun/star/lang/ServiceManager.idl index f74ca9f22fec..cc11c0844614 100644 --- a/udkapi/com/sun/star/lang/ServiceManager.idl +++ b/udkapi/com/sun/star/lang/ServiceManager.idl @@ -75,6 +75,21 @@ module com { module sun { module star { module lang { on the factory when going down (i.e. it is commonly disposed by the component context).</dd> </dl> + <p>Since LibreOffice 3.6, in addition to instances of + <type>XServiceInfo</type> et al, the + <type scope="com::sun::star::container">XSet</type> of at least the default + C++ service manager implementation now also supports sequences of + <type scope="com::sun::star::beans">NamedValue</type> in <code>insert</code> + and <code>remove</code>. The sequence elements must each have a + <code>Name</code> of <code>uri</code> and a string <code>Value</code> that + is the URI of a service rdb. It is legal for there to be no such + <code>uri</code> elements. For <code>insert</code>, there can additionally + be an optional element with a <code>Name</code> of + <code>component-context</code> and a value that is a non-null reference of + type <type scope="com::sun::star::uno">XComponentContext</type> that shall + be used instead of this service manager's default component context when + loading the corresponding implementations. + @see com::sun::star::uno::XComponentContext */ published service ServiceManager |