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

Generated by: LCOV version 1.10