[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.0' - 9 commits - cppuhelper/source desktop/Library_sofficeapp.mk desktop/source include/cppuhelper smoketest/libtest.cxx vcl/headless vcl/source

Michael Meeks michael.meeks at collabora.com
Mon Mar 21 06:25:28 UTC 2016


 cppuhelper/source/defaultbootstrap.cxx |   22 ++++++
 cppuhelper/source/gcc3.map             |    1 
 cppuhelper/source/servicemanager.cxx   |  111 ++++++++++++++++++++++++++++++++
 cppuhelper/source/servicemanager.hxx   |    2 
 desktop/Library_sofficeapp.mk          |    1 
 desktop/source/lib/init.cxx            |  112 +++++++++++++++++++++++----------
 include/cppuhelper/bootstrap.hxx       |   14 ++++
 smoketest/libtest.cxx                  |   24 ++++++-
 vcl/headless/svpframe.cxx              |    6 +
 vcl/source/app/svdata.cxx              |    4 -
 vcl/source/app/svmain.cxx              |   31 +++++++--
 vcl/source/window/window.cxx           |    4 +
 12 files changed, 292 insertions(+), 40 deletions(-)

New commits:
commit 55c467f23c00805e89ba72f941ca08e575bd7d43
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Fri Jan 29 15:31:58 2016 +0100

    headless: don't let windows become really visible to avoid paints.
    
    Paint at the wrong time has a habit of allocating over-large
    OutputDevice's for the drawing layer; saves 7Mb of heap for a
    dummy tilebench document.
    
    Change-Id: Ie06df705a55faadea2b06fd24b904d95ae64fd83
    (cherry picked from commit 5f1529cc95dcebf7066765f525d1e61776bfecda)

diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index d8c7846..1e4e875 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -1349,6 +1349,10 @@ SalGraphics* Window::ImplGetFrameGraphics() const
 
 void Window::ImplSetReallyVisible()
 {
+    // For now, no window is really visible in headless mode.
+    if( Application::IsHeadlessModeEnabled() )
+        return;
+
     // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between
     // ImplCallInitShow() and ImplSetReallyVisible() when called from Show()
     // mbReallyShown is a useful indicator
commit 4e195870ec16086ef31a51f65af0d7cbfeea723d
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Fri Jan 29 15:11:48 2016 +0100

    headless: for now don't allocate big cairo surfaces for invisible frames.
    
    This was ~10Mb of RAM for a hello-world.odt under tile-bench.
    
    Change-Id: Ie0787676be754ac81eb8ec036c9757a1bb2f2220
    (cherry picked from commit edaccf928c4e4e90a024e766aecd07181e29fd97)

diff --git a/vcl/headless/svpframe.cxx b/vcl/headless/svpframe.cxx
index e1218d7..56e9dd9 100644
--- a/vcl/headless/svpframe.cxx
+++ b/vcl/headless/svpframe.cxx
@@ -292,10 +292,16 @@ void SvpSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_u
             aFrameSize.setX( 1 );
         if( aFrameSize.getY() == 0 )
             aFrameSize.setY( 1 );
+
+        // Creating backing surfaces for invisible windows costs a big chunk of RAM.
+        if (Application::IsHeadlessModeEnabled())
+             aFrameSize = B2IVector( 1, 1 );
+
         sal_Int32 nStride = basebmp::getBitmapDeviceStrideForWidth(m_nScanlineFormat, aFrameSize.getX());
         m_aFrame = createBitmapDevice( aFrameSize, m_bTopDown, m_nScanlineFormat, nStride );
         if (m_bDamageTracking)
             m_aFrame->setDamageTracker(
+
                 basebmp::IBitmapDeviceDamageTrackerSharedPtr( new DamageTracker ) );
         // update device in existing graphics
         for( std::list< SvpSalGraphics* >::iterator it = m_aGraphics.begin();
commit df63131bfa652328f5b46bd638eb6f88deeeadf6
Author: Henry Castro <hcastro at collabora.com>
Date:   Mon Sep 7 17:21:38 2015 -0400

    preInitBootstrap call takes context
    
    Change-Id: I85b951f7d28d3d8af40b7d5f86b310021a079428
    (cherry picked from commit 1c565696231ae5296a47bbb9df78d80d2da031f4)

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index b6d8d05..a251adc 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -1944,7 +1944,7 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
             {
                 InitVCL();
                 // pre-load all component libraries.
-                cppu::preInitBootstrap();
+                cppu::preInitBootstrap(xContext);
                 // Release Solar Mutex, lo_startmain thread should acquire it.
                 Application::ReleaseSolarMutex();
             }
commit 58c4cd90d34aab5eb13380ef05d67ea7d2aaa225
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
    (cherry picked from commit ba29b6ddf4c079a93a8484e95aa42daf2b54a54b)

diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index 45b81a5..1182598 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 48eac22cce93c08d13022a7215b9549379453695
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
    (cherry picked from commit fca0980ec866279cc40ed1233bbddb2e4abe2fae)

diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx
index 860c206..0352290 100644
--- a/vcl/source/app/svdata.cxx
+++ b/vcl/source/app/svdata.cxx
@@ -104,10 +104,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 bdea938..45b81a5 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 19349554e77a23c0cb551b886f51e854ca174df0
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
    (cherry picked from commit f0f7eb475ba402ceafa1d6f1956e7dfe7779615d)

diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index 72881a6..bdea938 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 267aa137bc89fd48aaae4cd90eff8bca52228fd2
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
    (cherry picked from commit 78df8373b6442ee3d3b09101988817cf621c189b)

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 94fa0a5..9481720 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 194f58dc19743e4f21789e09ff8220ce3ce68383
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
    (cherry picked from commit 0e008a27e7f4e9b08a7b2bbd33702df336f1bca4)

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 8e824a59965906077f1d1c39c5afa73b9fc4d650
Author: Ashod Nakashian <ashod.nakashian at collabora.co.uk>
Date:   Thu Jan 28 18:31:03 2016 -0500

    Restoring preinit
    
    Change-Id: I65341c57d00308d246ec90deab8050b2c4bb3e61
    (cherry picked from commit 62a2d525a7db09c7223a21907e1a0f4989398c15)

diff --git a/cppuhelper/source/defaultbootstrap.cxx b/cppuhelper/source/defaultbootstrap.cxx
index 1fbbf8f..b135b2c 100644
--- a/cppuhelper/source/defaultbootstrap.cxx
+++ b/cppuhelper/source/defaultbootstrap.cxx
@@ -43,6 +43,18 @@ 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 >
@@ -107,4 +119,9 @@ cppu::defaultBootstrap_InitialComponentContext()
     return defaultBootstrap_InitialComponentContext(getUnoIniUri());
 }
 
+void
+cppu::preInitBootstrap()
+{
+    default_preInitBootstrap(getUnoIniUri());
+}
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cppuhelper/source/gcc3.map b/cppuhelper/source/gcc3.map
index 12c29834a..3d7a5c6 100644
--- a/cppuhelper/source/gcc3.map
+++ b/cppuhelper/source/gcc3.map
@@ -423,6 +423,7 @@ global:
         # enableChangeListenerNotification
         _ZN4cppu19OPropertySetHelper232enableChangeListenerNotificationEh;
         _ZThn*_N4cppu19OPropertySetHelper232enableChangeListenerNotificationEh;
+        _ZN4cppu16preInitBootstrapEv;
 } UDK_3.7;
 
 LIBO_UDK_3.9 { # LibO 3.7
diff --git a/cppuhelper/source/servicemanager.cxx b/cppuhelper/source/servicemanager.cxx
index 2140a2f..ffed6ba 100644
--- a/cppuhelper/source/servicemanager.cxx
+++ b/cppuhelper/source/servicemanager.cxx
@@ -42,6 +42,7 @@
 #include <rtl/strbuf.hxx>
 #include <sal/log.hxx>
 #include <uno/environment.hxx>
+#include <osl/module.hxx>
 
 #include "loadsharedlibcomponentfactory.hxx"
 
@@ -878,6 +879,40 @@ void cppuhelper::ServiceManager::loadImplementation(
     }
 }
 
+void cppuhelper::ServiceManager::loadImplementations()
+{
+    rtl::OUString aUri;
+    osl::MutexGuard g(rBHelper.rMutex);
+
+    for (Data::NamedImplementations::const_iterator iterator(
+            data_.namedImplementations.begin());
+            iterator != data_.namedImplementations.end(); ++iterator)
+    {
+        try
+        {
+            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)
+        {
+            oslModule aModule = osl_loadModule( aUri.pData, SAL_LOADMODULE_NOW | SAL_LOADMODULE_GLOBAL );
+            SAL_INFO("lok", "loaded component library " << aUri << ( aModule ? " ok" : " no"));
+
+            // leak aModule
+            // osl_unloadModule(aModule);
+            if ( aModule )
+                iterator->second->status = Data::Implementation::STATUS_LOADED;
+        }
+    }
+}
+
 void cppuhelper::ServiceManager::disposing() {
     std::vector< css::uno::Reference<css::lang::XComponent> > sngls;
     std::vector< css::uno::Reference< css::lang::XComponent > > comps;
diff --git a/cppuhelper/source/servicemanager.hxx b/cppuhelper/source/servicemanager.hxx
index 903084b..ddf85965f 100644
--- a/cppuhelper/source/servicemanager.hxx
+++ b/cppuhelper/source/servicemanager.hxx
@@ -203,6 +203,8 @@ public:
         css::uno::Reference< css::uno::XComponentContext > const & context,
         boost::shared_ptr< Data::Implementation > & implementation);
 
+    void loadImplementations();
+
 private:
     virtual ~ServiceManager() {}
 
diff --git a/desktop/Library_sofficeapp.mk b/desktop/Library_sofficeapp.mk
index ed5057b..28d83f8 100644
--- a/desktop/Library_sofficeapp.mk
+++ b/desktop/Library_sofficeapp.mk
@@ -59,6 +59,7 @@ $(eval $(call gb_Library_use_libraries,sofficeapp,\
     ucbhelper \
     utl \
     vcl \
+    xmlreader \
 	$(gb_UWINAPI) \
 ))
 
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index a40285b..b6d8d05 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -53,6 +53,8 @@
 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
 #include <com/sun/star/ucb/XContentProvider.hpp>
 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
 #include <com/sun/star/util/URLTransformer.hpp>
 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
 
@@ -1797,6 +1799,7 @@ static bool initialize_uno(const OUString& aAppProgramURL)
 #endif
 
     xContext = cppu::defaultBootstrap_InitialComponentContext();
+
     if (!xContext.is())
     {
         gImpl->maLastExceptionMsg = "XComponentContext could not be created";
@@ -1835,6 +1838,9 @@ static void lo_startmain(void*)
 {
     osl_setThreadName("lo_startmain");
 
+    if (GetpApp())
+        Application::GetSolarMutex().tryToAcquire();
+
     soffice_main();
 }
 
@@ -1863,19 +1869,38 @@ static void lo_status_indicator_callback(void *data, comphelper::LibreOfficeKit:
 
 static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char* pUserProfilePath)
 {
+    enum {
+        PRE_INIT,     // setup shared data in master process
+        SECOND_INIT,  // complete init. after fork
+        FULL_INIT     // do a standard complete init.
+    } eStage;
+
+    // Did we do a pre-initialize
+    static bool bPreInited = false;
+
+    // What stage are we at ?
+    if (pThis == NULL)
+        eStage = PRE_INIT;
+    else if (bPreInited)
+        eStage = SECOND_INIT;
+    else
+        eStage = FULL_INIT;
+
     LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis);
 
     if (bInitialized)
         return 1;
 
-    comphelper::LibreOfficeKit::setActive();
+    if (eStage != SECOND_INIT)
+        comphelper::LibreOfficeKit::setActive();
 
     static bool bViewCallback = getenv("LOK_VIEW_CALLBACK");
     comphelper::LibreOfficeKit::setViewCallback(bViewCallback);
 
-    comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib);
+    if (eStage != PRE_INIT)
+        comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib);
 
-    if (pUserProfilePath)
+    if (eStage != SECOND_INIT && pUserProfilePath)
         rtl::Bootstrap::set(OUString("UserInstallation"), OUString(pUserProfilePath, strlen(pUserProfilePath), RTL_TEXTENCODING_UTF8));
 
     OUString aAppPath;
@@ -1898,22 +1923,34 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
 
     try
     {
-        SAL_INFO("lok", "Attempting to initalize UNO");
-        if (!initialize_uno(aAppURL))
+        if (eStage != SECOND_INIT)
         {
-            return false;
-        }
-        force_c_locale();
+            SAL_INFO("lok", "Attempting to initalize UNO");
+
+            if (!initialize_uno(aAppURL))
+                return false;
+
+            // Force headless -- this is only for bitmap rendering.
+            rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp");
+
+            // We specifically need to make sure we have the "headless"
+            // command arg set (various code specifically checks via
+            // CommandLineArgs):
+            desktop::Desktop::GetCommandLineArgs().setHeadless();
 
-        // Force headless -- this is only for bitmap rendering.
-        rtl::Bootstrap::set("SAL_USE_VCLPLUGIN", "svp");
+            Application::EnableHeadlessMode(true);
 
-        // We specifically need to make sure we have the "headless"
-        // command arg set (various code specifically checks via
-        // CommandLineArgs):
-        desktop::Desktop::GetCommandLineArgs().setHeadless();
+            if (eStage == PRE_INIT)
+            {
+                InitVCL();
+                // pre-load all component libraries.
+                cppu::preInitBootstrap();
+                // Release Solar Mutex, lo_startmain thread should acquire it.
+                Application::ReleaseSolarMutex();
+            }
 
-        Application::EnableHeadlessMode(true);
+            force_c_locale();
+        }
 
         // This is horrible crack. I really would want to go back to simply just call
         // InitVCL() here. The OfficeIPCThread thing is just horrible.
@@ -1934,27 +1971,34 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
         // the Thread from wherever (it's done again in Desktop::Main), and can
         // then use it to wait until we're definitely ready to continue.
 
-        SAL_INFO("lok", "Enabling OfficeIPCThread");
-        OfficeIPCThread::EnableOfficeIPCThread();
-        SAL_INFO("lok", "Starting soffice_main");
-        pLib->maThread = osl_createThread(lo_startmain, NULL);
-        SAL_INFO("lok", "Waiting for OfficeIPCThread");
-        OfficeIPCThread::WaitForReady();
-        SAL_INFO("lok", "OfficeIPCThread ready -- continuing");
-
-        // If the Thread has been disabled again that indicates that a
-        // restart is required (or in any case we don't have a useable
-        // process around).
-        if (!OfficeIPCThread::IsEnabled())
+        if (eStage != PRE_INIT)
         {
-            fprintf(stderr, "LOK init failed -- restart required\n");
-            return false;
+            SAL_INFO("lok", "Enabling OfficeIPCThread");
+            OfficeIPCThread::EnableOfficeIPCThread();
+            SAL_INFO("lok", "Starting soffice_main");
+            pLib->maThread = osl_createThread(lo_startmain, NULL);
+            SAL_INFO("lok", "Waiting for OfficeIPCThread");
+            OfficeIPCThread::WaitForReady();
+            SAL_INFO("lok", "OfficeIPCThread ready -- continuing");
+
+            // If the Thread has been disabled again that indicates that a
+            // restart is required (or in any case we don't have a useable
+            // process around).
+            if (!OfficeIPCThread::IsEnabled())
+            {
+                fprintf(stderr, "LOK init failed -- restart required\n");
+                return false;
+            }
         }
 
-        ErrorHandler::RegisterDisplay(aBasicErrorFunc);
+        if (eStage != SECOND_INIT)
+            ErrorHandler::RegisterDisplay(aBasicErrorFunc);
 
         SAL_INFO("lok", "LOK Initialized");
-        bInitialized = true;
+        if (eStage == PRE_INIT)
+            bPreInited = true;
+        else
+            bInitialized = true;
     }
     catch (css::uno::Exception& exception)
     {
@@ -1988,6 +2032,12 @@ LibreOfficeKit *libreofficekit_hook(const char* install_path)
     return libreofficekit_hook_2(install_path, NULL);
 }
 
+SAL_JNI_EXPORT
+int lok_preinit(const char* install_path, const char* user_profile_path)
+{
+    return lo_initialize(NULL, install_path, user_profile_path);
+}
+
 static void lo_destroy(LibreOfficeKit* pThis)
 {
     bool bSuccess = false;
diff --git a/include/cppuhelper/bootstrap.hxx b/include/cppuhelper/bootstrap.hxx
index debddcf..94fa0a5 100644
--- a/include/cppuhelper/bootstrap.hxx
+++ b/include/cppuhelper/bootstrap.hxx
@@ -75,6 +75,9 @@ defaultBootstrap_InitialComponentContext();
 CPPUHELPER_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > SAL_CALL
 defaultBootstrap_InitialComponentContext(const ::rtl::OUString & iniFile);
 
+CPPUHELPER_DLLPUBLIC void SAL_CALL
+preInitBootstrap();
+
 /**
  * An exception indicating a bootstrap error.
  *
diff --git a/smoketest/libtest.cxx b/smoketest/libtest.cxx
index ae87c79..60ee19e 100644
--- a/smoketest/libtest.cxx
+++ b/smoketest/libtest.cxx
@@ -83,7 +83,29 @@ int main (int argc, char **argv)
         return 1;
 
     // coverity[tainted_string] - build time test tool
-    Office *pOffice = lok_cpp_init( argv[1] );
+    char *install_path = argv[1];
+
+    if( argc > 4 )
+    {
+        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 );
+    }
+
+    Office *pOffice = lok_cpp_init( install_path );
     if( !pOffice )
     {
         fprintf( stderr, "Failed to initialize\n" );


More information about the Libreoffice-commits mailing list