diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2013-12-19 08:48:56 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2013-12-19 08:48:56 +0100 |
commit | ae3a0c8da50b36db395984637f5ad74d3b4887bc (patch) | |
tree | c4936b9fba1f24d412d41474ebef44a5f094dbc8 /cppuhelper | |
parent | 80d977b896904a0261d32857469c1b3e7516ca1e (diff) |
Add .component <implementation constructor="..." feature
...to directly call constructor functions of ComponentContext-based C++
implementations of (non-single-instance) UNO services. The case where these
calls would need to be bridged across different environments (e.g., from gcc3
to gcc3:affine) is not yet implemented.
bootstrap.component and expwrap.component are adapted accordingly as a proof-of-
concept (which had previously been adapted to use the prefix="direct" feature,
which may become unnecessary again in the end, depending on how to handle
single-instance services/singletons). More to follow.
Change-Id: I18682d75bcd29d3d427e31331b4ce8161dbb846d
Diffstat (limited to 'cppuhelper')
-rw-r--r-- | cppuhelper/source/loadsharedlibcomponentfactory.hxx | 19 | ||||
-rw-r--r-- | cppuhelper/source/servicemanager.cxx | 156 | ||||
-rw-r--r-- | cppuhelper/source/servicemanager.hxx | 31 | ||||
-rw-r--r-- | cppuhelper/source/shlib.cxx | 659 |
4 files changed, 434 insertions, 431 deletions
diff --git a/cppuhelper/source/loadsharedlibcomponentfactory.hxx b/cppuhelper/source/loadsharedlibcomponentfactory.hxx index 9809c558cc09..9119674f9af6 100644 --- a/cppuhelper/source/loadsharedlibcomponentfactory.hxx +++ b/cppuhelper/source/loadsharedlibcomponentfactory.hxx @@ -14,18 +14,29 @@ #include <com/sun/star/uno/Reference.hxx> +#include <servicemanager.hxx> + namespace com { namespace sun { namespace star { namespace lang { class XMultiServiceFactory; } - namespace uno { class XInterface; } + namespace uno { + class Environment; + class XInterface; + } } } } namespace rtl { class OUString; } namespace cppuhelper { namespace detail { -css::uno::Reference<css::uno::XInterface> loadSharedLibComponentFactory( +css::uno::Environment getEnvironment( + rtl::OUString const & name, rtl::OUString const & implementation); + +void loadSharedLibComponentFactory( rtl::OUString const & uri, rtl::OUString const & environment, - rtl::OUString const & prefix, rtl::OUString const & rImplName, - css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr); + rtl::OUString const & prefix, rtl::OUString const & implementation, + rtl::OUString const & constructor, + css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager, + ImplementationConstructorFn ** constructorFunction, + css::uno::Reference<css::uno::XInterface> * factory); } } diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx index 3420233cc743..9a271d2e383a 100644 --- a/cppuhelper/source/servicemanager.cxx +++ b/cppuhelper/source/servicemanager.cxx @@ -40,6 +40,7 @@ #include "rtl/ustring.hxx" #include "rtl/strbuf.hxx" #include "sal/log.hxx" +#include "uno/environment.hxx" #include <loadsharedlibcomponentfactory.hxx> @@ -344,18 +345,76 @@ void Parser::handleComponent() { } void Parser::handleImplementation() { - OUString name(getNameAttribute()); + rtl::OUString attrName; + rtl::OUString attrConstructor; + 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() + + ": <implementation> has multiple \"name\" attributes"), + css::uno::Reference< css::uno::XInterface >()); + } + attrName = reader_.getAttributeValue(false).convertFromUtf8(); + if (attrName.isEmpty()) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + ": <implementation> has empty \"name\" attribute"), + css::uno::Reference< css::uno::XInterface >()); + } + } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE + && name.equals(RTL_CONSTASCII_STRINGPARAM("constructor"))) + { + if (!attrConstructor.isEmpty()) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + (": <implementation> has multiple \"constructor\"" + " attributes")), + css::uno::Reference< css::uno::XInterface >()); + } + attrConstructor = reader_.getAttributeValue(false) + .convertFromUtf8(); + if (attrConstructor.isEmpty()) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + ": element has empty \"constructor\" attribute"), + css::uno::Reference< css::uno::XInterface >()); + } + if (attrEnvironment_.isEmpty()) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + (": <implementation> has \"constructor\" attribute but" + " <component> has no \"environment\" attribute")), + css::uno::Reference< css::uno::XInterface >()); + } + } else { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + ": unexpected element attribute \"" + + name.convertFromUtf8() + "\" in <implementation>"), + css::uno::Reference< css::uno::XInterface >()); + } + } + if (attrName.isEmpty()) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + ": <implementation> is missing \"name\" attribute"), + css::uno::Reference< css::uno::XInterface >()); + } implementation_.reset( new cppuhelper::ServiceManager::Data::Implementation( - name, attrLoader_, attrUri_, attrEnvironment_, attrPrefix_, - alienContext_, reader_.getUrl())); + attrName, attrLoader_, attrUri_, attrEnvironment_, attrConstructor, + attrPrefix_, alienContext_, reader_.getUrl())); if (!data_->namedImplementations.insert( cppuhelper::ServiceManager::Data::NamedImplementations::value_type( - name, implementation_)). + attrName, implementation_)). second) { throw css::registry::InvalidRegistryException( - (reader_.getUrl() + ": duplicate <implementation name=\"" + name + (reader_.getUrl() + ": duplicate <implementation name=\"" + attrName + "\">"), css::uno::Reference< css::uno::XInterface >()); } @@ -471,7 +530,7 @@ public: boost::shared_ptr< cppuhelper::ServiceManager::Data::ImplementationInfo > const & info): - manager_(manager), info_(info), loaded_(false) + manager_(manager), info_(info), loaded_(false), constructor_(0) { assert(manager.is() && info.get() != 0); } private: @@ -514,6 +573,7 @@ private: osl::Mutex mutex_; bool loaded_; + cppuhelper::ImplementationConstructorFn * constructor_; css::uno::Reference< css::lang::XSingleComponentFactory > factory1_; css::uno::Reference< css::lang::XSingleServiceFactory > factory2_; }; @@ -524,7 +584,12 @@ FactoryWrapper::createInstanceWithContext( throw (css::uno::Exception, css::uno::RuntimeException) { loadImplementation(Context); - return factory1_.is() + return constructor_ != 0 + ? css::uno::Reference<css::uno::XInterface>( + (*constructor_)( + Context.get(), css::uno::Sequence<css::uno::Any>().get()), + SAL_NO_ACQUIRE) + : factory1_.is() ? factory1_->createInstanceWithContext(Context) : factory2_->createInstance(); } @@ -536,7 +601,10 @@ FactoryWrapper::createInstanceWithArgumentsAndContext( throw (css::uno::Exception, css::uno::RuntimeException) { loadImplementation(Context); - return factory1_.is() + return constructor_ != 0 + ? css::uno::Reference<css::uno::XInterface>( + (*constructor_)(Context.get(), Arguments.get()), SAL_NO_ACQUIRE) + : factory1_.is() ? factory1_->createInstanceWithArgumentsAndContext(Arguments, Context) : factory2_->createInstanceWithArguments(Arguments); } @@ -544,10 +612,7 @@ FactoryWrapper::createInstanceWithArgumentsAndContext( css::uno::Reference< css::uno::XInterface > FactoryWrapper::createInstance() throw (css::uno::Exception, css::uno::RuntimeException) { - loadImplementation(manager_->getContext()); - return factory1_.is() - ? factory1_->createInstanceWithContext(manager_->getContext()) - : factory2_->createInstance(); + return createInstanceWithContext(manager_->getContext()); } css::uno::Reference< css::uno::XInterface > @@ -555,11 +620,8 @@ FactoryWrapper::createInstanceWithArguments( css::uno::Sequence< css::uno::Any > const & Arguments) throw (css::uno::Exception, css::uno::RuntimeException) { - loadImplementation(manager_->getContext()); - return factory1_.is() - ? factory1_->createInstanceWithArgumentsAndContext( - Arguments, manager_->getContext()) - : factory2_->createInstanceWithArguments(Arguments); + return createInstanceWithArgumentsAndContext( + Arguments, manager_->getContext()); } rtl::OUString FactoryWrapper::getImplementationName() @@ -603,20 +665,23 @@ void FactoryWrapper::loadImplementation( return; } } + cppuhelper::ImplementationConstructorFn * ctor = 0; css::uno::Reference< css::lang::XSingleComponentFactory > f1; css::uno::Reference< css::lang::XSingleServiceFactory > f2; //TODO: There is a race here, as the relevant service factory can already // have been removed and loading can thus fail, as the entity from which to // load can disappear once the service factory is removed: - manager_->loadImplementation(context, info_, &f1, &f2); - if (!(f1.is() || f2.is())) { + manager_->loadImplementation(context, info_, &ctor, &f1, &f2); + if (ctor == 0 && !f1.is() && !f2.is()) { throw css::uno::DeploymentException( - "Implementation " + info_->name + " does not provide a factory", + ("Implementation " + info_->name + + " does not provide a constructor or factory"), static_cast< cppu::OWeakObject * >(this)); } osl::MutexGuard g(mutex_); if (!loaded_) { loaded_ = true; + constructor_ = ctor; factory1_ = f1; factory2_ = f2; } @@ -647,11 +712,13 @@ void cppuhelper::ServiceManager::addSingletonContextEntries( void cppuhelper::ServiceManager::loadImplementation( css::uno::Reference< css::uno::XComponentContext > const & context, boost::shared_ptr< Data::ImplementationInfo > const & info, + ImplementationConstructorFn ** constructor, css::uno::Reference< css::lang::XSingleComponentFactory > * factory1, css::uno::Reference< css::lang::XSingleServiceFactory > * factory2) { assert( - info.get() != 0 && factory1 != 0 && !factory1->is() && factory2 != 0 + info.get() != 0 && constructor != 0 && *constructor == 0 + && factory1 != 0 && !factory1->is() && factory2 != 0 && !factory2->is()); rtl::OUString uri; try { @@ -662,13 +729,29 @@ void cppuhelper::ServiceManager::loadImplementation( static_cast< cppu::OWeakObject * >(this)); } css::uno::Reference< css::uno::XInterface > f0; - // Shortcut loading via SharedLibrary loader, to pass in environment and - // prefix arguments: + // Special handling of SharedLibrary loader, with support for environment, + // constructor, and prefix arguments: if (!info->alienContext.is() && info->loader == "com.sun.star.loader.SharedLibrary") { - f0 = cppuhelper::detail::loadSharedLibComponentFactory( - uri, info->environment, info->prefix, info->name, this); + cppuhelper::detail::loadSharedLibComponentFactory( + uri, info->environment, info->prefix, info->name, info->constructor, + this, constructor, &f0); + if (constructor != 0 && *constructor != 0) { + assert(!info->environment.isEmpty()); + css::uno::Environment curEnv(css::uno::Environment::getCurrent()); + css::uno::Environment env( + cppuhelper::detail::getEnvironment( + info->environment, info->name)); + if (!(curEnv.is() && env.is())) { + throw css::uno::DeploymentException( + "cannot get environments", + css::uno::Reference<css::uno::XInterface>()); + } + if (curEnv.get() != env.get()) { + std::abort();//TODO + } + } } else { SAL_WARN_IF( !info->environment.isEmpty(), "cppuhelper", @@ -676,6 +759,10 @@ void cppuhelper::ServiceManager::loadImplementation( << info->environment); SAL_WARN_IF( !info->prefix.isEmpty(), "cppuhelper", + "Loader " << info->loader << " and non-empty constructor " + << info->constructor); + SAL_WARN_IF( + !info->prefix.isEmpty(), "cppuhelper", "Loader " << info->loader << " and non-empty prefix " << info->prefix); css::uno::Reference< css::uno::XComponentContext > ctxt; @@ -810,7 +897,12 @@ cppuhelper::ServiceManager::createInstanceWithContext( if (impl.get() == 0) { return css::uno::Reference< css::uno::XInterface >(); } - if (impl->factory1.is()) { + if (impl->constructor != 0) { + return css::uno::Reference<css::uno::XInterface>( + (*impl->constructor)( + Context.get(), css::uno::Sequence<css::uno::Any>().get()), + SAL_NO_ACQUIRE); + } else if (impl->factory1.is()) { return impl->factory1->createInstanceWithContext(Context); } if (impl->factory2.is()) { @@ -833,7 +925,11 @@ cppuhelper::ServiceManager::createInstanceWithArgumentsAndContext( if (impl.get() == 0) { return css::uno::Reference< css::uno::XInterface >(); } - if (impl->factory1.is()) { + if (impl->constructor != 0) { + return css::uno::Reference<css::uno::XInterface>( + (*impl->constructor)(Context.get(), Arguments.get()), + SAL_NO_ACQUIRE); + } else if (impl->factory1.is()) { return impl->factory1->createInstanceWithArgumentsAndContext( Arguments, Context); } @@ -1309,7 +1405,7 @@ bool cppuhelper::ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) { boost::shared_ptr< Data::Implementation > impl( new Data::Implementation( name, readLegacyRdbString(uri, implKey, "UNO/ACTIVATOR"), - readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", + readLegacyRdbString(uri, implKey, "UNO/LOCATION"), "", "", "", css::uno::Reference< css::uno::XComponentContext >(), uri)); if (!data_.namedImplementations.insert( Data::NamedImplementations::value_type(name, impl)). @@ -1679,12 +1775,14 @@ cppuhelper::ServiceManager::findServiceImplementation( // 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) { + cppuhelper::ImplementationConstructorFn * ctor = 0; css::uno::Reference< css::lang::XSingleComponentFactory > f1; css::uno::Reference< css::lang::XSingleServiceFactory > f2; - loadImplementation(context, impl->info, &f1, &f2); + loadImplementation(context, impl->info, &ctor, &f1, &f2); osl::MutexGuard g(rBHelper.rMutex); if (!(isDisposed() || impl->loaded)) { impl->loaded = true; + impl->constructor = ctor; impl->factory1 = f1; impl->factory2 = f2; } diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx index b68cd4b95edd..d76b93f9a4f6 100644 --- a/cppuhelper/source/servicemanager.hxx +++ b/cppuhelper/source/servicemanager.hxx @@ -34,10 +34,20 @@ #include "registry/registry.hxx" #include "rtl/ustring.hxx" +namespace com { namespace sun { namespace star { namespace lang { + class XSingleComponentFactory; +} } } } namespace cppu { struct ContextEntry_Init; } namespace cppuhelper { +extern "C" { + +typedef css::uno::XInterface * SAL_CALL ImplementationConstructorFn( + css::uno::XComponentContext *, uno_Sequence *); + +} + typedef cppu::WeakComponentImplHelper8< css::lang::XServiceInfo, css::lang::XMultiServiceFactory, css::lang::XMultiComponentFactory, css::container::XSet, @@ -55,13 +65,15 @@ public: rtl::OUString const & theName, rtl::OUString const & theLoader, rtl::OUString const & theUri, rtl::OUString const & theEnvironment, + rtl::OUString const & theConstructor, rtl::OUString const & thePrefix, css::uno::Reference< css::uno::XComponentContext > const & theAlienContext, rtl::OUString const & theRdbFile): name(theName), loader(theLoader), uri(theUri), - environment(theEnvironment), prefix(thePrefix), - alienContext(theAlienContext), rdbFile(theRdbFile) + environment(theEnvironment), constructor(theConstructor), + prefix(thePrefix), alienContext(theAlienContext), + rdbFile(theRdbFile) {} explicit ImplementationInfo(rtl::OUString const & theName): @@ -71,6 +83,7 @@ public: rtl::OUString const loader; rtl::OUString const uri; rtl::OUString const environment; + rtl::OUString const constructor; rtl::OUString const prefix; css::uno::Reference< css::uno::XComponentContext > const alienContext; @@ -83,15 +96,16 @@ public: Implementation( rtl::OUString const & name, rtl::OUString const & loader, rtl::OUString const & uri, rtl::OUString const & environment, + rtl::OUString const & constructorName, rtl::OUString const & prefix, css::uno::Reference< css::uno::XComponentContext > const & alienContext, rtl::OUString const & rdbFile): info( new ImplementationInfo( - name, loader, uri, environment, prefix, alienContext, - rdbFile)), - loaded(false) + name, loader, uri, environment, constructorName, prefix, + alienContext, rdbFile)), + constructor(0), loaded(false) {} Implementation( @@ -102,11 +116,13 @@ public: theFactory2, css::uno::Reference< css::lang::XComponent > const & theComponent): - info(new ImplementationInfo(name)), factory1(theFactory1), - factory2(theFactory2), component(theComponent), loaded(true) + info(new ImplementationInfo(name)), constructor(0), + factory1(theFactory1), factory2(theFactory2), + component(theComponent), loaded(true) {} boost::shared_ptr< ImplementationInfo > info; + ImplementationConstructorFn * constructor; css::uno::Reference< css::lang::XSingleComponentFactory > factory1; css::uno::Reference< css::lang::XSingleServiceFactory > factory2; css::uno::Reference< css::lang::XComponent > component; @@ -160,6 +176,7 @@ public: void loadImplementation( css::uno::Reference< css::uno::XComponentContext > const & context, boost::shared_ptr< Data::ImplementationInfo > const & info, + ImplementationConstructorFn ** constructor, css::uno::Reference< css::lang::XSingleComponentFactory > * factory1, css::uno::Reference< css::lang::XSingleServiceFactory > * factory2); diff --git a/cppuhelper/source/shlib.cxx b/cppuhelper/source/shlib.cxx index 81e02d3eb1ac..972357b3c05c 100644 --- a/cppuhelper/source/shlib.cxx +++ b/cppuhelper/source/shlib.cxx @@ -17,456 +17,333 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include "sal/config.h" +#include <sal/config.h> #include <cassert> +#include <cstdlib> -#include "osl/module.hxx" -#include "uno/environment.h" -#include <uno/lbnames.h> -#include "uno/mapping.hxx" -#include "cppuhelper/factory.hxx" -#include "cppuhelper/shlib.hxx" - -#include "com/sun/star/beans/XPropertySet.hpp" +#include <com/sun/star/loader/CannotActivateFactoryException.hpp> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/shlib.hxx> +#include <osl/module.hxx> +#include <uno/environment.hxx> +#include <uno/mapping.hxx> #include <loadsharedlibcomponentfactory.hxx> -#include <stdio.h> - -#ifdef ANDROID +#if defined ANDROID #include <osl/detail/android-bootstrap.h> -#endif - -#ifdef IOS +#elif defined IOS #include <osl/detail/component-mapping.h> #endif -using namespace ::osl; -using namespace ::com::sun::star; -using namespace ::com::sun::star::uno; - -using rtl::OString; -using rtl::OUString; - -namespace { - -uno::Environment getEnvironment( - OUString const & name, OUString const & cImplName) +css::uno::Environment cppuhelper::detail::getEnvironment( + rtl::OUString const & name, rtl::OUString const & implementation) { - OUString n(name); - static const char * pUNO_ENV_LOG = ::getenv( "UNO_ENV_LOG" ); - if (pUNO_ENV_LOG && rtl_str_getLength(pUNO_ENV_LOG) ) - { - OString implName(OUStringToOString(cImplName, RTL_TEXTENCODING_ASCII_US)); - OString aEnv( pUNO_ENV_LOG ); - sal_Int32 nIndex = 0; - do - { - const OString aStr( aEnv.getToken( 0, ';', nIndex ) ); - if ( aStr.equals(implName) ) - { - n += ::rtl::OUString(":log"); + assert(!implementation.isEmpty()); + rtl::OUString n(name); + static char const * log = std::getenv("UNO_ENV_LOG"); + if (log != 0 && *log != 0) { + rtl::OString imps(log); + for (sal_Int32 i = 0; i != -1;) { + rtl::OString imp(imps.getToken(0, ';', i)); + //TODO: this assumes UNO_ENV_LOG only contains ASCII characters: + if (implementation.equalsAsciiL(imp.getStr(), imp.getLength())) { + n += ":log"; break; } - } while( nIndex != -1 ); + } } - return uno::Environment(n); + return css::uno::Environment(n); } -#ifndef DISABLE_DYNLOADING - -void getLibEnv(oslModule lib, - uno::Environment * pEnv, - uno::Environment const & cTargetEnv, - OUString const & cImplName = OUString(), - OUString const & rPrefix = OUString()) -{ - sal_Char const * pEnvTypeName = NULL; +namespace { - OUString aGetEnvNameExt = rPrefix + COMPONENT_GETENVEXT; - component_getImplementationEnvironmentExtFunc pGetImplEnvExt = - (component_getImplementationEnvironmentExtFunc)osl_getFunctionSymbol(lib, aGetEnvNameExt.pData); +#if !defined DISABLE_DYNLOADING - if (pGetImplEnvExt) - { - OString implName(OUStringToOString(cImplName, RTL_TEXTENCODING_ASCII_US)); - pGetImplEnvExt(&pEnvTypeName, (uno_Environment **)pEnv, implName.getStr(), cTargetEnv.get()); +css::uno::Environment getEnvironmentFromModule( + osl::Module const & module, css::uno::Environment const & target, + rtl::OUString const & implementation, rtl::OUString const & prefix) +{ + char const * name = 0; + css::uno::Environment env; + rtl::OUString fullPrefix(prefix); + if (!fullPrefix.isEmpty()) { + fullPrefix += "_"; } - else - { - OUString aGetEnvName = rPrefix + COMPONENT_GETENV; - component_getImplementationEnvironmentFunc pGetImplEnv = - (component_getImplementationEnvironmentFunc)osl_getFunctionSymbol( - lib, aGetEnvName.pData ); - if (pGetImplEnv) - pGetImplEnv(&pEnvTypeName, (uno_Environment **)pEnv); - - else // this symbol used to be mandatory, but is no longer - pEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + component_getImplementationEnvironmentExtFunc fp1 + = reinterpret_cast<component_getImplementationEnvironmentExtFunc>( + module.getFunctionSymbol(fullPrefix + COMPONENT_GETENVEXT)); + if (fp1 != 0) { + (*fp1)( + &name, reinterpret_cast<uno_Environment **>(&env), + (rtl::OUStringToOString(implementation, RTL_TEXTENCODING_ASCII_US) + .getStr()), + target.get()); + } else { + component_getImplementationEnvironmentFunc fp2 + = reinterpret_cast<component_getImplementationEnvironmentFunc>( + module.getFunctionSymbol(fullPrefix + COMPONENT_GETENV)); + if (fp2 != 0) { + (*fp2)(&name, reinterpret_cast<uno_Environment **>(&env)); + } else { + name = CPPU_CURRENT_LANGUAGE_BINDING_NAME; //TODO: fail + } } - - if (!pEnv->is() && pEnvTypeName) - { - *pEnv = getEnvironment( - OUString::createFromAscii(pEnvTypeName), cImplName); + if (!env.is() && name != 0) { + env = cppuhelper::detail::getEnvironment( + rtl::OUString::createFromAscii(name), implementation); } + return env; } #endif -extern "C" void s_getFactory(va_list * pParam) -{ - component_getFactoryFunc pSym = va_arg(*pParam, component_getFactoryFunc); - OString const * pImplName = va_arg(*pParam, OString const *); - void * pSMgr = va_arg(*pParam, void *); - void * pKey = va_arg(*pParam, void *); - void ** ppSSF = va_arg(*pParam, void **); - - *ppSSF = pSym(pImplName->getStr(), pSMgr, pKey); +extern "C" void getFactory(va_list * args) { + component_getFactoryFunc fn = va_arg(*args, component_getFactoryFunc); + rtl::OString const * implementation = va_arg(*args, rtl::OString const *); + void * smgr = va_arg(*args, void *); + void * key = va_arg(*args, void *); + void ** factory = va_arg(*args, void **); + *factory = (*fn)(implementation->getStr(), smgr, key); } -} - -namespace cppu -{ - -/* For backwards compatibility */ -Reference< XInterface > SAL_CALL loadSharedLibComponentFactory( - OUString const & uri, OUString const & rPath, OUString const & rImplName, - Reference< lang::XMultiServiceFactory > const & xMgr, - Reference< registry::XRegistryKey > const & xKey ) - SAL_THROW( (loader::CannotActivateFactoryException) ) +css::uno::Reference<css::uno::XInterface> invokeComponentFactory( + css::uno::Environment const & source, css::uno::Environment const & target, + component_getFactoryFunc function, rtl::OUString const & uri, + rtl::OUString const & implementation, + css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager) { - assert(rPath.isEmpty()); - assert(!xKey.is()); - (void) rPath; - (void) xKey; - return cppuhelper::detail::loadSharedLibComponentFactory( - uri, "", "", rImplName, xMgr); + if (!(source.is() && target.is())) { + throw css::loader::CannotActivateFactoryException( + "cannot get environments", + css::uno::Reference<css::uno::XInterface>()); + } + rtl::OString impl( + rtl::OUStringToOString(implementation, RTL_TEXTENCODING_ASCII_US)); + if (source.get() == target.get()) { + return css::uno::Reference<css::uno::XInterface>( + static_cast<css::uno::XInterface *>( + (*function)(impl.getStr(), serviceManager.get(), 0)), + SAL_NO_ACQUIRE); + } else { + css::uno::Mapping mapTo(source, target); + css::uno::Mapping mapFrom(target, source); + if (!(mapTo.is() && mapFrom.is())) { + throw css::loader::CannotActivateFactoryException( + "cannot get mappings", + css::uno::Reference<css::uno::XInterface>()); + } + void * smgr = mapTo.mapInterface( + serviceManager.get(), + cppu::UnoType<css::lang::XMultiServiceFactory>::get()); + void * factory = 0; + target.invoke(getFactory, function, &impl, smgr, 0, &factory); + if (smgr != 0) { + (*target.get()->pExtEnv->releaseInterface)( + target.get()->pExtEnv, smgr); + } + if (factory == 0) { + throw css::loader::CannotActivateFactoryException( + ("calling factory function for \"" + implementation + "\" in <" + + uri + "> returned null"), + css::uno::Reference<css::uno::XInterface>()); + } + css::uno::Reference<css::uno::XInterface> res; + mapFrom.mapInterface( + reinterpret_cast<void **>(&res), factory, + cppu::UnoType<css::uno::XInterface>::get()); + (*target.get()->pExtEnv->releaseInterface)( + target.get()->pExtEnv, factory); + return res; + } } } -namespace +void cppuhelper::detail::loadSharedLibComponentFactory( + rtl::OUString const & uri, rtl::OUString const & environment, + rtl::OUString const & prefix, rtl::OUString const & implementation, + rtl::OUString const & constructor, + css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager, + ImplementationConstructorFn ** constructorFunction, + css::uno::Reference<css::uno::XInterface> * factory) { - -Reference< XInterface > invokeComponentFactory( - uno::Environment const & env, - oslGenericFunction pGetter, - OUString const & rModulePath, - OUString const & rImplName, - Reference< ::com::sun::star::lang::XMultiServiceFactory > const & xMgr, - OUString &rExcMsg ) -{ - Reference< XInterface > xRet; - uno::Environment currentEnv(Environment::getCurrent()); - - OString aImplName( - OUStringToOString( rImplName, RTL_TEXTENCODING_ASCII_US ) ); - - if (env.is() && currentEnv.is()) - { -#if OSL_DEBUG_LEVEL > 1 - { - rtl::OString modPath(rtl::OUStringToOString(rModulePath, RTL_TEXTENCODING_ASCII_US)); - rtl::OString implName(rtl::OUStringToOString(rImplName, RTL_TEXTENCODING_ASCII_US)); - rtl::OString envDcp(rtl::OUStringToOString(env.getTypeName(), RTL_TEXTENCODING_ASCII_US)); - - fprintf(stderr, "invokeComponentFactory envDcp:%s implName:%s modPath:%s\n", envDcp.getStr(), implName.getStr(), modPath.getStr()); + assert(constructor.isEmpty() || !environment.isEmpty()); + assert( + (constructorFunction == 0 && constructor.isEmpty()) + || *constructorFunction == 0); + assert(factory != 0 && !factory->is()); +#if defined DISABLE_DYNLOADING + assert(!environment.isEmpty()); + if (constructor.isEmpty()) { + css::uno::Environment curEnv(css::uno::Environment::getCurrent()); + css::uno::Environment env(getEnvironment(environment, implementation)); + if (!(curEnv.is() && env.is())) { + throw css::loader::CannotActivateFactoryException( + "cannot get environments", + css::uno::Reference<css::uno::XInterface>()); } -#endif - if (env.get() == currentEnv.get()) - { - xRet.set( - static_cast<css::uno::XInterface *>( - (*reinterpret_cast<component_getFactoryFunc>(pGetter))( - aImplName.getStr(), xMgr.get(), 0)), - SAL_NO_ACQUIRE); + if (curEnv.get() != env.get()) { + std::abort();//TODO } - else - { - Mapping aCurrent2Env( currentEnv, env ); - Mapping aEnv2Current( env, currentEnv ); - - if (aCurrent2Env.is() && aEnv2Current.is()) - { - void * pSMgr = aCurrent2Env.mapInterface( - xMgr.get(), ::getCppuType( &xMgr ) ); - - void * pSSF = NULL; - - env.invoke(s_getFactory, pGetter, &aImplName, pSMgr, 0, &pSSF); - - if (pSMgr) - { - (*env.get()->pExtEnv->releaseInterface)( - env.get()->pExtEnv, pSMgr ); - } - - if (pSSF) - { - aEnv2Current.mapInterface( - reinterpret_cast< void ** >( &xRet ), - pSSF, ::getCppuType( &xRet ) ); - (env.get()->pExtEnv->releaseInterface)( - env.get()->pExtEnv, pSSF ); - } - else - { - rExcMsg = rModulePath + - ": cannot get factory of " + - "demanded implementation: " + - OStringToOUString( - aImplName, RTL_TEXTENCODING_ASCII_US ); - } + rtl::OUString name(prefix == "direct" ? implementation : uri); + lib_to_factory_mapping const * map = lo_get_factory_map(); + component_getFactoryFunc fp; + for (int i = 0; map[i].name != 0; ++i) { + if (name.equalsAscii(map[i].name)) { + fp = map[i].component_getFactory_function; + break; } - else - { - rExcMsg = - "cannot get uno mappings: C++ <=> UNO!"; + } + if (fp == 0) { + throw css::loader::CannotActivateFactoryException( + "unknown factory name \"" + name + "\"", + css::uno::Reference<css::uno::XInterface>()); + } + *factory = invokeComponentFactory( + css::uno::Environment::getCurrent(), + getEnvironment(environment, implementation), fp, uri, + implementation, serviceManager); + } else { + lib_to_constructor_mapping const * map = lo_get_constructor_map(); + for (int i = 0; map[i].name != 0; ++i) { + if (constructor.equalsAscii(map[i].name)) { + *constructorFunction + = reinterpret_cast<ImplementationConstructorFn *>( + map[i].constructor_function); + return; } } - } - else - { - rExcMsg = "cannot get uno environments!"; - } - - return xRet; -} - -} // namespace - -namespace cppuhelper { namespace detail { - -css::uno::Reference<css::uno::XInterface> loadSharedLibComponentFactory( - OUString const & uri, OUString const & rEnvironment, - OUString const & rPrefix, OUString const & rImplName, - css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr) -{ -#ifndef DISABLE_DYNLOADING - OUString moduleUri(uri); - oslModule lib = osl_loadModule( - moduleUri.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL ); - if (! lib) - { - OUString const msg("loading component library failed: " + moduleUri); - SAL_WARN("cppuhelper", msg); - throw loader::CannotActivateFactoryException(msg, - Reference< XInterface >() ); + throw css::loader::CannotActivateFactoryException( + "unknown constructor name \"" + constructor + "\"", + css::uno::Reference<css::uno::XInterface>()); } #else - oslModule lib; - OUString moduleUri("MAIN"); - if (! osl_getModuleHandle( NULL, &lib)) - { - throw loader::CannotActivateFactoryException( - "osl_getModuleHandle of the executable: ", - Reference< XInterface >() ); - } -#endif - - Reference< XInterface > xRet; - - OUString aExcMsg; - - OUString aFullPrefix(rPrefix); - if (!aFullPrefix.isEmpty()) { - aFullPrefix += "_"; - } - OUString aGetFactoryName = aFullPrefix + COMPONENT_GETFACTORY; - if (rPrefix == "direct") - aGetFactoryName = rImplName.replace('.', '_') + "_" + COMPONENT_GETFACTORY; - - oslGenericFunction pSym = NULL; - -#ifdef DISABLE_DYNLOADING - - OString sName; - const lib_to_component_mapping *map = NULL; - if (rPrefix == "direct") - { - sName = OUStringToOString(rImplName, RTL_TEXTENCODING_ASCII_US); - map = lo_get_implementation_map(); - } - else - { - sName = OUStringToOString(uri, RTL_TEXTENCODING_ASCII_US); - map = lo_get_library_map(); - } - for (int i = 0; pSym == NULL && map[i].name != NULL; ++i) - { - if ( sName == map[i].name ) - pSym = (oslGenericFunction) map[i].component_getFactory_function; - } - if ( pSym == NULL ) - { - fprintf( stderr, "attempting to load unknown library %s\n", OUStringToOString( uri, RTL_TEXTENCODING_ASCII_US ).getStr() ); - assert( !"Attempt to load unknown library" ); + osl::Module mod(uri, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL); + if (!mod.is()) { + throw css::loader::CannotActivateFactoryException( + "loading component library <" + uri + "> failed", + css::uno::Reference<css::uno::XInterface>()); } -#else - - if ( pSym == NULL ) - pSym = osl_getFunctionSymbol( lib, aGetFactoryName.pData ); -#endif - - if (pSym != 0) - { - uno::Environment env; - if (rEnvironment.isEmpty()) { -#if defined DISABLE_DYNLOADING - //TODO: assert(false); // this cannot happen - env = getEnvironment(CPPU_CURRENT_LANGUAGE_BINDING_NAME, rImplName); - -#else - getLibEnv( - lib, &env, Environment::getCurrent(), rImplName, aFullPrefix); -#endif + if (constructor.isEmpty()) { + rtl::OUString sym; + if (prefix == "direct") { + sym = implementation.replace('.', '_') + "_" + COMPONENT_GETFACTORY; + } else if (!prefix.isEmpty()) { + sym = prefix + "_" + COMPONENT_GETFACTORY; } else { - env = getEnvironment(rEnvironment, rImplName); + sym = COMPONENT_GETFACTORY; } - - xRet = invokeComponentFactory( - env, pSym, moduleUri, rImplName, xMgr, aExcMsg ); - } - else - { - aExcMsg = moduleUri; - aExcMsg += ": cannot get symbol: "; - aExcMsg += aGetFactoryName; + oslGenericFunction fp = mod.getFunctionSymbol(sym); + if (fp == 0) { + throw css::loader::CannotActivateFactoryException( + ("no factory symbol \"" + sym + "\" in component library <" + + uri + ">"), + css::uno::Reference<css::uno::XInterface>()); + } + css::uno::Environment curEnv(css::uno::Environment::getCurrent()); + *factory = invokeComponentFactory( + curEnv, + (environment.isEmpty() + ? getEnvironmentFromModule(mod, curEnv, implementation, prefix) + : getEnvironment(environment, implementation)), + reinterpret_cast<component_getFactoryFunc>(fp), uri, implementation, + serviceManager); + } else { + oslGenericFunction fp = mod.getFunctionSymbol(constructor); + if (fp == 0) { + throw css::loader::CannotActivateFactoryException( + ("no constructor symbol \"" + constructor + + "\" in component library <" + uri + ">"), + css::uno::Reference<css::uno::XInterface>()); + } + *constructorFunction = reinterpret_cast<ImplementationConstructorFn *>( + fp); } - - if (! xRet.is()) - { -#ifndef DISABLE_DYNLOADING - osl_unloadModule( lib ); + mod.release(); #endif - SAL_WARN("cppuhelper", "### cannot activate factory: " << aExcMsg); - throw loader::CannotActivateFactoryException( - aExcMsg, - Reference< XInterface >() ); - } - return xRet; } -} } +#if !defined DISABLE_DYNLOADING -#ifndef DISABLE_DYNLOADING - -//============================================================================== -extern "C" { static void s_writeInfo(va_list * pParam) +css::uno::Reference<css::uno::XInterface> cppu::loadSharedLibComponentFactory( + rtl::OUString const & uri, rtl::OUString const & rPath, + rtl::OUString const & rImplName, + css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr, + css::uno::Reference<css::registry::XRegistryKey> const & xKey) + SAL_THROW((css::loader::CannotActivateFactoryException)) { - component_writeInfoFunc pSym = va_arg(*pParam, component_writeInfoFunc); - void * pSMgr = va_arg(*pParam, void *); - void * pKey = va_arg(*pParam, void *); - sal_Bool * pbRet = va_arg(*pParam, sal_Bool *); + assert(rPath.isEmpty()); (void) rPath; + assert(!xKey.is()); (void) xKey; + css::uno::Reference<css::uno::XInterface> fac; + cppuhelper::detail::loadSharedLibComponentFactory( + uri, "", "", rImplName, "", xMgr, 0, &fac); + return fac; +} - *pbRet = pSym(pSMgr, pKey); +namespace { -}} +extern "C" void writeInfo(va_list * args) { + component_writeInfoFunc fn = va_arg(*args, component_writeInfoFunc); + void * smgr = va_arg(*args, void *); + void * key = va_arg(*args, void *); + sal_Bool * ok = va_arg(*args, sal_Bool *); + *ok = (*fn)(smgr, key); +} -namespace cppu { +} -void SAL_CALL writeSharedLibComponentInfo( - OUString const & uri, OUString const & rPath, - Reference< lang::XMultiServiceFactory > const & xMgr, - Reference< registry::XRegistryKey > const & xKey ) - SAL_THROW( (registry::CannotRegisterImplementationException) ) +void cppu::writeSharedLibComponentInfo( + rtl::OUString const & uri, rtl::OUString const & rPath, + css::uno::Reference<css::lang::XMultiServiceFactory> const & xMgr, + css::uno::Reference<css::registry::XRegistryKey> const & xKey) + SAL_THROW((css::registry::CannotRegisterImplementationException)) { - (void) rPath; - assert(rPath.isEmpty()); - oslModule lib = osl_loadModule( - uri.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL ); - if (! lib) - { - OUString const msg("loading component library failed: " + uri); - SAL_WARN("cppuhelper", msg); - throw registry::CannotRegisterImplementationException(msg, - Reference< XInterface >() ); + assert(rPath.isEmpty()); (void) rPath; + osl::Module mod(uri, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL); + if (!mod.is()) { + throw css::registry::CannotRegisterImplementationException( + "loading component library <" + uri + "> failed", + css::uno::Reference<css::uno::XInterface>()); } - - sal_Bool bRet = sal_False; - - uno::Environment currentEnv(Environment::getCurrent()); - uno::Environment env; - - OUString aExcMsg; - - getLibEnv(lib, &env, currentEnv); - - OUString aWriteInfoName = COMPONENT_WRITEINFO; - oslGenericFunction pSym = osl_getFunctionSymbol( lib, aWriteInfoName.pData ); - if (pSym != 0) - { - if (env.is() && currentEnv.is()) - { - Mapping aCurrent2Env( currentEnv, env ); - if (aCurrent2Env.is()) - { - void * pSMgr = aCurrent2Env.mapInterface( - xMgr.get(), ::getCppuType( &xMgr ) ); - void * pKey = aCurrent2Env.mapInterface( - xKey.get(), ::getCppuType( &xKey ) ); - if (pKey) - { - env.invoke(s_writeInfo, pSym, pSMgr, pKey, &bRet); - - - (*env.get()->pExtEnv->releaseInterface)( - env.get()->pExtEnv, pKey ); - if (! bRet) - { - aExcMsg = uri; - aExcMsg += ": component_writeInfo() " - "returned false!"; - } - } - else - { - // key is mandatory - aExcMsg = uri; - aExcMsg += ": registry is mandatory to invoke" - " component_writeInfo()!"; - } - - if (pSMgr) - { - (*env.get()->pExtEnv->releaseInterface)( - env.get()->pExtEnv, pSMgr ); - } - } - else - { - aExcMsg = "cannot get uno mapping: C++ <=> UNO!"; - } - } - else - { - aExcMsg = "cannot get uno environments!"; - } + oslGenericFunction fp = mod.getFunctionSymbol(COMPONENT_WRITEINFO); + if (fp == 0) { + throw css::registry::CannotRegisterImplementationException( + ("no symbol \"" COMPONENT_WRITEINFO "\" in component library <" + + uri + ">"), + css::uno::Reference<css::uno::XInterface>()); } - else - { - aExcMsg = uri; - aExcMsg += ": cannot get symbol: "; - aExcMsg += aWriteInfoName; + css::uno::Environment curEnv(css::uno::Environment::getCurrent()); + css::uno::Environment env(getEnvironmentFromModule(mod, curEnv, "", "")); + if (!(curEnv.is() && env.is())) { + throw css::registry::CannotRegisterImplementationException( + "cannot get environments", + css::uno::Reference<css::uno::XInterface>()); } - -//! -//! OK: please look at #88219# -//! -//! ::osl_unloadModule( lib); - if (! bRet) - { - SAL_WARN("cppuhelper", "### cannot write component info: " << aExcMsg); - throw registry::CannotRegisterImplementationException( - aExcMsg, Reference< XInterface >() ); + css::uno::Mapping map(curEnv, env); + if (!map.is()) { + throw css::registry::CannotRegisterImplementationException( + "cannot get mapping", css::uno::Reference<css::uno::XInterface>()); + } + void * smgr = map.mapInterface( + xMgr.get(), cppu::UnoType<css::lang::XMultiServiceFactory>::get()); + void * key = map.mapInterface( + xKey.get(), cppu::UnoType<css::registry::XRegistryKey>::get()); + sal_Bool ok; + env.invoke(writeInfo, fp, smgr, key, &ok); + (*env.get()->pExtEnv->releaseInterface)(env.get()->pExtEnv, key); + if (smgr != 0) { + (*env.get()->pExtEnv->releaseInterface)(env.get()->pExtEnv, smgr); + } + if (!ok) { + throw css::registry::CannotRegisterImplementationException( + ("calling \"" COMPONENT_WRITEINFO "\" in component library <" + uri + + "> returned false"), + css::uno::Reference<css::uno::XInterface>()); } } -} - -#endif // DISABLE_DYNLOADING +#endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |