[Libreoffice-commits] core.git: Branch 'private/hcvcastro/preinit' - 8 commits - cppuhelper/source desktop/source include/cppuhelper smoketest/libtest.cxx vcl/source

Henry Castro hcastro at collabora.com
Sun Sep 13 09:01:41 PDT 2015


Rebased ref, commits from common ancestor:
commit bfe8e4c19643228cb4c87de23946f377166b7b8a
Author: Henry Castro <hcastro at collabora.com>
Date:   Mon Sep 7 20:27:40 2015 -0400

    cppuhelper: method 2, load implementations to invoke component factory
    
    In the preinit stage, method 2 is simplified, looping all registered
    services, and for each service load implementation is called.
    
    The disadvantages using this method, it cannot load the module with flag
    SAL_LOADMODULE_NOW set, to ensure all symbols are resolved. But we still
    can set the flag LD_BIND_NOW=1 in the parent process.
    
    Change-Id: Ieb7b90f4f43f980e15d66d490505147e166bf772

diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx
index 602fdfb..9e9aa8e 100644
--- a/cppuhelper/source/defaultbootstrap.cxx
+++ b/cppuhelper/source/defaultbootstrap.cxx
@@ -125,6 +125,6 @@ cppu::preInitBootstrap(css::uno::Reference< css::uno::XComponentContext > const
     // 1) defaultBootstrap_InitialComponentContext()
     // 2) comphelper::setProcessServiceFactory(xSFactory);
     // 3) InitVCL()
-    aService->loadImplementations();
+    aService->loadImplementations(xContext);
 }
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
index 8be70aa..aba6745 100644
--- a/cppuhelper/source/servicemanager.cxx
+++ b/cppuhelper/source/servicemanager.cxx
@@ -881,110 +881,28 @@ void cppuhelper::ServiceManager::loadImplementation(
     }
 }
 
-void cppuhelper::ServiceManager::loadImplementations()
+void cppuhelper::ServiceManager::loadImplementations(css::uno::Reference< css::uno::XComponentContext > const & context)
 {
-    rtl::OUString aUri;
     osl::MutexGuard g(rBHelper.rMutex);
-    css::uno::Environment aSourceEnv(css::uno::Environment::getCurrent());
 
     // loop all implementations
     for (Data::NamedImplementations::const_iterator iterator(
             data_.namedImplementations.begin());
             iterator != data_.namedImplementations.end(); ++iterator)
     {
-        try
-        {
-            // expand absolute URI implementation component library
-            aUri = cppu::bootstrap_expandUri(iterator->second->info->uri);
-        }
-        catch (css::lang::IllegalArgumentException& aError)
-        {
-            throw css::uno::DeploymentException(
-                "Cannot expand URI" + iterator->second->info->uri + ": " + aError.Message,
-                static_cast< cppu::OWeakObject * >(this));
-        }
-
         if (iterator->second->info->loader == "com.sun.star.loader.SharedLibrary" &&
             iterator->second->status != Data::Implementation::STATUS_LOADED)
         {
-            // load component library
-            osl::Module aModule(aUri, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL);
-            SAL_INFO("lok", "loaded component library " << aUri << ( aModule.is() ? " ok" : " no"));
-
-            if (aModule.is() &&
-                !iterator->second->info->environment.isEmpty())
+            SAL_INFO("lok", "loading component library " +iterator->second->info->uri);
+            boost::shared_ptr< cppuhelper::ServiceManager::Data::Implementation > impl = iterator->second;
+            try
             {
-                OUString aSymFactory;
-                oslGenericFunction fpFactory;
-                css::uno::Environment aTargetEnv;
-                css::uno::Reference<css::uno::XInterface> xFactory;
-
-                if(iterator->second->info->constructor.isEmpty())
-                {
-                    // expand full name component factory symbol
-                    if (iterator->second->info->prefix == "direct")
-                        aSymFactory = iterator->second->info->name.replace('.', '_') + "_" COMPONENT_GETFACTORY;
-                    else if (!iterator->second->info->prefix.isEmpty())
-                        aSymFactory = iterator->second->info->prefix + "_" COMPONENT_GETFACTORY;
-                    else
-                        aSymFactory = COMPONENT_GETFACTORY;
-
-                    // get function symbol component factory
-                    fpFactory = aModule.getFunctionSymbol(aSymFactory);
-                    if (fpFactory == 0)
-                    {
-                        throw css::loader::CannotActivateFactoryException(
-                            ("no factory symbol \"" + aSymFactory + "\" in component library :" + aUri),
-                            css::uno::Reference<css::uno::XInterface>());
-                    }
-
-                    aTargetEnv = cppuhelper::detail::getEnvironment(iterator->second->info->environment, iterator->second->info->name);
-                    component_getFactoryFunc fpComponentFactory = reinterpret_cast<component_getFactoryFunc>(fpFactory);
-
-                    if (aSourceEnv.get() == aTargetEnv.get())
-                    {
-                        // invoke function component factory
-                        OString aImpl(rtl::OUStringToOString(iterator->second->info->name, RTL_TEXTENCODING_ASCII_US));
-                        xFactory.set(css::uno::Reference<css::uno::XInterface>(static_cast<css::uno::XInterface *>(
-                            (*fpComponentFactory)(aImpl.getStr(), this, 0)), SAL_NO_ACQUIRE));
-                    }
-                }
-                else
-                {
-                    // get function symbol component factory
-                    fpFactory = aModule.getFunctionSymbol(iterator->second->info->constructor);
-                }
-
-                css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory;
-                css::uno::Reference<css::lang::XSingleServiceFactory> xSSFactory;
-
-                // query interface XSingleComponentFactory or XSingleServiceFactory
-                if (xFactory.is())
-                {
-                    xSCFactory.set(xFactory, css::uno::UNO_QUERY);
-                    if (!xSCFactory.is())
-                    {
-                        xSSFactory.set(xFactory, css::uno::UNO_QUERY);
-                        if (!xSSFactory.is())
-                        {
-                            throw css::uno::DeploymentException(
-                                ("Implementation " + iterator->second->info->name
-                                  + " does not provide a constructor or factory"),
-                                static_cast< cppu::OWeakObject * >(this));
-                        }
-                    }
-                }
-
-                if (!iterator->second->info->constructor.isEmpty() && fpFactory)
-                    iterator->second->constructor = reinterpret_cast<ImplementationConstructorFn *>(fpFactory);
-
-                iterator->second->factory1 = xSCFactory;
-                iterator->second->factory2 = xSSFactory;
-                iterator->second->status = Data::Implementation::STATUS_LOADED;
-
+                loadImplementation(context, impl);
+            }
+            catch (css::uno::RuntimeException & aError)
+            {
+                SAL_WARN("lok", aError.Message);
             }
-            // leak aModule
-            aModule.release();
         }
     }
 }
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx
index ddf85965f..571f857 100644
--- a/cppuhelper/source/servicemanager.hxx
+++ b/cppuhelper/source/servicemanager.hxx
@@ -203,7 +203,7 @@ public:
         css::uno::Reference< css::uno::XComponentContext > const & context,
         boost::shared_ptr< Data::Implementation > & implementation);
 
-    void loadImplementations();
+    void loadImplementations(css::uno::Reference< css::uno::XComponentContext > const & context);
 
 private:
     virtual ~ServiceManager() {}
commit 5e49de2277df600e6f6663a396e979cb91eebd0c
Author: Henry Castro <hcastro at collabora.com>
Date:   Sat Sep 12 12:11:43 2015 -0400

    vcl: desktop terminate, to dispose objects
    
    In the preinit stage, the Desktop terminate() method is never called
    when lo_startmain thread is disposing objects. This produces debug
    assertions and osl assertions.
    
    It is forced to call terminate() method, when a tiled rendering case is
    active then it has a clean disposing objects process.
    
    However DBGGUI_DEINIT_SOLARMUTEXCHECK() check is moved at the end to
    prevent debug assertions solar mutex complains.
    
    Change-Id: I4a9b6398296d9150ab748a8d48868a08e7232909

diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index fcc7b8c..ce95437 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -28,6 +28,7 @@
 #include "tools/resmgr.hxx"
 
 #include "comphelper/processfactory.hxx"
+#include "comphelper/lok.hxx"
 
 #include "unotools/syslocaleoptions.hxx"
 #include "vcl/svapp.hxx"
@@ -445,8 +446,6 @@ void DeInitVCL()
     }
     pSVData->mpDefaultWin.disposeAndClear();
 
-    DBGGUI_DEINIT_SOLARMUTEXCHECK();
-
     if ( pSVData->mpUnoWrapper )
     {
         try
@@ -454,6 +453,12 @@ void DeInitVCL()
             uno::Reference<frame::XDesktop2> const xDesktop = frame::Desktop::create(
                     comphelper::getProcessComponentContext() );
             xDesktop->addEventListener(new VCLUnoWrapperDeleter());
+
+            if (comphelper::LibreOfficeKit::isActive())
+            {
+                SAL_WARN_IF(!xDesktop.is(), "desktop.app", "No Desktop interface");
+                xDesktop->terminate();
+            }
         }
         catch (uno::Exception const&)
         {
@@ -567,6 +572,8 @@ void DeInitVCL()
     }
 
     EmbeddedFontsHelper::clearTemporaryFontFiles();
+
+    DBGGUI_DEINIT_SOLARMUTEXCHECK();
 }
 
 // only one call is allowed
commit 459493b467fb4976baaf27906e6f725d3fca21c2
Author: Henry Castro <hcastro at collabora.com>
Date:   Mon Sep 7 17:43:04 2015 -0400

    vcl: assign NULL after deleting
    
    In the preinit stage, the VCL initialization is done by the parent process
    and when the lo_startmain thread de-initialize the VCL, some services are
    disposed early, and it causes segmentation violation.
    
    So it is ensured that pointers to service objetcs is set NULL after the
    delete.
    
    Change-Id: I65ecfc2d2694a981ec2986988efabdfd28d0cce4

diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx
index 14cf94d..94c23db 100644
--- a/vcl/source/app/svdata.cxx
+++ b/vcl/source/app/svdata.cxx
@@ -102,10 +102,10 @@ void ImplDeInitSVData()
 
     // delete global instance data
     if( pSVData->mpSettingsConfigItem )
-        delete pSVData->mpSettingsConfigItem;
+        delete pSVData->mpSettingsConfigItem, pSVData->mpSettingsConfigItem = NULL;
 
     if( pSVData->mpDockingManager )
-        delete pSVData->mpDockingManager;
+        delete pSVData->mpDockingManager, pSVData->mpDockingManager = NULL;
 
     if( pSVData->maCtrlData.mpFieldUnitStrings )
         delete pSVData->maCtrlData.mpFieldUnitStrings, pSVData->maCtrlData.mpFieldUnitStrings = NULL;
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index df187484..fcc7b8c 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -390,7 +390,7 @@ void DeInitVCL()
         delete pSVData->mpSettingsConfigItem, pSVData->mpSettingsConfigItem = NULL;
 
     if ( pSVData->maAppData.mpIdleMgr )
-        delete pSVData->maAppData.mpIdleMgr;
+        delete pSVData->maAppData.mpIdleMgr, pSVData->maAppData.mpIdleMgr = NULL;
     Scheduler::ImplDeInitScheduler();
 
     if ( pSVData->maWinData.mpMsgBoxImgList )
@@ -554,7 +554,11 @@ void DeInitVCL()
     pSVData->mpSalTimer = NULL;
 
     // Deinit Sal
-    DestroySalInstance( pSVData->mpDefInst );
+    if (pSVData->mpDefInst)
+    {
+        DestroySalInstance( pSVData->mpDefInst );
+        pSVData->mpDefInst = NULL;
+    }
 
     if( pOwnSvApp )
     {
commit 85ba488463321162790894489251b1e269ee5651
Author: Henry Castro <hcastro at collabora.com>
Date:   Mon Sep 7 17:33:09 2015 -0400

    vcl: add isInitVCL, to not initialize twice
    
    In the preinit stage, the VCL is initialized in the parent process
    and when the lo_startmain thread is started, the thread initialize
    VCL again.
    
    It is not necessary to initialize twice.
    
    Change-Id: I819cf0125afe7760c3f4d91c420d36a3a383902c

diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index b24714d..df187484 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -91,6 +91,8 @@
 
 using namespace ::com::sun::star;
 
+bool isInitVCL();
+
 oslSignalAction SAL_CALL VCLExceptionSignal_impl( void* /*pData*/, oslSignalInfo* pInfo)
 {
     static bool bIn = false;
@@ -160,7 +162,7 @@ int ImplSVMain()
 
     int nReturn = EXIT_FAILURE;
 
-    bool bInit = InitVCL();
+    bool bInit = (!isInitVCL() ? InitVCL() : true);
 
     if( bInit )
     {
@@ -243,6 +245,14 @@ uno::Any SAL_CALL DesktopEnvironmentContext::getValueByName( const OUString& Nam
     return retVal;
 }
 
+bool isInitVCL()
+{
+    ImplSVData* pSVData = ImplGetSVData();
+    return  pExceptionHandler != NULL &&
+            pSVData->mpApp != NULL &&
+            pSVData->mpDefInst != NULL;
+}
+
 bool InitVCL()
 {
     if( pExceptionHandler != NULL )
commit 49a21351f9de5903cbabd9a08e3343e9943b278e
Author: Henry Castro <hcastro at collabora.com>
Date:   Mon Sep 7 17:21:38 2015 -0400

    desktop: add InitVCL to lo_initialize
    
    In the preinit stage, VCL initialization is required before call
    preInitBootstrap that load implementations.
    
    However, InitVCL acquire the Solar Mutex, and it is released because
    it will produce deadlock between the parent process and lo_startmain
    thread.
    
    On the other hand, lo_startmain thread acquires the Solar Mutex, if
    not debug assertion complains.
    
    Change-Id: Ib5d4b5788441b92a30f58a129441ffeba076c181

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 9e1f1b4..98a0548 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -894,7 +894,7 @@ static void aBasicErrorFunc(const OUString& rError, const OUString& rAction)
     fprintf(stderr, "Unexpected basic error dialog '%s'\n", aBuffer.getStr());
 }
 
-static bool initialize_uno(const OUString& aAppProgramURL, bool bPreInit)
+static bool initialize_uno(const OUString& aAppProgramURL)
 {
 #ifdef IOS
     // For iOS we already hardocde the inifile as "rc" in the .app directory.
@@ -903,14 +903,8 @@ static bool initialize_uno(const OUString& aAppProgramURL, bool bPreInit)
     rtl::Bootstrap::setIniFilename(aAppProgramURL + "/" SAL_CONFIGFILE("soffice"));
 #endif
 
-    if (bPreInit)
-    {
-        // pre-load all component libraries.
-        cppu::preInitBootstrap();
-        return true;
-    }
-
     xContext = cppu::defaultBootstrap_InitialComponentContext();
+
     if (!xContext.is())
     {
         gImpl->maLastExceptionMsg = "XComponentContext could not be created";
@@ -947,6 +941,9 @@ static bool initialize_uno(const OUString& aAppProgramURL, bool bPreInit)
 
 static void lo_startmain(void*)
 {
+    if (GetpApp())
+        Application::GetSolarMutex().tryToAcquire();
+
     soffice_main();
 }
 
@@ -973,11 +970,6 @@ static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit:
     }
 }
 
-/// pre-load and parse all filter XML
-static void forceLoadFilterXML()
-{
-}
-
 static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char* pUserProfilePath)
 {
     enum {
@@ -1034,12 +1026,9 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
         {
             SAL_INFO("lok", "Attempting to initalize UNO");
 
-            if (!initialize_uno(aAppURL, (eStage == PRE_INIT)))
+            if (!initialize_uno(aAppURL))
                 return false;
 
-            if (eStage != PRE_INIT)
-                force_c_locale();
-
             // Force headless -- this is only for bitmap rendering.
             rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp");
 
@@ -1049,11 +1038,17 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
             desktop::Desktop::GetCommandLineArgs().setHeadless();
 
             Application::EnableHeadlessMode(true);
-        }
 
-        if (eStage == PRE_INIT)
-        {
-            forceLoadFilterXML();
+            if (eStage == PRE_INIT)
+            {
+                InitVCL();
+                // pre-load all component libraries.
+                cppu::preInitBootstrap(xContext);
+                // Release Solar Mutex, lo_startmain thread should acquire it.
+                Application::ReleaseSolarMutex();
+            }
+
+            force_c_locale();
         }
 
         // This is horrible crack. I really would want to go back to simply just call
commit 0209190e09c12b76db8cbcba2d5649781486056e
Author: Henry Castro <hcastro at collabora.com>
Date:   Mon Sep 7 17:17:22 2015 -0400

    cppuhelper: add preInitBootstrap symbol
    
    In the preinit stage, the preInitBootstrap is called to load
    implementations for each service registered by the service manager.
    
    All service requests are: initial Component Context and the process
    service factory is set.
    
    However, some services require that VCL is properly initialized.
    
    Change-Id: Ib116e3da172b860f2df4d672f6181b5de0b7e6b2

diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx
index b135b2c..602fdfb 100644
--- a/cppuhelper/source/defaultbootstrap.cxx
+++ b/cppuhelper/source/defaultbootstrap.cxx
@@ -42,19 +42,6 @@ rtl::OUString getBootstrapVariable(
     }
     return v;
 }
-
-void default_preInitBootstrap(rtl::OUString const & aUri)
-{
-    rtl::Bootstrap bsUri(aUri);
-    if (bsUri.getHandle() == 0)
-        throw css::uno::DeploymentException("Cannot open uno ini " + aUri);
-
-    // create the service manager
-    rtl::Reference< cppuhelper::ServiceManager > aManager(new cppuhelper::ServiceManager);
-    // read rdb files
-    aManager->init(getBootstrapVariable(bsUri, "UNO_SERVICES"));
-    aManager->loadImplementations();
-}
 }
 
 css::uno::Reference< css::uno::XComponentContext >
@@ -120,8 +107,24 @@ cppu::defaultBootstrap_InitialComponentContext()
 }
 
 void
-cppu::preInitBootstrap()
+cppu::preInitBootstrap(css::uno::Reference< css::uno::XComponentContext > const & xContext)
 {
-    default_preInitBootstrap(getUnoIniUri());
+    if (!xContext.is())
+        throw css::uno::DeploymentException("preInit: XComponentContext is not created");
+
+    css::uno::Reference< css::uno::XInterface > xService;
+    xContext->getValueByName("/singletons/com.sun.star.lang.theServiceManager") >>= xService;
+    if (!xService.is())
+        throw css::uno::DeploymentException("preInit: XMultiComponentFactory is not created");
+
+    rtl::Reference<cppuhelper::ServiceManager> aService(reinterpret_cast<cppuhelper::ServiceManager*>(xService.get()));
+
+    // pre-requisites:
+    // In order to load implementations and invoke
+    // component factory it is required:
+    // 1) defaultBootstrap_InitialComponentContext()
+    // 2) comphelper::setProcessServiceFactory(xSFactory);
+    // 3) InitVCL()
+    aService->loadImplementations();
 }
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/gcc3.map b/cppuhelper/source/gcc3.map
index 3d7a5c6..6344bc2 100644
--- a/cppuhelper/source/gcc3.map
+++ b/cppuhelper/source/gcc3.map
@@ -423,7 +423,7 @@ global:
         # enableChangeListenerNotification
         _ZN4cppu19OPropertySetHelper232enableChangeListenerNotificationEh;
         _ZThn*_N4cppu19OPropertySetHelper232enableChangeListenerNotificationEh;
-        _ZN4cppu16preInitBootstrapEv;
+        _ZN4cppu16preInitBootstrapERKN3com3sun4star3uno9ReferenceINS3_17XComponentContextEEE;
 } UDK_3.7;
 
 LIBO_UDK_3.9 { # LibO 3.7
diff --git a/include/cppuhelper/bootstrap.hxx b/include/cppuhelper/bootstrap.hxx
index debddcf..1530f0a 100644
--- a/include/cppuhelper/bootstrap.hxx
+++ b/include/cppuhelper/bootstrap.hxx
@@ -57,6 +57,16 @@ CPPUHELPER_DLLPUBLIC sal_Bool SAL_CALL installTypeDescriptionManager(
 CPPUHELPER_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > SAL_CALL
 defaultBootstrap_InitialComponentContext();
 
+/** preload component shared library with service manager upon
+    information from bootstrap variables.
+
+    This function tries to find its parameters via these bootstrap variables:
+
+      - UNO_SERVICES      -- a space separated list of file urls of service rdbs
+
+*/
+CPPUHELPER_DLLPUBLIC void SAL_CALL
+preInitBootstrap(css::uno::Reference< css::uno::XComponentContext > const & xContext);
 
 /** Bootstraps an initial component context with service manager upon
     information from an ini file.
@@ -72,6 +82,7 @@ defaultBootstrap_InitialComponentContext();
     @param iniFile ini filename to get bootstrap variables
     @return component context
 */
+
 CPPUHELPER_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > SAL_CALL
 defaultBootstrap_InitialComponentContext(const ::rtl::OUString & iniFile);
 
commit 0d94313f9cc4437f76f833dd10417593338dc70e
Author: Henry Castro <hcastro at collabora.com>
Date:   Mon Sep 7 17:11:45 2015 -0400

    cppuhelper: method 1, load implementations to invoke component factory
    
    In the preinit stage, for each library that is registered by the service
    manager, is loaded with the flag SAL_LOADMODULE_NOW and the component
    factory is invoked to initialize its data.
    
    Change-Id: Ie6f6d769b611c8440ddab802545e6bdc482d1476

diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
index ffed6ba..8be70aa 100644
--- a/cppuhelper/source/servicemanager.cxx
+++ b/cppuhelper/source/servicemanager.cxx
@@ -35,6 +35,8 @@
 #include <cppuhelper/implbase1.hxx>
 #include <cppuhelper/implbase3.hxx>
 #include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/shlib.hxx>
 #include <osl/file.hxx>
 #include <rtl/ref.hxx>
 #include <rtl/uri.hxx>
@@ -883,13 +885,16 @@ void cppuhelper::ServiceManager::loadImplementations()
 {
     rtl::OUString aUri;
     osl::MutexGuard g(rBHelper.rMutex);
+    css::uno::Environment aSourceEnv(css::uno::Environment::getCurrent());
 
+    // loop all implementations
     for (Data::NamedImplementations::const_iterator iterator(
             data_.namedImplementations.begin());
             iterator != data_.namedImplementations.end(); ++iterator)
     {
         try
         {
+            // expand absolute URI implementation component library
             aUri = cppu::bootstrap_expandUri(iterator->second->info->uri);
         }
         catch (css::lang::IllegalArgumentException& aError)
@@ -902,13 +907,84 @@ void cppuhelper::ServiceManager::loadImplementations()
         if (iterator->second->info->loader == "com.sun.star.loader.SharedLibrary" &&
             iterator->second->status != Data::Implementation::STATUS_LOADED)
         {
-            oslModule aModule = osl_loadModule( aUri.pData, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL );
-            SAL_INFO("lok", "loaded component library " << aUri << ( aModule ? " ok" : " no"));
+            // load component library
+            osl::Module aModule(aUri, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL);
+            SAL_INFO("lok", "loaded component library " << aUri << ( aModule.is() ? " ok" : " no"));
 
-            // leak aModule
-            // osl_unloadModule(aModule);
-            if ( aModule )
+            if (aModule.is() &&
+                !iterator->second->info->environment.isEmpty())
+            {
+                OUString aSymFactory;
+                oslGenericFunction fpFactory;
+                css::uno::Environment aTargetEnv;
+                css::uno::Reference<css::uno::XInterface> xFactory;
+
+                if(iterator->second->info->constructor.isEmpty())
+                {
+                    // expand full name component factory symbol
+                    if (iterator->second->info->prefix == "direct")
+                        aSymFactory = iterator->second->info->name.replace('.', '_') + "_" COMPONENT_GETFACTORY;
+                    else if (!iterator->second->info->prefix.isEmpty())
+                        aSymFactory = iterator->second->info->prefix + "_" COMPONENT_GETFACTORY;
+                    else
+                        aSymFactory = COMPONENT_GETFACTORY;
+
+                    // get function symbol component factory
+                    fpFactory = aModule.getFunctionSymbol(aSymFactory);
+                    if (fpFactory == 0)
+                    {
+                        throw css::loader::CannotActivateFactoryException(
+                            ("no factory symbol \"" + aSymFactory + "\" in component library :" + aUri),
+                            css::uno::Reference<css::uno::XInterface>());
+                    }
+
+                    aTargetEnv = cppuhelper::detail::getEnvironment(iterator->second->info->environment, iterator->second->info->name);
+                    component_getFactoryFunc fpComponentFactory = reinterpret_cast<component_getFactoryFunc>(fpFactory);
+
+                    if (aSourceEnv.get() == aTargetEnv.get())
+                    {
+                        // invoke function component factory
+                        OString aImpl(rtl::OUStringToOString(iterator->second->info->name, RTL_TEXTENCODING_ASCII_US));
+                        xFactory.set(css::uno::Reference<css::uno::XInterface>(static_cast<css::uno::XInterface *>(
+                            (*fpComponentFactory)(aImpl.getStr(), this, 0)), SAL_NO_ACQUIRE));
+                    }
+                }
+                else
+                {
+                    // get function symbol component factory
+                    fpFactory = aModule.getFunctionSymbol(iterator->second->info->constructor);
+                }
+
+                css::uno::Reference<css::lang::XSingleComponentFactory> xSCFactory;
+                css::uno::Reference<css::lang::XSingleServiceFactory> xSSFactory;
+
+                // query interface XSingleComponentFactory or XSingleServiceFactory
+                if (xFactory.is())
+                {
+                    xSCFactory.set(xFactory, css::uno::UNO_QUERY);
+                    if (!xSCFactory.is())
+                    {
+                        xSSFactory.set(xFactory, css::uno::UNO_QUERY);
+                        if (!xSSFactory.is())
+                        {
+                            throw css::uno::DeploymentException(
+                                ("Implementation " + iterator->second->info->name
+                                  + " does not provide a constructor or factory"),
+                                static_cast< cppu::OWeakObject * >(this));
+                        }
+                    }
+                }
+
+                if (!iterator->second->info->constructor.isEmpty() && fpFactory)
+                    iterator->second->constructor = reinterpret_cast<ImplementationConstructorFn *>(fpFactory);
+
+                iterator->second->factory1 = xSCFactory;
+                iterator->second->factory2 = xSSFactory;
                 iterator->second->status = Data::Implementation::STATUS_LOADED;
+
+            }
+            // leak aModule
+            aModule.release();
         }
     }
 }
commit 6afd2c0369dff5c976a191acb765f4a3a17ac699
Author: Henry Castro <hcastro at collabora.com>
Date:   Mon Sep 7 17:04:37 2015 -0400

    smoketest: add lok_preinit to libtest
    
    In the preinit stage, it is added the symbol lok_preinit to compute
    preInit time, or trace opening files.
    
    Change-Id: Ia4d9b27169d2f298fb90d83dd9f4fbf059fd3237

diff --git a/smoketest/libtest.cxx b/smoketest/libtest.cxx
index 60ee19e..b155525 100644
--- a/smoketest/libtest.cxx
+++ b/smoketest/libtest.cxx
@@ -16,7 +16,9 @@
 #include <LibreOfficeKit/LibreOfficeKitInit.h>
 #include <LibreOfficeKit/LibreOfficeKit.hxx>
 
+#define LIB_SOFFICEAPP  "lib" "sofficeapp" ".so"
 
+typedef int (LokHookPreInit)  ( const char *install_path, const char *user_profile_path );
 
 #ifdef _WIN32
 //#include <Windows.h>   // come from LibreOfficeKitInit.h
@@ -68,6 +70,30 @@ static int help()
     return 1;
 }
 
+bool lok_cpp_preInit(const char *pLOInstall)
+{
+    char pOfficePath[strlen(pLOInstall) + strlen(LIB_SOFFICEAPP)];
+    void* pHandle;
+    LokHookPreInit* pSymPreInit;
+
+    sprintf(pOfficePath, "%s/%s", pLOInstall, LIB_SOFFICEAPP);
+    pHandle = dlopen(pOfficePath, RTLD_GLOBAL | RTLD_NOW);
+    if (!pHandle)
+    {
+        fprintf(stderr, "Failed to load library :%s\n", pOfficePath);
+        return false;
+    }
+
+    pSymPreInit = (LokHookPreInit *)dlsym(pHandle, "lok_preinit");
+    if (!pSymPreInit)
+    {
+        fprintf(stderr, "Failed to find lok_preinit hook in library");
+        return false;
+    }
+
+    return pSymPreInit(pLOInstall, NULL) == 0;
+}
+
 int main (int argc, char **argv)
 {
     long start, end;
@@ -82,30 +108,17 @@ int main (int argc, char **argv)
     if( !IsAbsolutePath(argv[1]) )
         return 1;
 
-    // coverity[tainted_string] - build time test tool
-    char *install_path = argv[1];
-
-    if( argc > 4 )
+    if( !lok_cpp_preInit( argv[1] ) )
     {
-        fprintf( stderr, "testing preinit\n");
-        char *imp_lib;
-        void *dlhandle;
-        dlhandle = lok_dlopen( install_path, &imp_lib );
-        if( !dlhandle )
-        {
-            fprintf( stderr, "Failed to link '%s'\n", lok_dlerror() );
-            return -1;
-        }
-        LokHookPreInit *preinit = (LokHookPreInit *) lok_dlsym( dlhandle, "lok_preinit" );
-        if( !preinit )
-        {
-            fprintf( stderr, "Failed to find pre-init symbol: %s\n", lok_dlerror() );
-            return -1;
-        }
-        preinit( install_path, NULL );
+        fprintf( stderr, "Failed to pre-initialize\n" );
+        return -1;
     }
+    end = getTimeMS();
+    fprintf( stderr, "preInit time: %ld ms\n", (end-start) );
+    start = end;
 
-    Office *pOffice = lok_cpp_init( install_path );
+    // coverity[tainted_string] - build time test tool
+    Office *pOffice = lok_cpp_init( argv[1] );
     if( !pOffice )
     {
         fprintf( stderr, "Failed to initialize\n" );


More information about the Libreoffice-commits mailing list