[Libreoffice-commits] .: cppuhelper/source

Stephan Bergmann sbergmann at kemper.freedesktop.org
Fri Jun 1 01:06:37 PDT 2012


 cppuhelper/source/defaultbootstrap.cxx |  433 +++++++++++++++++++++++----------
 1 file changed, 314 insertions(+), 119 deletions(-)

New commits:
commit c16d0dd846e25df56feffe868a15eb33bb55e42a
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Fri Jun 1 09:59:49 2012 +0200

    fdo#49291 Postpone actual factory instantiation as long as possible
    
    ...see comment in ServiceManager::createContentEnumeration for a rationale.
    
    Splitting ImplementationInfo out of Implementation has become necessary to avoid
    circular references.
    
    Change-Id: I29aef81ce78b9ab71e18663f8c7e6ca913c6a650

diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx
index c903c2b..55a4f09 100644
--- a/cppuhelper/source/defaultbootstrap.cxx
+++ b/cppuhelper/source/defaultbootstrap.cxx
@@ -60,6 +60,7 @@
 #include "cppuhelper/compbase8.hxx"
 #include "cppuhelper/component_context.hxx"
 #include "cppuhelper/implbase1.hxx"
+#include "cppuhelper/implbase3.hxx"
 #include "cppuhelper/shlib.hxx"
 #include "osl/file.hxx"
 #include "registry/registry.hxx"
@@ -124,36 +125,51 @@ void decodeRdbUri(rtl::OUString * uri, bool * optional, bool * directory) {
     }
 }
 
+struct ImplementationInfo: private boost::noncopyable {
+    ImplementationInfo(
+        rtl::OUString const & theName, rtl::OUString const & theLoader,
+        rtl::OUString const & theUri, rtl::OUString const & thePrefix,
+        css::uno::Reference< css::uno::XComponentContext > const &
+            theAlienContext):
+        name(theName), loader(theLoader), uri(theUri), prefix(thePrefix),
+        alienContext(theAlienContext)
+    {}
+
+    explicit ImplementationInfo(rtl::OUString const & theName): name(theName) {}
+
+    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;
+};
+
 struct Implementation: private boost::noncopyable {
     Implementation(
-        rtl::OUString const & theName, rtl::OUString const & theLoader,
-        rtl::OUString const & theUri,
-        rtl::OUString const & thePrefix = rtl::OUString(),
+        rtl::OUString const & name, rtl::OUString const & loader,
+        rtl::OUString const & uri,
+        rtl::OUString const & prefix = rtl::OUString(),
         css::uno::Reference< css::uno::XComponentContext > const &
-            theAlienContext
+            alienContext
                 = css::uno::Reference< css::uno::XComponentContext >()):
-        name(theName), loader(theLoader), uri(theUri), prefix(thePrefix),
-        alienContext(theAlienContext), loaded(false)
+        info(new ImplementationInfo(name, loader, uri, prefix, alienContext)),
+        loaded(false)
     {}
 
     Implementation(
-        rtl::OUString const & theName,
+        rtl::OUString const & name,
         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)
+        info(new ImplementationInfo(name)), 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;
+    boost::shared_ptr< ImplementationInfo > info;
     css::uno::Reference< css::lang::XSingleComponentFactory > factory1;
     css::uno::Reference< css::lang::XSingleServiceFactory > factory2;
     css::uno::Reference< css::lang::XComponent > component;
@@ -463,13 +479,13 @@ void Parser::handleImplementation() {
 
 void Parser::handleService() {
     rtl::OUString name(getNameAttribute());
-    implementation_->services.push_back(name);
+    implementation_->info->services.push_back(name);
     data_->services[name].push_back(implementation_);
 }
 
 void Parser::handleSingleton() {
     rtl::OUString name(getNameAttribute());
-    implementation_->singletons.push_back(name);
+    implementation_->info->singletons.push_back(name);
     data_->singletons[name].push_back(implementation_);
 }
 
@@ -585,8 +601,18 @@ public:
         context_ = context;
     }
 
+    css::uno::Reference< css::uno::XComponentContext > getContext() const {
+        assert(context_.is());
+        return context_;
+    }
+
     Data const & getData() const { return data_; }
 
+    void loadImplementation(
+        boost::shared_ptr< ImplementationInfo > const & info,
+        css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
+        css::uno::Reference< css::lang::XSingleServiceFactory > * factory2);
+
     virtual rtl::OUString SAL_CALL getImplementationName()
         throw (css::uno::RuntimeException);
 
@@ -757,12 +783,136 @@ private:
     boost::shared_ptr< Implementation > findServiceImplementation(
         rtl::OUString const & specifier);
 
-    void loadImplementation(Implementation * implementation);
-
     css::uno::Reference< css::uno::XComponentContext > context_;
     Data data_;
 };
 
+class FactoryWrapper:
+    public cppu::WeakImplHelper3<
+        css::lang::XSingleComponentFactory, css::lang::XSingleServiceFactory,
+        css::lang::XServiceInfo >,
+    private boost::noncopyable
+{
+public:
+    FactoryWrapper(
+        rtl::Reference< ServiceManager > const & manager,
+        boost::shared_ptr< ImplementationInfo > const & info):
+        manager_(manager), info_(info), loaded_(false)
+    { assert(manager.is() && info.get() != 0); }
+
+private:
+    virtual ~FactoryWrapper() {}
+
+    virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+    createInstanceWithContext(
+        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(
+        css::uno::Sequence< css::uno::Any > const & Arguments,
+        css::uno::Reference< css::uno::XComponentContext > const & Context)
+        throw (css::uno::Exception, css::uno::RuntimeException);
+
+    virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+    createInstance() throw (css::uno::Exception, css::uno::RuntimeException);
+
+    virtual css::uno::Reference< css::uno::XInterface > SAL_CALL
+    createInstanceWithArguments(
+        css::uno::Sequence< css::uno::Any > const & Arguments)
+        throw (css::uno::Exception, css::uno::RuntimeException);
+
+    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);
+
+    void loadImplementation();
+
+    rtl::Reference< ServiceManager > manager_;
+    boost::shared_ptr< ImplementationInfo > info_;
+
+    osl::Mutex mutex_;
+    bool loaded_;
+    css::uno::Reference< css::lang::XSingleComponentFactory > factory1_;
+    css::uno::Reference< css::lang::XSingleServiceFactory > factory2_;
+};
+
+void ServiceManager::loadImplementation(
+        boost::shared_ptr< ImplementationInfo > const & info,
+        css::uno::Reference< css::lang::XSingleComponentFactory > * factory1,
+        css::uno::Reference< css::lang::XSingleServiceFactory > * factory2)
+{
+    assert(
+        info.get() != 0 && factory1 != 0 && !factory1->is() && factory2 != 0
+        && !factory2->is());
+    rtl::OUString uri;
+    try {
+        uri = cppu::bootstrap_expandUri(info->uri);
+    } catch (css::lang::IllegalArgumentException & e) {
+        throw css::uno::DeploymentException(
+            "Cannot expand URI" + info->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 (!info->alienContext.is()
+        && info->loader == "com.sun.star.loader.SharedLibrary")
+    {
+        rtl::OUString prefix(info->prefix);
+        if (!prefix.isEmpty()) {
+            prefix += "_";
+        }
+        try {
+            f0 = cppu::loadSharedLibComponentFactory(
+                uri, rtl::OUString(), info->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(
+            !info->prefix.isEmpty(), "cppuhelper",
+            "Loader " << info->loader << " and non-empty prefix "
+                << info->prefix);
+        css::uno::Reference< css::uno::XComponentContext > ctxt;
+        css::uno::Reference< css::lang::XMultiComponentFactory > smgr;
+        if (info->alienContext.is()) {
+            ctxt = info->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(info->loader, ctxt),
+            css::uno::UNO_QUERY_THROW);
+        try {
+            f0 = loader->activate(
+                info->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));
+        }
+    }
+    factory1->set(f0, css::uno::UNO_QUERY);
+    if (!factory1->is()) {
+        factory2->set(f0, css::uno::UNO_QUERY);
+    }
+}
+
 rtl::OUString ServiceManager::getImplementationName()
     throw (css::uno::RuntimeException)
 {
@@ -852,7 +1002,7 @@ ServiceManager::createInstanceWithContext(
         return impl->factory2->createInstance();
     }
     throw css::uno::DeploymentException(
-        "Implementation " + impl->name + " does not provide a factory",
+        "Implementation " + impl->info->name + " does not provide a factory",
         static_cast< cppu::OWeakObject * >(this));
 }
 
@@ -876,7 +1026,7 @@ ServiceManager::createInstanceWithArgumentsAndContext(
         return impl->factory2->createInstanceWithArguments(Arguments);
     }
     throw css::uno::DeploymentException(
-        "Implementation " + impl->name + " does not provide a factory",
+        "Implementation " + impl->info->name + " does not provide a factory",
         static_cast< cppu::OWeakObject * >(this));
 }
 
@@ -1036,21 +1186,21 @@ ServiceManager::createContentEnumeration(rtl::OUString const & aServiceName)
     {
         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->loaded) {
+                // Postpone actual factory instantiation as long as possible (so
+                // that e.g. opening LO's "Tools - Macros" menu does not try to
+                // instantiate a JVM, which can lead to a synchronous error
+                // dialog when no JVM is specified, and showing the dialog while
+                // hovering over a menu can cause trouble):
+                impl->factory1 = new FactoryWrapper(this, impl->info);
+                impl->loaded = true;
+            }
         }
         if (impl->factory1.is()) {
             factories.push_back(css::uno::makeAny(impl->factory1));
@@ -1058,7 +1208,8 @@ ServiceManager::createContentEnumeration(rtl::OUString const & aServiceName)
             factories.push_back(css::uno::makeAny(impl->factory2));
         } else {
             throw css::uno::DeploymentException(
-                "Implementation " + impl->name + " does not provide a factory",
+                ("Implementation " + impl->info->name
+                 + " does not provide a factory"),
                 static_cast< cppu::OWeakObject * >(this));
         }
     }
@@ -1365,17 +1516,19 @@ bool ServiceManager::readLegacyRdbFile(rtl::OUString const & uri) {
                 uri + ": duplicate <implementation name=\"" + name + "\">",
                 css::uno::Reference< css::uno::XInterface >());
         }
-        readLegacyRdbStrings(uri, implKey, "UNO/SERVICES", &impl->services);
+        readLegacyRdbStrings(
+            uri, implKey, "UNO/SERVICES", &impl->info->services);
         for (std::vector< rtl::OUString >::const_iterator j(
-                 impl->services.begin());
-             j != impl->services.end(); ++j)
+                 impl->info->services.begin());
+             j != impl->info->services.end(); ++j)
         {
             data_.services[*j].push_back(impl);
         }
-        readLegacyRdbStrings(uri, implKey, "UNO/SINGLETONS", &impl->singletons);
+        readLegacyRdbStrings(
+            uri, implKey, "UNO/SINGLETONS", &impl->info->singletons);
         for (std::vector< rtl::OUString >::const_iterator j(
-                 impl->singletons.begin());
-             j != impl->singletons.end(); ++j)
+                 impl->info->singletons.begin());
+             j != impl->info->singletons.end(); ++j)
         {
             data_.singletons[*j].push_back(impl);
         }
@@ -1494,7 +1647,7 @@ void ServiceManager::insertLegacyFactory(
     css::uno::Sequence< rtl::OUString > services(
         factoryInfo->getSupportedServiceNames());
     for (sal_Int32 i = 0; i != services.getLength(); ++i) {
-        impl->services.push_back(services[i]);
+        impl->info->services.push_back(services[i]);
         extra.services[services[i]].push_back(impl);
     }
     if (insertExtraData(extra) && comp.is()) {
@@ -1560,15 +1713,15 @@ bool ServiceManager::insertExtraData(Data const & extra) {
             assert(i->second[0].get() != 0);
             SAL_INFO_IF(
                 i->second.size() > 1, "cppuhelper",
-                "Arbitrarily chosing " << i->second[0]->name
+                "Arbitrarily chosing " << i->second[0]->info->name
                     << " among multiple implementations for singleton "
                     << i->first);
             try {
                 cont->insertByName(
-                    name + "/service", css::uno::Any(i->second[0]->name));
+                    name + "/service", css::uno::Any(i->second[0]->info->name));
             } catch (css::container::ElementExistException &) {
                 cont->replaceByName(
-                    name + "/service", css::uno::Any(i->second[0]->name));
+                    name + "/service", css::uno::Any(i->second[0]->info->name));
             }
             try {
                 cont->insertByName(name, css::uno::Any());
@@ -1594,13 +1747,13 @@ void ServiceManager::removeRdbFiles(std::vector< rtl::OUString > const & uris) {
              j != data_.namedImplementations.end();)
         {
             assert(j->second.get() != 0);
-            if (j->second->uri == *i) {
+            if (j->second->info->uri == *i) {
                 //TODO: The below leaves data_ in an inconsistent state upon
                 // exceptions:
                 removeFromImplementationMap(
-                    &data_.services, j->second->services, j->second);
+                    &data_.services, j->second->info->services, j->second);
                 removeFromImplementationMap(
-                    &data_.singletons, j->second->singletons, j->second);
+                    &data_.singletons, j->second->info->singletons, j->second);
                 data_.namedImplementations.erase(j++);
             } else {
                 ++j;
@@ -1626,11 +1779,11 @@ bool ServiceManager::removeLegacyFactory(
         assert(i->second.get() != 0);
         //TODO: The below leaves data_ in an inconsistent state upon exceptions:
         removeFromImplementationMap(
-            &data_.services, i->second->services, i->second);
+            &data_.services, i->second->info->services, i->second);
         removeFromImplementationMap(
-            &data_.singletons, i->second->singletons, i->second);
-        if (!i->second->name.isEmpty()) {
-            data_.namedImplementations.erase(i->second->name);
+            &data_.singletons, i->second->info->singletons, i->second);
+        if (!i->second->info->name.isEmpty()) {
+            data_.namedImplementations.erase(i->second->info->name);
         }
         data_.dynamicImplementations.erase(i);
         if (removeListener) {
@@ -1659,9 +1812,9 @@ void ServiceManager::removeImplementation(rtl::OUString name) {
     assert(i->second.get() != 0);
     //TODO: The below leaves data_ in an inconsistent state upon exceptions:
     removeFromImplementationMap(
-        &data_.services, i->second->services, i->second);
+        &data_.services, i->second->info->services, i->second);
     removeFromImplementationMap(
-        &data_.singletons, i->second->singletons, i->second);
+        &data_.singletons, i->second->info->singletons, i->second);
     for (DynamicImplementations::iterator j(
              data_.dynamicImplementations.begin());
          j != data_.dynamicImplementations.end(); ++j)
@@ -1694,7 +1847,7 @@ boost::shared_ptr< Implementation > ServiceManager::findServiceImplementation(
             assert(!i->second.empty());
             SAL_INFO_IF(
                 i->second.size() > 1, "cppuhelper",
-                "Arbitrarily chosing " << i->second[0]->name
+                "Arbitrarily chosing " << i->second[0]->info->name
                     << " among multiple implementations for " << i->first);
             impl = i->second[0];
         }
@@ -1705,82 +1858,124 @@ boost::shared_ptr< Implementation > 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) {
-        loadImplementation(impl.get());
+        css::uno::Reference< css::lang::XSingleComponentFactory > f1;
+        css::uno::Reference< css::lang::XSingleServiceFactory > f2;
+        loadImplementation(impl->info, &f1, &f2);
+        osl::MutexGuard g(rBHelper.rMutex);
+        if (!(isDisposed() || impl->loaded)) {
+            impl->loaded = true;
+            impl->factory1 = f1;
+            impl->factory2 = f2;
+        }
     }
     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,
+css::uno::Reference< css::uno::XInterface >
+FactoryWrapper::createInstanceWithContext(
+    css::uno::Reference< css::uno::XComponentContext > const & Context)
+    throw (css::uno::Exception, css::uno::RuntimeException)
+{
+    loadImplementation();
+    return factory1_.is()
+        ? factory1_->createInstanceWithContext(Context)
+        : factory2_->createInstance();
+}
+
+css::uno::Reference< css::uno::XInterface >
+FactoryWrapper::createInstanceWithArgumentsAndContext(
+    css::uno::Sequence< css::uno::Any > const & Arguments,
+    css::uno::Reference< css::uno::XComponentContext > const & Context)
+    throw (css::uno::Exception, css::uno::RuntimeException)
+{
+    loadImplementation();
+    return factory1_.is()
+        ? factory1_->createInstanceWithArgumentsAndContext(Arguments, Context)
+        : factory2_->createInstanceWithArguments(Arguments);
+}
+
+css::uno::Reference< css::uno::XInterface > FactoryWrapper::createInstance()
+    throw (css::uno::Exception, css::uno::RuntimeException)
+{
+    loadImplementation();
+    return factory1_.is()
+        ? factory1_->createInstanceWithContext(manager_->getContext())
+        : factory2_->createInstance();
+}
+
+css::uno::Reference< css::uno::XInterface >
+FactoryWrapper::createInstanceWithArguments(
+    css::uno::Sequence< css::uno::Any > const & Arguments)
+    throw (css::uno::Exception, css::uno::RuntimeException)
+{
+    loadImplementation();
+    return factory1_.is()
+        ? factory1_->createInstanceWithArgumentsAndContext(
+            Arguments, manager_->getContext())
+        : factory2_->createInstanceWithArguments(Arguments);
+}
+
+rtl::OUString FactoryWrapper::getImplementationName()
+    throw (css::uno::RuntimeException)
+{
+    return info_->name;
+}
+
+sal_Bool FactoryWrapper::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 > FactoryWrapper::getSupportedServiceNames()
+    throw (css::uno::RuntimeException)
+{
+    if (info_->services.size() > static_cast< sal_uInt32 >(SAL_MAX_INT32)) {
+        throw css::uno::RuntimeException(
+            "Implementation " + info_->name + " supports too many services",
             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")
+    css::uno::Sequence< rtl::OUString > names(
+        static_cast< sal_Int32 >(info_->services.size()));
+    sal_Int32 i = 0;
+    for (std::vector< rtl::OUString >::const_iterator j(
+             info_->services.begin());
+         j != info_->services.end(); ++j)
     {
-        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));
+        names[i++] = *j;
+    }
+    return names;
+}
+
+void FactoryWrapper::loadImplementation() {
+    {
+        osl::MutexGuard g(mutex_);
+        if (loaded_) {
+            return;
         }
     }
-    css::uno::Reference< css::lang::XSingleComponentFactory > f1(
-        f0, css::uno::UNO_QUERY);
+    css::uno::Reference< css::lang::XSingleComponentFactory > f1;
     css::uno::Reference< css::lang::XSingleServiceFactory > f2;
-    if (!f1.is()) {
-        f2 = css::uno::Reference< css::lang::XSingleServiceFactory >(
-            f0, css::uno::UNO_QUERY);
+    //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(info_, &f1, &f2);
+    if (!(f1.is() || f2.is())) {
+        throw css::uno::DeploymentException(
+            "Implementation " + info_->name + " does not provide a factory",
+            static_cast< cppu::OWeakObject * >(this));
     }
-    osl::MutexGuard g(rBHelper.rMutex);
-    if (!(isDisposed() || implementation->loaded)) {
-        implementation->loaded = true;
-        implementation->factory1 = f1;
-        implementation->factory2 = f2;
+    osl::MutexGuard g(mutex_);
+    if (!loaded_) {
+        loaded_ = true;
+        factory1_ = f1;
+        factory2_ = f2;
     }
 }
 
@@ -1818,12 +2013,12 @@ css::uno::Reference< css::uno::XComponentContext > bootstrapComponentContext(
         assert(i->second[0].get() != 0);
         SAL_INFO_IF(
             i->second.size() > 1, "cppuhelper",
-            "Arbitrarily chosing " << i->second[0]->name
+            "Arbitrarily chosing " << i->second[0]->info->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));
+                css::uno::makeAny(i->second[0]->info->name), true));
     }
     cppu::add_access_control_entries(&context_values, bootstrap);
     assert(!context_values.empty());


More information about the Libreoffice-commits mailing list