LCOV - code coverage report
Current view: top level - desktop/source/deployment/registry/script - dp_script.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 32 154 20.8 %
Date: 2014-11-03 Functions: 7 20 35.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "dp_script.hrc"
      22             : #include "dp_lib_container.h"
      23             : #include "dp_backend.h"
      24             : #include "dp_ucb.h"
      25             : #include <rtl/uri.hxx>
      26             : #include <ucbhelper/content.hxx>
      27             : #include <cppuhelper/exc_hlp.hxx>
      28             : #include <cppuhelper/implbase1.hxx>
      29             : #include <comphelper/servicedecl.hxx>
      30             : #include <svl/inettype.hxx>
      31             : #include <com/sun/star/util/XUpdatable.hpp>
      32             : #include <com/sun/star/script/XLibraryContainer3.hpp>
      33             : #include <com/sun/star/util/XMacroExpander.hpp>
      34             : #include <com/sun/star/uri/XUriReferenceFactory.hpp>
      35             : #include <memory>
      36             : #include "dp_scriptbackenddb.hxx"
      37             : 
      38             : using namespace ::dp_misc;
      39             : using namespace ::com::sun::star;
      40             : using namespace ::com::sun::star::uno;
      41             : using namespace ::com::sun::star::ucb;
      42             : 
      43             : namespace dp_registry {
      44             : namespace backend {
      45             : namespace script {
      46             : namespace {
      47             : 
      48             : typedef ::cppu::ImplInheritanceHelper1<
      49             :     ::dp_registry::backend::PackageRegistryBackend, util::XUpdatable > t_helper;
      50             : 
      51         490 : class BackendImpl : public t_helper
      52             : {
      53           0 :     class PackageImpl : public ::dp_registry::backend::Package
      54             :     {
      55             :         BackendImpl * getMyBackend() const;
      56             : 
      57             :         const OUString m_scriptURL;
      58             :         const OUString m_dialogURL;
      59             :         OUString m_dialogName;
      60             : 
      61             :         // Package
      62             :         virtual beans::Optional< beans::Ambiguous<sal_Bool> > isRegistered_(
      63             :             ::osl::ResettableMutexGuard & guard,
      64             :             ::rtl::Reference<AbortChannel> const & abortChannel,
      65             :             Reference<XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
      66             :         virtual void processPackage_(
      67             :             ::osl::ResettableMutexGuard & guard,
      68             :             bool registerPackage,
      69             :             bool startup,
      70             :             ::rtl::Reference<AbortChannel> const & abortChannel,
      71             :             Reference<XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
      72             : 
      73             :     public:
      74             :         PackageImpl(
      75             :             ::rtl::Reference<BackendImpl> const & myBackend,
      76             :             OUString const & url,
      77             :             Reference<XCommandEnvironment> const &xCmdEnv,
      78             :             OUString const & scriptURL, OUString const & dialogURL,
      79             :             bool bRemoved, OUString const & identifier);
      80             :     };
      81             :     friend class PackageImpl;
      82             : 
      83             :     // PackageRegistryBackend
      84             :     virtual Reference<deployment::XPackage> bindPackage_(
      85             :         OUString const & url, OUString const & mediaType,
      86             :         bool bRemoved, OUString const & identifier,
      87             :         Reference<XCommandEnvironment> const & xCmdEnv ) SAL_OVERRIDE;
      88             : 
      89             :     void addDataToDb(OUString const & url);
      90             :     bool hasActiveEntry(OUString const & url);
      91             :     void revokeEntryFromDb(OUString const & url);
      92             : 
      93             :     const Reference<deployment::XPackageTypeInfo> m_xBasicLibTypeInfo;
      94             :     const Reference<deployment::XPackageTypeInfo> m_xDialogLibTypeInfo;
      95             :     Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos;
      96             :     std::unique_ptr<ScriptBackendDb> m_backendDb;
      97             : public:
      98             :     BackendImpl( Sequence<Any> const & args,
      99             :                  Reference<XComponentContext> const & xComponentContext );
     100             : 
     101             :     // XUpdatable
     102             :     virtual void SAL_CALL update() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     103             : 
     104             :     // XPackageRegistry
     105             :     virtual Sequence< Reference<deployment::XPackageTypeInfo> > SAL_CALL
     106             :     getSupportedPackageTypes() throw (RuntimeException, std::exception) SAL_OVERRIDE;
     107             :     virtual void SAL_CALL packageRemoved(OUString const & url, OUString const & mediaType)
     108             :         throw (deployment::DeploymentException,
     109             :                uno::RuntimeException, std::exception) SAL_OVERRIDE;
     110             : 
     111             : };
     112             : 
     113             : 
     114           0 : BackendImpl::PackageImpl::PackageImpl(
     115             :     ::rtl::Reference<BackendImpl> const & myBackend,
     116             :     OUString const & url,
     117             :     Reference<XCommandEnvironment> const &xCmdEnv,
     118             :     OUString const & scriptURL, OUString const & dialogURL, bool bRemoved,
     119             :     OUString const & identifier)
     120           0 :     : Package( myBackend.get(), url,
     121             :                OUString(), OUString(), // will be late-initialized
     122           0 :                !scriptURL.isEmpty() ? myBackend->m_xBasicLibTypeInfo
     123           0 :                : myBackend->m_xDialogLibTypeInfo, bRemoved, identifier),
     124             :       m_scriptURL( scriptURL ),
     125           0 :       m_dialogURL( dialogURL )
     126             : {
     127             :     // name, displayName:
     128           0 :     if (!dialogURL.isEmpty()) {
     129           0 :         m_dialogName = LibraryContainer::get_libname(
     130           0 :             dialogURL, xCmdEnv, myBackend->getComponentContext() );
     131             :     }
     132           0 :     if (!scriptURL.isEmpty()) {
     133           0 :         m_name = LibraryContainer::get_libname(
     134           0 :             scriptURL, xCmdEnv, myBackend->getComponentContext() );
     135             :     }
     136             :     else
     137           0 :         m_name = m_dialogName;
     138           0 :     m_displayName = m_name;
     139           0 : }
     140             : 
     141             : 
     142         490 : BackendImpl::BackendImpl(
     143             :     Sequence<Any> const & args,
     144             :     Reference<XComponentContext> const & xComponentContext )
     145             :     : t_helper( args, xComponentContext ),
     146             :       m_xBasicLibTypeInfo( new Package::TypeInfo(
     147             :                                "application/vnd.sun.star.basic-library",
     148             :                                OUString() /* no file filter */,
     149             :                                getResourceString(RID_STR_BASIC_LIB),
     150         490 :                                RID_IMG_SCRIPTLIB) ),
     151             :       m_xDialogLibTypeInfo( new Package::TypeInfo(
     152             :                                 "application/vnd.sun.star.dialog-library",
     153             :                                 OUString() /* no file filter */,
     154             :                                 getResourceString(RID_STR_DIALOG_LIB),
     155         490 :                                 RID_IMG_DIALOGLIB) ),
     156        1470 :       m_typeInfos( 2 )
     157             : {
     158         490 :     m_typeInfos[ 0 ] = m_xBasicLibTypeInfo;
     159         490 :     m_typeInfos[ 1 ] = m_xDialogLibTypeInfo;
     160             : 
     161             :     OSL_ASSERT( ! transientMode() );
     162             : 
     163         490 :     if (!transientMode())
     164             :     {
     165         490 :         OUString dbFile = makeURL(getCachePath(), "backenddb.xml");
     166             :         m_backendDb.reset(
     167         490 :             new ScriptBackendDb(getComponentContext(), dbFile));
     168             :     }
     169             : 
     170         490 : }
     171           0 : void BackendImpl::addDataToDb(OUString const & url)
     172             : {
     173           0 :     if (m_backendDb.get())
     174           0 :         m_backendDb->addEntry(url);
     175           0 : }
     176             : 
     177           0 : bool BackendImpl::hasActiveEntry(OUString const & url)
     178             : {
     179           0 :     if (m_backendDb.get())
     180           0 :         return m_backendDb->hasActiveEntry(url);
     181           0 :     return false;
     182             : }
     183             : 
     184             : // XUpdatable
     185             : 
     186          64 : void BackendImpl::update() throw (RuntimeException, std::exception)
     187             : {
     188             :     // Nothing to do here after fixing i70283!?
     189          64 : }
     190             : 
     191             : // XPackageRegistry
     192             : 
     193             : Sequence< Reference<deployment::XPackageTypeInfo> >
     194         490 : BackendImpl::getSupportedPackageTypes() throw (RuntimeException, std::exception)
     195             : {
     196         490 :     return m_typeInfos;
     197             : }
     198           0 : void BackendImpl::revokeEntryFromDb(OUString const & url)
     199             : {
     200           0 :     if (m_backendDb.get())
     201           0 :         m_backendDb->revokeEntry(url);
     202           0 : }
     203             : 
     204           0 : void BackendImpl::packageRemoved(OUString const & url, OUString const & /*mediaType*/)
     205             :         throw (deployment::DeploymentException,
     206             :                uno::RuntimeException, std::exception)
     207             : {
     208           0 :     if (m_backendDb.get())
     209           0 :         m_backendDb->removeEntry(url);
     210           0 : }
     211             : 
     212             : // PackageRegistryBackend
     213             : 
     214           6 : Reference<deployment::XPackage> BackendImpl::bindPackage_(
     215             :     OUString const & url, OUString const & mediaType_,
     216             :     bool bRemoved, OUString const & identifier,
     217             :     Reference<XCommandEnvironment> const & xCmdEnv )
     218             : {
     219           6 :     OUString mediaType( mediaType_ );
     220           6 :     if (mediaType.isEmpty())
     221             :     {
     222             :         // detect media-type:
     223           6 :         ::ucbhelper::Content ucbContent;
     224          12 :         if (create_ucb_content( &ucbContent, url, xCmdEnv ) &&
     225           6 :             ucbContent.isFolder())
     226             :         {
     227             :             // probe for script.xlb:
     228           4 :             if (create_ucb_content(
     229             :                     0, makeURL( url, "script.xlb" ),
     230           4 :                     xCmdEnv, false /* no throw */ ))
     231           0 :                 mediaType = "application/vnd.sun.star.basic-library";
     232             :             // probe for dialog.xlb:
     233           4 :             else if (create_ucb_content(
     234             :                          0, makeURL( url, "dialog.xlb" ),
     235           4 :                          xCmdEnv, false /* no throw */ ))
     236           0 :                 mediaType = "application/vnd.sun.star.dialog-library";
     237             :         }
     238           6 :         if (mediaType.isEmpty())
     239             :             throw lang::IllegalArgumentException(
     240          12 :                 StrCannotDetectMediaType::get() + url,
     241          18 :                 static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) );
     242             :     }
     243             : 
     244           0 :     OUString type, subType;
     245           0 :     INetContentTypeParameterList params;
     246           0 :     if (INetContentTypes::parse( mediaType, type, subType, &params ))
     247             :     {
     248           0 :         if (type.equalsIgnoreAsciiCase("application"))
     249             :         {
     250           0 :             OUString dialogURL( makeURL( url, "dialog.xlb" ) );
     251           0 :             if (! create_ucb_content(
     252           0 :                     0, dialogURL, xCmdEnv, false /* no throw */ )) {
     253           0 :                 dialogURL = "";
     254             :             }
     255             : 
     256           0 :             if (subType.equalsIgnoreAsciiCase("vnd.sun.star.basic-library"))
     257             :             {
     258           0 :                 OUString scriptURL( makeURL( url, "script.xlb"));
     259           0 :                 if (! create_ucb_content(
     260           0 :                         0, scriptURL, xCmdEnv, false /* no throw */ )) {
     261           0 :                     scriptURL = "";
     262             :                 }
     263             : 
     264             :                 return new PackageImpl(
     265             :                     this, url, xCmdEnv, scriptURL,
     266           0 :                     dialogURL, bRemoved, identifier);
     267             :             }
     268           0 :             else if (subType.equalsIgnoreAsciiCase(
     269             :                          "vnd.sun.star.dialog-library")) {
     270             :                 return new PackageImpl(
     271             :                     this, url, xCmdEnv,
     272             :                     OUString() /* no script lib */,
     273             :                     dialogURL,
     274           0 :                     bRemoved, identifier);
     275           0 :             }
     276             :         }
     277             :     }
     278             :     throw lang::IllegalArgumentException(
     279           0 :         StrUnsupportedMediaType::get() + mediaType,
     280             :         static_cast<OWeakObject *>(this),
     281           6 :         static_cast<sal_Int16>(-1) );
     282             : }
     283             : 
     284             : 
     285             : // Package
     286           0 : BackendImpl * BackendImpl::PackageImpl::getMyBackend() const
     287             : {
     288           0 :     BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get());
     289           0 :     if (NULL == pBackend)
     290             :     {
     291             :         //May throw a DisposedException
     292           0 :         check();
     293             :         //We should never get here...
     294             :         throw RuntimeException(
     295             :             "Failed to get the BackendImpl",
     296           0 :             static_cast<OWeakObject*>(const_cast<PackageImpl *>(this)));
     297             :     }
     298           0 :     return pBackend;
     299             : }
     300             : 
     301             : beans::Optional< beans::Ambiguous<sal_Bool> >
     302           0 : BackendImpl::PackageImpl::isRegistered_(
     303             :     ::osl::ResettableMutexGuard & /* guard */,
     304             :     ::rtl::Reference<AbortChannel> const & /* abortChannel */,
     305             :     Reference<XCommandEnvironment> const & /* xCmdEnv */ )
     306             : {
     307           0 :     BackendImpl * that = getMyBackend();
     308           0 :     Reference< deployment::XPackage > xThisPackage( this );
     309             : 
     310           0 :     bool registered = that->hasActiveEntry(getURL());
     311             :     return beans::Optional< beans::Ambiguous<sal_Bool> >(
     312             :         true /* IsPresent */,
     313           0 :         beans::Ambiguous<sal_Bool>( registered, false /* IsAmbiguous */ ) );
     314             : }
     315             : 
     316             : void
     317           0 : lcl_maybeRemoveScript(
     318             :         bool const bExists,
     319             :         OUString const& rName,
     320             :         OUString const& rScriptURL,
     321             :         Reference<css::script::XLibraryContainer3> const& xScriptLibs)
     322             : {
     323           0 :     if (bExists && xScriptLibs.is() && xScriptLibs->hasByName(rName))
     324             :     {
     325           0 :         const OUString sScriptUrl = xScriptLibs->getOriginalLibraryLinkURL(rName);
     326           0 :         if (sScriptUrl == rScriptURL)
     327           0 :             xScriptLibs->removeLibrary(rName);
     328             :     }
     329           0 : }
     330             : 
     331             : bool
     332           0 : lcl_maybeAddScript(
     333             :         bool const bExists,
     334             :         OUString const& rName,
     335             :         OUString const& rScriptURL,
     336             :         Reference<css::script::XLibraryContainer3> const& xScriptLibs)
     337             : {
     338           0 :     if (bExists && xScriptLibs.is())
     339             :     {
     340           0 :         bool bCanAdd = true;
     341           0 :         if (xScriptLibs->hasByName(rName))
     342             :         {
     343           0 :             const OUString sOriginalUrl = xScriptLibs->getOriginalLibraryLinkURL(rName);
     344             :             //We assume here that library names in extensions are unique, which may not be the case
     345             :             //ToDo: If the script exist in another extension, then both extensions must have the
     346             :             //same id
     347           0 :             if (sOriginalUrl.match("vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE")
     348           0 :                 || sOriginalUrl.match("vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE")
     349           0 :                 || sOriginalUrl.match("vnd.sun.star.expand:$BUNDLED_EXTENSIONS")
     350           0 :                 || sOriginalUrl.match("$(INST)/share/basic/Access2Base/"))
     351             :             {
     352           0 :                 xScriptLibs->removeLibrary(rName);
     353           0 :                 bCanAdd = true;
     354             :             }
     355             :             else
     356             :             {
     357           0 :                 bCanAdd = false;
     358           0 :             }
     359             :         }
     360             : 
     361           0 :         if (bCanAdd)
     362             :         {
     363           0 :             xScriptLibs->createLibraryLink(rName, rScriptURL, false);
     364           0 :             return xScriptLibs->hasByName(rName);
     365             :         }
     366             :     }
     367             : 
     368           0 :     return false;
     369             : }
     370             : 
     371           0 : void BackendImpl::PackageImpl::processPackage_(
     372             :     ::osl::ResettableMutexGuard & /* guard */,
     373             :     bool doRegisterPackage,
     374             :     bool startup,
     375             :     ::rtl::Reference<AbortChannel> const & /* abortChannel */,
     376             :     Reference<XCommandEnvironment> const & /* xCmdEnv */ )
     377             : {
     378           0 :     BackendImpl * that = getMyBackend();
     379             : 
     380           0 :     Reference< deployment::XPackage > xThisPackage( this );
     381           0 :     Reference<XComponentContext> const & xComponentContext = that->getComponentContext();
     382             : 
     383           0 :     bool bScript = !m_scriptURL.isEmpty();
     384           0 :     Reference<css::script::XLibraryContainer3> xScriptLibs;
     385             : 
     386           0 :     bool bDialog = !m_dialogURL.isEmpty();
     387           0 :     Reference<css::script::XLibraryContainer3> xDialogLibs;
     388             : 
     389           0 :     bool bRunning = !startup && office_is_running();
     390           0 :     if( bRunning )
     391             :     {
     392           0 :         if( bScript )
     393             :         {
     394             :             xScriptLibs.set(
     395           0 :                 xComponentContext->getServiceManager()->createInstanceWithContext(
     396             :                     "com.sun.star.script.ApplicationScriptLibraryContainer",
     397           0 :                     xComponentContext ), UNO_QUERY_THROW );
     398             :         }
     399             : 
     400           0 :         if( bDialog )
     401             :         {
     402             :             xDialogLibs.set(
     403           0 :                 xComponentContext->getServiceManager()->createInstanceWithContext(
     404             :                     "com.sun.star.script.ApplicationDialogLibraryContainer",
     405           0 :                     xComponentContext ), UNO_QUERY_THROW );
     406             :         }
     407             :     }
     408           0 :     bool bRegistered = getMyBackend()->hasActiveEntry(getURL());
     409           0 :     if( !doRegisterPackage )
     410             :     {
     411             :         //We cannot just call removeLibrary(name) because this could remove a
     412             :         //script which was added by an extension in a different repository. For
     413             :         //example, extension foo is contained in the bundled repository and then
     414             :         //the user adds it it to the user repository. The extension manager will
     415             :         //then register the new script and revoke the script from the bundled
     416             :         //extension. removeLibrary(name) would now remove the script from the
     417             :         //user repository. That is, the script of the newly added user extension does
     418             :         //not work anymore. Therefore we must check if the currently active
     419             :         //script comes in fact from the currently processed extension.
     420             : 
     421           0 :         if (bRegistered)
     422             :         {
     423             :             //we also prevent and live deployment at startup
     424           0 :             if (!isRemoved() && !startup)
     425             :             {
     426           0 :                 lcl_maybeRemoveScript(bScript, m_name, m_scriptURL, xScriptLibs);
     427           0 :                 lcl_maybeRemoveScript(bDialog, m_dialogName, m_dialogURL, xDialogLibs);
     428             :             }
     429           0 :             getMyBackend()->revokeEntryFromDb(getURL());
     430           0 :             return;
     431             :         }
     432             :     }
     433           0 :     if (bRegistered)
     434           0 :         return;     // Already registered
     435             : 
     436             :     // Update LibraryContainer
     437           0 :     bool bScriptSuccess = false;
     438           0 :     bool bDialogSuccess = false;
     439           0 :     if (!startup)
     440             :     {
     441             :         //If there is a bundled extension, and the user installes the same extension
     442             :         //then the script from the bundled extension must be removed. If this does not work
     443             :         //then live deployment does not work for scripts.
     444           0 :         bScriptSuccess = lcl_maybeAddScript(bScript, m_name, m_scriptURL, xScriptLibs);
     445           0 :         bDialogSuccess = lcl_maybeAddScript(bDialog, m_dialogName, m_dialogURL, xDialogLibs);
     446             :     }
     447           0 :     bool bSuccess = bScript || bDialog;     // Something must have happened
     448           0 :     if( bRunning )
     449           0 :         if( (bScript && !bScriptSuccess) || (bDialog && !bDialogSuccess) )
     450           0 :             bSuccess = false;
     451             : 
     452           0 :     if (bSuccess)
     453           0 :         getMyBackend()->addDataToDb(getURL());
     454             : }
     455             : 
     456             : } // anon namespace
     457             : 
     458             : namespace sdecl = comphelper::service_decl;
     459         140 : sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI;
     460         140 : extern sdecl::ServiceDecl const serviceDecl(
     461             :     serviceBI,
     462             :     "com.sun.star.comp.deployment.script.PackageRegistryBackend",
     463             :     BACKEND_SERVICE_NAME );
     464             : 
     465             : } // namespace script
     466             : } // namespace backend
     467         420 : } // namespace dp_registry
     468             : 
     469             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10