diff options
author | Michael Stahl <mstahl@redhat.com> | 2017-01-13 23:40:51 +0100 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2017-01-17 22:03:11 +0000 |
commit | 6ef033669762a0c7ce70c111458437d5e727a4ae (patch) | |
tree | 56f4a621c7f6a4c22e8822be00d71ff5bffefc89 /cppuhelper/source/shlib.cxx | |
parent | 57f66925d4c43dad7b0e2e67f91fc4d965f3f92d (diff) |
cppuhelper: implement environment mapping for constructor functions
ae3a0c8da50b36db395984637f5ad74d3b4887bc unfortunately forgot to
implement mapping between UNO environments for constructor functions
in the UNO service manager, and due to the many componennt conversions
to constructor functions since then, the log UNO purpose environment
has become mostly useless.
Save the environment, create a closure today!
https://wiki.openoffice.org/wiki/Uno/Spec/Log_Environment
Change-Id: Idc03b5ed9529da8e81cd91efe50cbeceffa2b247
Reviewed-on: https://gerrit.libreoffice.org/33060
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Michael Stahl <mstahl@redhat.com>
Diffstat (limited to 'cppuhelper/source/shlib.cxx')
-rw-r--r-- | cppuhelper/source/shlib.cxx | 77 |
1 files changed, 73 insertions, 4 deletions
diff --git a/cppuhelper/source/shlib.cxx b/cppuhelper/source/shlib.cxx index 0cffab6783f8..fa88cc4b484c 100644 --- a/cppuhelper/source/shlib.cxx +++ b/cppuhelper/source/shlib.cxx @@ -160,6 +160,70 @@ css::uno::Reference<css::uno::XInterface> invokeComponentFactory( } } +extern "C" void getInstance(va_list * args) { + cppuhelper::ImplementationConstructorFn * fn = va_arg(*args, cppuhelper::ImplementationConstructorFn *); + void * ctxt = va_arg(*args, void *); + assert(ctxt); + void * argseq = va_arg(*args, void *); + assert(argseq); + void ** instance = va_arg(*args, void **); + assert(instance); + assert(*instance == nullptr); + *instance = (*fn)(static_cast<css::uno::XComponentContext*>(ctxt), + *static_cast<css::uno::Sequence<css::uno::Any> const*>(argseq)); +} + +cppuhelper::WrapperConstructorFn mapConstructorFn( + css::uno::Environment const & source, css::uno::Environment const & target, + cppuhelper::ImplementationConstructorFn *const constructorFunction) +{ + if (!(source.is() && target.is())) { + throw css::loader::CannotActivateFactoryException( + "cannot get environments", + css::uno::Reference<css::uno::XInterface>()); + } + if (source.get() == target.get()) { + return cppuhelper::WrapperConstructorFn(constructorFunction); + } else { + // note: it should be valid to capture these mappings because they are + // ref-counted, and the returned closure will always be invoked in the + // "source" environment + 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>()); + } + return [mapFrom, mapTo, target, constructorFunction] + (css::uno::XComponentContext *const context, css::uno::Sequence<css::uno::Any> const& args) + { + void *const ctxt = mapTo.mapInterface( + context, + cppu::UnoType<css::uno::XComponentContext>::get()); + if (args.getLength() > 0) { + std::abort(); // TODO map args + } + void * instance = nullptr; + target.invoke(getInstance, constructorFunction, ctxt, &args, &instance); + if (ctxt != nullptr) { + (*target.get()->pExtEnv->releaseInterface)( + target.get()->pExtEnv, ctxt); + } + css::uno::XInterface * res = nullptr; + if (instance == nullptr) { + return res; + } + mapFrom.mapInterface( + reinterpret_cast<void **>(&res), instance, + cppu::UnoType<css::uno::XInterface>::get()); + (*target.get()->pExtEnv->releaseInterface)( + target.get()->pExtEnv, instance); + return res; + }; + } +} + } void cppuhelper::detail::loadSharedLibComponentFactory( @@ -167,13 +231,13 @@ void cppuhelper::detail::loadSharedLibComponentFactory( rtl::OUString const & prefix, rtl::OUString const & implementation, rtl::OUString const & constructor, css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager, - ImplementationConstructorFn ** constructorFunction, + WrapperConstructorFn * constructorFunction, css::uno::Reference<css::uno::XInterface> * factory) { assert(constructor.isEmpty() || !environment.isEmpty()); assert( (constructorFunction == nullptr && constructor.isEmpty()) - || *constructorFunction == nullptr); + || !*constructorFunction); assert(factory != nullptr && !factory->is()); #if defined DISABLE_DYNLOADING assert(!environment.isEmpty()); @@ -273,8 +337,13 @@ void cppuhelper::detail::loadSharedLibComponentFactory( + "\" in component library <" + uri + ">"), css::uno::Reference<css::uno::XInterface>()); } - *constructorFunction = reinterpret_cast<ImplementationConstructorFn *>( - fp); + css::uno::Environment curEnv(css::uno::Environment::getCurrent()); + *constructorFunction = mapConstructorFn( + curEnv, + (environment.isEmpty() + ? getEnvironmentFromModule(mod, curEnv, implementation, prefix) + : getEnvironment(environment, implementation)), + reinterpret_cast<ImplementationConstructorFn *>(fp)); } mod.release(); #endif |