[Libreoffice-commits] core.git: cppuhelper/source

Michael Stahl mstahl at redhat.com
Tue Jan 17 22:03:35 UTC 2017


 cppuhelper/source/loadsharedlibcomponentfactory.hxx |    2 
 cppuhelper/source/servicemanager.cxx                |   45 ++++-------
 cppuhelper/source/servicemanager.hxx                |    4 -
 cppuhelper/source/shlib.cxx                         |   77 ++++++++++++++++++--
 4 files changed, 94 insertions(+), 34 deletions(-)

New commits:
commit 6ef033669762a0c7ce70c111458437d5e727a4ae
Author: Michael Stahl <mstahl at redhat.com>
Date:   Fri Jan 13 23:40:51 2017 +0100

    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 at libreoffice.org>
    Reviewed-by: Michael Stahl <mstahl at redhat.com>

diff --git a/cppuhelper/source/loadsharedlibcomponentfactory.hxx b/cppuhelper/source/loadsharedlibcomponentfactory.hxx
index 7062d86..df6e226 100644
--- a/cppuhelper/source/loadsharedlibcomponentfactory.hxx
+++ b/cppuhelper/source/loadsharedlibcomponentfactory.hxx
@@ -35,7 +35,7 @@ void 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);
 
 } }
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
index 780fe02..6d2321c 100644
--- a/cppuhelper/source/servicemanager.cxx
+++ b/cppuhelper/source/servicemanager.cxx
@@ -686,9 +686,9 @@ cppuhelper::ServiceManager::Data::Implementation::createInstance(
     bool singletonRequest)
 {
     css::uno::Reference<css::uno::XInterface> inst;
-    if (constructor != nullptr) {
+    if (constructor) {
         inst.set(
-            (*constructor)(context.get(), css::uno::Sequence<css::uno::Any>()),
+            constructor(context.get(), css::uno::Sequence<css::uno::Any>()),
             SAL_NO_ACQUIRE);
     } else if (factory1.is()) {
             inst = factory1->createInstanceWithContext(context);
@@ -706,8 +706,8 @@ cppuhelper::ServiceManager::Data::Implementation::createInstanceWithArguments(
     bool singletonRequest, css::uno::Sequence<css::uno::Any> const & arguments)
 {
     css::uno::Reference<css::uno::XInterface> inst;
-    if (constructor != nullptr) {
-        inst.set((*constructor)(context.get(), arguments), SAL_NO_ACQUIRE);
+    if (constructor) {
+        inst.set(constructor(context.get(), arguments), SAL_NO_ACQUIRE);
         //HACK: The constructor will either observe arguments and return inst
         // that does not implement XInitialization (or null), or ignore
         // arguments and return inst that implements XInitialization; this
@@ -797,7 +797,7 @@ void cppuhelper::ServiceManager::loadImplementation(
             "Cannot expand URI" + implementation->info->uri + ": " + e.Message,
             static_cast< cppu::OWeakObject * >(this));
     }
-    cppuhelper::ImplementationConstructorFn * ctor = nullptr;
+    cppuhelper::WrapperConstructorFn ctor;
     css::uno::Reference< css::uno::XInterface > f0;
     // Special handling of SharedLibrary loader, with support for environment,
     // constructor, and prefix arguments:
@@ -808,27 +808,8 @@ void cppuhelper::ServiceManager::loadImplementation(
             uri, implementation->info->environment,
             implementation->info->prefix, implementation->info->name,
             implementation->info->constructor, this, &ctor, &f0);
-        if (ctor != nullptr) {
+        if (ctor) {
             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 {
         SAL_WARN_IF(
@@ -864,7 +845,7 @@ void cppuhelper::ServiceManager::loadImplementation(
     }
     css::uno::Reference<css::lang::XSingleComponentFactory> f1;
     css::uno::Reference<css::lang::XSingleServiceFactory> f2;
-    if (ctor == nullptr) {
+    if (!ctor) {
         f1.set(f0, css::uno::UNO_QUERY);
         if (!f1.is()) {
             f2.set(f0, css::uno::UNO_QUERY);
@@ -1978,7 +1959,15 @@ void cppuhelper::ServiceManager::preloadImplementations() {
                 else
                 {
                     // 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;
@@ -2002,7 +1991,7 @@ void cppuhelper::ServiceManager::preloadImplementations() {
                 }
 
                 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->factory2 = xSSFactory;
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx
index ca00213..5f6efd0 100644
--- a/cppuhelper/source/servicemanager.hxx
+++ b/cppuhelper/source/servicemanager.hxx
@@ -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<
     css::lang::XServiceInfo, css::lang::XMultiServiceFactory,
     css::lang::XMultiComponentFactory, css::container::XSet,
@@ -149,7 +151,7 @@ public:
             enum Status { STATUS_NEW, STATUS_WRAPPER, STATUS_LOADED };
 
             std::shared_ptr< ImplementationInfo > info;
-            ImplementationConstructorFn * constructor;
+            WrapperConstructorFn constructor;
             css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
             css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
             css::uno::Reference< css::lang::XComponent > component;
diff --git a/cppuhelper/source/shlib.cxx b/cppuhelper/source/shlib.cxx
index 0cffab6..fa88cc4 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


More information about the Libreoffice-commits mailing list