Kaydet (Commit) 6ef03366 authored tarafından Michael Stahl's avatar Michael Stahl

cppuhelper: implement environment mapping for constructor functions

ae3a0c8d 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/33060Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarMichael Stahl <mstahl@redhat.com>
üst 57f66925
...@@ -35,7 +35,7 @@ void loadSharedLibComponentFactory( ...@@ -35,7 +35,7 @@ void loadSharedLibComponentFactory(
rtl::OUString const & prefix, rtl::OUString const & implementation, rtl::OUString const & prefix, rtl::OUString const & implementation,
rtl::OUString const & constructor, rtl::OUString const & constructor,
css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager, css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager,
ImplementationConstructorFn ** constructorFunction, WrapperConstructorFn * constructorFunction,
css::uno::Reference<css::uno::XInterface> * factory); css::uno::Reference<css::uno::XInterface> * factory);
} } } }
......
...@@ -686,9 +686,9 @@ cppuhelper::ServiceManager::Data::Implementation::createInstance( ...@@ -686,9 +686,9 @@ cppuhelper::ServiceManager::Data::Implementation::createInstance(
bool singletonRequest) bool singletonRequest)
{ {
css::uno::Reference<css::uno::XInterface> inst; css::uno::Reference<css::uno::XInterface> inst;
if (constructor != nullptr) { if (constructor) {
inst.set( inst.set(
(*constructor)(context.get(), css::uno::Sequence<css::uno::Any>()), constructor(context.get(), css::uno::Sequence<css::uno::Any>()),
SAL_NO_ACQUIRE); SAL_NO_ACQUIRE);
} else if (factory1.is()) { } else if (factory1.is()) {
inst = factory1->createInstanceWithContext(context); inst = factory1->createInstanceWithContext(context);
...@@ -706,8 +706,8 @@ cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments( ...@@ -706,8 +706,8 @@ cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments) bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
{ {
css::uno::Reference<css::uno::XInterface> inst; css::uno::Reference<css::uno::XInterface> inst;
if (constructor != nullptr) { if (constructor) {
inst.set((*constructor)(context.get(), arguments), SAL_NO_ACQUIRE); inst.set(constructor(context.get(), arguments), SAL_NO_ACQUIRE);
//HACK: The constructor will either observe arguments and return inst //HACK: The constructor will either observe arguments and return inst
// that does not implement XInitialization (or null), or ignore // that does not implement XInitialization (or null), or ignore
// arguments and return inst that implements XInitialization; this // arguments and return inst that implements XInitialization; this
...@@ -797,7 +797,7 @@ void cppuhelper::ServiceManager::loadImplementation( ...@@ -797,7 +797,7 @@ void cppuhelper::ServiceManager::loadImplementation(
"Cannot expand URI" + implementation->info->uri + ": " + e.Message, "Cannot expand URI" + implementation->info->uri + ": " + e.Message,
static_cast< cppu::OWeakObject * >(this)); static_cast< cppu::OWeakObject * >(this));
} }
cppuhelper::ImplementationConstructorFn * ctor = nullptr; cppuhelper::WrapperConstructorFn ctor;
css::uno::Reference< css::uno::XInterface > f0; css::uno::Reference< css::uno::XInterface > f0;
// Special handling of SharedLibrary loader, with support for environment, // Special handling of SharedLibrary loader, with support for environment,
// constructor, and prefix arguments: // constructor, and prefix arguments:
...@@ -808,27 +808,8 @@ void cppuhelper::ServiceManager::loadImplementation( ...@@ -808,27 +808,8 @@ void cppuhelper::ServiceManager::loadImplementation(
uri, implementation->info->environment, uri, implementation->info->environment,
implementation->info->prefix, implementation->info->name, implementation->info->prefix, implementation->info->name,
implementation->info->constructor, this, &ctor, &f0); implementation->info->constructor, this, &ctor, &f0);
if (ctor != nullptr) { if (ctor) {
assert(!implementation->info->environment.isEmpty()); assert(!implementation->info->environment.isEmpty());
css::uno::Environment curEnv(css::uno::Environment::getCurrent());
if (!curEnv.is()) {
throw css::uno::DeploymentException(
"cannot get current environment",
css::uno::Reference<css::uno::XInterface>());
}
css::uno::Environment env(
cppuhelper::detail::getEnvironment(
implementation->info->environment,
implementation->info->name));
if (!env.is()) {
throw css::uno::DeploymentException(
("cannot get environment "
+ implementation->info->environment),
css::uno::Reference<css::uno::XInterface>());
}
if (curEnv.get() != env.get()) {
std::abort();//TODO
}
} }
} else { } else {
SAL_WARN_IF( SAL_WARN_IF(
...@@ -864,7 +845,7 @@ void cppuhelper::ServiceManager::loadImplementation( ...@@ -864,7 +845,7 @@ void cppuhelper::ServiceManager::loadImplementation(
} }
css::uno::Reference<css::lang::XSingleComponentFactory> f1; css::uno::Reference<css::lang::XSingleComponentFactory> f1;
css::uno::Reference<css::lang::XSingleServiceFactory> f2; css::uno::Reference<css::lang::XSingleServiceFactory> f2;
if (ctor == nullptr) { if (!ctor) {
f1.set(f0, css::uno::UNO_QUERY); f1.set(f0, css::uno::UNO_QUERY);
if (!f1.is()) { if (!f1.is()) {
f2.set(f0, css::uno::UNO_QUERY); f2.set(f0, css::uno::UNO_QUERY);
...@@ -1978,7 +1959,15 @@ void cppuhelper::ServiceManager::preloadImplementations() { ...@@ -1978,7 +1959,15 @@ void cppuhelper::ServiceManager::preloadImplementations() {
else else
{ {
// get function symbol component factory // get function symbol component factory
fpFactory = aModule.getFunctionSymbol(iterator->second->info->constructor); aTargetEnv = cppuhelper::detail::getEnvironment(iterator->second->info->environment, iterator->second->info->name);
if (aSourceEnv.get() == aTargetEnv.get())
{
fpFactory = aModule.getFunctionSymbol(iterator->second->info->constructor);
}
else
{
fpFactory = nullptr;
}
} }
css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory; css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory;
...@@ -2002,7 +1991,7 @@ void cppuhelper::ServiceManager::preloadImplementations() { ...@@ -2002,7 +1991,7 @@ void cppuhelper::ServiceManager::preloadImplementations() {
} }
if (!iterator->second->info->constructor.isEmpty() && fpFactory) if (!iterator->second->info->constructor.isEmpty() && fpFactory)
iterator->second->constructor = reinterpret_cast<ImplementationConstructorFn *>(fpFactory); iterator->second->constructor = WrapperConstructorFn(reinterpret_cast<ImplementationConstructorFn *>(fpFactory));
iterator->second->factory1 = xSCFactory; iterator->second->factory1 = xSCFactory;
iterator->second->factory2 = xSSFactory; iterator->second->factory2 = xSSFactory;
......
...@@ -50,6 +50,8 @@ typedef css::uno::XInterface * SAL_CALL ImplementationConstructorFn( ...@@ -50,6 +50,8 @@ typedef css::uno::XInterface * SAL_CALL ImplementationConstructorFn(
} }
typedef std::function<css::uno::XInterface * (css::uno::XComponentContext *, css::uno::Sequence<css::uno::Any> const&)> WrapperConstructorFn;
typedef cppu::WeakComponentImplHelper< typedef cppu::WeakComponentImplHelper<
css::lang::XServiceInfo, css::lang::XMultiServiceFactory, css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
css::lang::XMultiComponentFactory, css::container::XSet, css::lang::XMultiComponentFactory, css::container::XSet,
...@@ -149,7 +151,7 @@ public: ...@@ -149,7 +151,7 @@ public:
enum Status { STATUS_NEW, STATUS_WRAPPER, STATUS_LOADED }; enum Status { STATUS_NEW, STATUS_WRAPPER, STATUS_LOADED };
std::shared_ptr< ImplementationInfo > info; std::shared_ptr< ImplementationInfo > info;
ImplementationConstructorFn * constructor; WrapperConstructorFn constructor;
css::uno::Reference< css::lang::XSingleComponentFactory > factory1; css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
css::uno::Reference< css::lang::XSingleServiceFactory > factory2; css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
css::uno::Reference< css::lang::XComponent > component; css::uno::Reference< css::lang::XComponent > component;
......
...@@ -160,6 +160,70 @@ css::uno::Reference<css::uno::XInterface> invokeComponentFactory( ...@@ -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( void cppuhelper::detail::loadSharedLibComponentFactory(
...@@ -167,13 +231,13 @@ void cppuhelper::detail::loadSharedLibComponentFactory( ...@@ -167,13 +231,13 @@ void cppuhelper::detail::loadSharedLibComponentFactory(
rtl::OUString const & prefix, rtl::OUString const & implementation, rtl::OUString const & prefix, rtl::OUString const & implementation,
rtl::OUString const & constructor, rtl::OUString const & constructor,
css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager, css::uno::Reference<css::lang::XMultiServiceFactory> const & serviceManager,
ImplementationConstructorFn ** constructorFunction, WrapperConstructorFn * constructorFunction,
css::uno::Reference<css::uno::XInterface> * factory) css::uno::Reference<css::uno::XInterface> * factory)
{ {
assert(constructor.isEmpty() || !environment.isEmpty()); assert(constructor.isEmpty() || !environment.isEmpty());
assert( assert(
(constructorFunction == nullptr && constructor.isEmpty()) (constructorFunction == nullptr && constructor.isEmpty())
|| *constructorFunction == nullptr); || !*constructorFunction);
assert(factory != nullptr && !factory->is()); assert(factory != nullptr && !factory->is());
#if defined DISABLE_DYNLOADING #if defined DISABLE_DYNLOADING
assert(!environment.isEmpty()); assert(!environment.isEmpty());
...@@ -273,8 +337,13 @@ void cppuhelper::detail::loadSharedLibComponentFactory( ...@@ -273,8 +337,13 @@ void cppuhelper::detail::loadSharedLibComponentFactory(
+ "\" in component library <" + uri + ">"), + "\" in component library <" + uri + ">"),
css::uno::Reference<css::uno::XInterface>()); css::uno::Reference<css::uno::XInterface>());
} }
*constructorFunction = reinterpret_cast<ImplementationConstructorFn *>( css::uno::Environment curEnv(css::uno::Environment::getCurrent());
fp); *constructorFunction = mapConstructorFn(
curEnv,
(environment.isEmpty()
? getEnvironmentFromModule(mod, curEnv, implementation, prefix)
: getEnvironment(environment, implementation)),
reinterpret_cast<ImplementationConstructorFn *>(fp));
} }
mod.release(); mod.release();
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment