diff options
45 files changed, 4396 insertions, 888 deletions
diff --git a/desktop/inc/app.hxx b/desktop/inc/app.hxx index 0ae632a6e968..4f5a3b176be3 100644 --- a/desktop/inc/app.hxx +++ b/desktop/inc/app.hxx @@ -132,6 +132,7 @@ class Desktop : public Application static sal_Bool LicenseNeedsAcceptance(); static sal_Bool IsFirstStartWizardNeeded(); static sal_Bool CheckExtensionDependencies(); + static void SynchronizeExtensionRepositories(); private: // Bootstrap methods diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx index efba60ca75b9..b82915871566 100644 --- a/desktop/source/app/app.cxx +++ b/desktop/source/app/app.cxx @@ -1395,6 +1395,9 @@ void Desktop::Main() bool bAbort = CheckExtensionDependencies(); if ( bAbort ) return; + //Check if bundled or shared extensions were added /removed + //and process those extensions + SynchronizeExtensionRepositories(); // First Start Wizard allowed ? if ( ! pCmdLineArgs->IsNoFirstStartWizard()) diff --git a/desktop/source/app/check_ext_deps.cxx b/desktop/source/app/check_ext_deps.cxx index 8b73e0c2c525..17dc20e1a129 100644 --- a/desktop/source/app/check_ext_deps.cxx +++ b/desktop/source/app/check_ext_deps.cxx @@ -27,21 +27,27 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_desktop.hxx" +#include <osl/file.hxx> #include <rtl/bootstrap.hxx> #include <rtl/ustring.hxx> +#include <rtl/logfile.hxx> +#include "cppuhelper/compbase3.hxx" + #include <unotools/configmgr.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/sequence.hxx> #include <cppuhelper/bootstrap.hxx> - +#include <com/sun/star/ucb/XCommandEnvironment.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/NamedValue.hpp> #include "com/sun/star/deployment/XPackage.hpp" #include "com/sun/star/deployment/XPackageManager.hpp" #include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" #include <com/sun/star/task/XJob.hpp> #include <com/sun/star/task/XJobExecutor.hpp> +#include <com/sun/star/task/XInteractionApprove.hpp> #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> #include <com/sun/star/util/XChangesBatch.hpp> @@ -53,9 +59,91 @@ using namespace com::sun::star; #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) +namespace +{ +//For use with XExtensionManager.synchronize +class SilentCommandEnv + : public ::cppu::WeakImplHelper3< ucb::XCommandEnvironment, + task::XInteractionHandler, + ucb::XProgressHandler > +{ +public: + virtual ~SilentCommandEnv(){}; + SilentCommandEnv(){}; + + // XCommandEnvironment + virtual uno::Reference<task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (uno::RuntimeException); + virtual uno::Reference<ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + uno::Reference<task::XInteractionRequest > const & xRequest ) + throw (uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( uno::Any const & Status ) + throw (uno::RuntimeException); + virtual void SAL_CALL update( uno::Any const & Status ) + throw (uno::RuntimeException); + virtual void SAL_CALL pop() throw (uno::RuntimeException); +}; +Reference<task::XInteractionHandler> SilentCommandEnv::getInteractionHandler() +throw (uno::RuntimeException) +{ + return this; +} + +Reference<ucb::XProgressHandler> SilentCommandEnv::getProgressHandler() +throw (uno::RuntimeException) +{ + return this; +} + +// XInteractionHandler +void SilentCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + + // We approve everything here + uno::Sequence< Reference< task::XInteractionContinuation > > conts( + xRequest->getContinuations() ); + Reference< task::XInteractionContinuation > const * pConts = + conts.getConstArray(); + sal_Int32 len = conts.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + + Reference< task::XInteractionApprove > xInteractionApprove( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + } + } +} + +// XProgressHandler +void SilentCommandEnv::push( uno::Any const & /*Status*/ ) +throw (uno::RuntimeException) +{ +} + + +void SilentCommandEnv::update( uno::Any const & /*Status */) +throw (uno::RuntimeException) +{ +} + +void SilentCommandEnv::pop() throw (uno::RuntimeException) +{ +} + +} // end namespace static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ); - //------------------------------------------------------------------------------ static sal_Int16 impl_showExtensionDialog( uno::Reference< uno::XComponentContext > &xContext ) { @@ -254,3 +342,146 @@ sal_Bool Desktop::CheckExtensionDependencies() return bAbort; } +//Returns true if the Folder was more recently modified then +//the lastsynchronized file. That is the repository needs to +//be synchronized. +static bool compareExtensionFolderWithLastSynchronizedFile( + OUString const & folderURL, OUString const & fileURL) +{ + bool bNeedsSync = false; + ::osl::DirectoryItem itemExtFolder; + ::osl::File::RC err1 = + ::osl::DirectoryItem::get(folderURL, itemExtFolder); + //If it does not exist, then there is nothing to be done + if (err1 == ::osl::File::E_NOENT) + { + return false; + } + else if (err1 != ::osl::File::E_None) + { + OSL_ENSURE(0, "Cannot access extension folder"); + return true; //sync just in case + } + + //If last synchronized does not exist, then OOo is started for the first time + ::osl::DirectoryItem itemFile; + ::osl::File::RC err2 = ::osl::DirectoryItem::get(fileURL, itemFile); + if (err2 == ::osl::File::E_NOENT) + { + return true; + + } + else if (err2 != ::osl::File::E_None) + { + OSL_ENSURE(0, "Cannot access file lastsynchronized"); + return true; //sync just in case + } + + //compare the modification time of the extension folder and the last + //modified file + ::osl::FileStatus statFolder(FileStatusMask_ModifyTime); + ::osl::FileStatus statFile(FileStatusMask_ModifyTime); + if (itemExtFolder.getFileStatus(statFolder) == ::osl::File::E_None) + { + if (itemFile.getFileStatus(statFile) == ::osl::File::E_None) + { + TimeValue timeFolder = statFolder.getModifyTime(); + TimeValue timeFile = statFile.getModifyTime(); + + if (timeFile.Seconds < timeFolder.Seconds) + bNeedsSync = true; + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + } + else + { + OSL_ASSERT(0); + bNeedsSync = true; + } + return bNeedsSync; +} + +static bool needToSyncRepostitory(OUString const & name) +{ + OUString folder; + OUString file; + if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("bundled")))) + { + folder = OUString( + RTL_CONSTASCII_USTRINGPARAM("$BUNDLED_EXTENSIONS")); + file = OUString ( + RTL_CONSTASCII_USTRINGPARAM( + "$BUNDLED_EXTENSIONS_USER/lastsynchronized")); + } + else if (name.equals(OUString(RTL_CONSTASCII_USTRINGPARAM("shared")))) + { + folder = OUString( + RTL_CONSTASCII_USTRINGPARAM( + "$UNO_SHARED_PACKAGES_CACHE/uno_packages")); + file = OUString ( + RTL_CONSTASCII_USTRINGPARAM( + "$SHARED_EXTENSIONS_USER/lastsynchronized")); + } + else + { + OSL_ASSERT(0); + return true; + } + ::rtl::Bootstrap::expandMacros(folder); + ::rtl::Bootstrap::expandMacros(file); + return compareExtensionFolderWithLastSynchronizedFile( + folder, file); +} + +void Desktop::SynchronizeExtensionRepositories() +{ + RTL_LOGFILE_CONTEXT(aLog,"desktop (jl97489) ::Desktop::SynchronizeExtensionRepositories"); + OUString sDisable; + ::rtl::Bootstrap::get( + OUString(RTL_CONSTASCII_USTRINGPARAM("DISABLE_SYNC_EXTENSIONS")), + sDisable, + OUString(RTL_CONSTASCII_USTRINGPARAM(""))); + if (sDisable.getLength() > 0) + return; + Reference<deployment::XExtensionManager> xExtensionManager; + //synchronize shared before bundled otherewise there are + //more revoke and registration calls. + OUString sShared(RTL_CONSTASCII_USTRINGPARAM("shared")); + if (needToSyncRepostitory(sShared)) + { + xExtensionManager = + deployment::ExtensionManager::get( + comphelper_getProcessComponentContext()); + if (xExtensionManager.is()) + { + Reference<ucb::XCommandEnvironment> cmdEnv( + new SilentCommandEnv()); + xExtensionManager->synchronize( + sShared, Reference<task::XAbortChannel>(), cmdEnv); + } + + } + + OUString sBundled(RTL_CONSTASCII_USTRINGPARAM("bundled")); + if (needToSyncRepostitory( sBundled)) + { + if (!xExtensionManager.is()) + { + xExtensionManager = + deployment::ExtensionManager::get( + comphelper_getProcessComponentContext()); + } + if (xExtensionManager.is()) + { + Reference<ucb::XCommandEnvironment> cmdEnv( + new SilentCommandEnv()); + xExtensionManager->synchronize( + sBundled, Reference<task::XAbortChannel>(), cmdEnv); + + } + } +} diff --git a/desktop/source/deployment/dp_services.cxx b/desktop/source/deployment/dp_services.cxx index c83a62bfd17e..05b9a2a1971a 100644 --- a/desktop/source/deployment/dp_services.cxx +++ b/desktop/source/deployment/dp_services.cxx @@ -28,7 +28,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_desktop.hxx" -#define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 11 +#define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 12 #include "comphelper/servicedecl.hxx" using namespace com::sun::star; @@ -69,6 +69,8 @@ namespace factory { extern sdecl::ServiceDecl const serviceDecl; bool singleton_entries( uno::Reference<registry::XRegistryKey> const& ); } +extern sdecl::ServiceDecl const serviceDecl; +bool singleton_entries( uno::Reference<registry::XRegistryKey> const& ); } namespace dp_log { @@ -109,9 +111,11 @@ sal_Bool SAL_CALL component_writeInfo( dp_manager::factory::serviceDecl, dp_log::serviceDecl, dp_migration::serviceDecl, - dp_info::serviceDecl ) && + dp_info::serviceDecl, + dp_manager::serviceDecl) && dp_manager::factory::singleton_entries( pRegistryKey ) && - dp_info::singleton_entries( pRegistryKey ); + dp_info::singleton_entries( pRegistryKey ) && + dp_manager::singleton_entries( pRegistryKey); } void * SAL_CALL component_getFactory( @@ -130,7 +134,8 @@ void * SAL_CALL component_getFactory( dp_manager::factory::serviceDecl, dp_log::serviceDecl, dp_migration::serviceDecl, - dp_info::serviceDecl ); + dp_info::serviceDecl, + dp_manager::serviceDecl); } } // extern "C" diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx index 58a5ab1c19ea..89a5ae1e22c8 100644 --- a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx @@ -110,12 +110,15 @@ using ::rtl::OUString; namespace { -OUString getVersion( const uno::Reference< deployment::XPackage > &rPackage ) +OUString getVersion( OUString const & sVersion ) { - OUString sVersion( rPackage->getVersion()); return ( sVersion.getLength() == 0 ) ? OUString( RTL_CONSTASCII_USTRINGPARAM( "0" ) ) : sVersion; } +OUString getVersion( const uno::Reference< deployment::XPackage > &rPackage ) +{ + return getVersion( rPackage->getVersion()); +} } @@ -468,7 +471,8 @@ void ProgressCmdEnv::handle( uno::Reference< task::XInteractionRequest > const & else if (request >>= verExc) { sal_uInt32 id; - switch (dp_misc::comparePackageVersions( verExc.New, verExc.Deployed )) + switch (dp_misc::compareVersions( + verExc.NewVersion, verExc.Deployed->getVersion() )) { case dp_misc::LESS: id = RID_WARNINGBOX_VERSION_LESS; @@ -480,8 +484,8 @@ void ProgressCmdEnv::handle( uno::Reference< task::XInteractionRequest > const & id = RID_WARNINGBOX_VERSION_GREATER; break; } - OSL_ASSERT( verExc.New.is() && verExc.Deployed.is() ); - bool bEqualNames = verExc.New->getDisplayName().equals( + OSL_ASSERT( verExc.Deployed.is() ); + bool bEqualNames = verExc.NewDisplayName.equals( verExc.Deployed->getDisplayName()); { vos::OGuard guard(Application::GetSolarMutex()); @@ -506,9 +510,9 @@ void ProgressCmdEnv::handle( uno::Reference< task::XInteractionRequest > const & { s = String(ResId(RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES, *DeploymentGuiResMgr::get())); } - s.SearchAndReplaceAllAscii( "$NAME", verExc.New->getDisplayName()); + s.SearchAndReplaceAllAscii( "$NAME", verExc.NewDisplayName); s.SearchAndReplaceAllAscii( "$OLDNAME", verExc.Deployed->getDisplayName()); - s.SearchAndReplaceAllAscii( "$NEW", getVersion(verExc.New) ); + s.SearchAndReplaceAllAscii( "$NEW", getVersion(verExc.NewVersion) ); s.SearchAndReplaceAllAscii( "$DEPLOYED", getVersion(verExc.Deployed) ); box.SetMessText(s); approve = box.Execute() == RET_OK; @@ -527,7 +531,7 @@ void ProgressCmdEnv::handle( uno::Reference< task::XInteractionRequest > const & { vos::OGuard guard(Application::GetSolarMutex()); - approve = m_pDialogHelper->installExtensionWarn( instExc.New->getDisplayName() ); + approve = m_pDialogHelper->installExtensionWarn( instExc.displayName ); } else approve = false; diff --git a/desktop/source/deployment/inc/dp_descriptioninfoset.hxx b/desktop/source/deployment/inc/dp_descriptioninfoset.hxx index 38a1870782ed..3d2d56cad00a 100644 --- a/desktop/source/deployment/inc/dp_descriptioninfoset.hxx +++ b/desktop/source/deployment/inc/dp_descriptioninfoset.hxx @@ -62,6 +62,7 @@ struct DESKTOP_DEPLOYMENTMISC_DLLPUBLIC SimpleLicenseAttributes bool suppressIfRequired; }; + /** Access to the content of an XML <code>description</code> element. @@ -226,6 +227,8 @@ public: ::com::sun::star::uno::Reference< ::com::sun::star::xml::xpath::XXPathAPI > getXpath() const; + bool hasDescription() const; + private: SAL_DLLPRIVATE ::boost::optional< ::rtl::OUString > getOptionalValue( ::rtl::OUString const & expression) const; @@ -289,6 +292,18 @@ private: ::com::sun::star::xml::xpath::XXPathAPI > m_xpath; }; +inline bool DescriptionInfoset::hasDescription() const +{ + return m_element.is(); +} + +/** creates a DescriptionInfoset object. + + The argument sExtensionFolderURL is a file URL to extension folder containing + the description.xml. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +DescriptionInfoset getDescriptionInfoset(::rtl::OUString const & sExtensionFolderURL); } #endif diff --git a/desktop/source/deployment/inc/dp_misc.h b/desktop/source/deployment/inc/dp_misc.h index a717e7797c8a..ee5867a655d3 100644 --- a/desktop/source/deployment/inc/dp_misc.h +++ b/desktop/source/deployment/inc/dp_misc.h @@ -74,9 +74,25 @@ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString expandUnoRcUrl( ::rtl::OUString const & url ); //============================================================================== + +/** appends a relative path to a url. + + The relative path must already be correctly encoded for use in an URL. + If the URL starts with vnd.sun.star.expand then the relative path will + be again encoded for use in an "expand" URL. + */ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString makeURL( ::rtl::OUString const & baseURL, ::rtl::OUString const & relPath ); + +/** appends a relative path to a url. + + This is the same as makeURL, but the relative Path must me a segment + of an system path. + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString makeURLAppendSysPathSegment( + ::rtl::OUString const & baseURL, ::rtl::OUString const & relPath ); + //============================================================================== DESKTOP_DEPLOYMENTMISC_DLLPUBLIC ::rtl::OUString generateRandomPipeId(); @@ -151,6 +167,11 @@ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC void TRACE(::rtl::OUString const & sText); DESKTOP_DEPLOYMENTMISC_DLLPUBLIC void TRACE(::rtl::OString const & sText); + +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +bool hasExtensionRepositoryChanged(::rtl::OUString const & repository); + + } #endif diff --git a/desktop/source/deployment/inc/dp_version.hxx b/desktop/source/deployment/inc/dp_version.hxx index 9808ebaab388..c459333f97a9 100644 --- a/desktop/source/deployment/inc/dp_version.hxx +++ b/desktop/source/deployment/inc/dp_version.hxx @@ -43,13 +43,6 @@ enum Order { LESS, EQUAL, GREATER }; DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions( ::rtl::OUString const & version1, ::rtl::OUString const & version2); - -DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order comparePackageVersions( - ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > - const & package1, - ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > - const & package2); - } #endif diff --git a/desktop/source/deployment/manager/dp_activepackages.cxx b/desktop/source/deployment/manager/dp_activepackages.cxx index 04dc22b77a77..bf9071682b2e 100644 --- a/desktop/source/deployment/manager/dp_activepackages.cxx +++ b/desktop/source/deployment/manager/dp_activepackages.cxx @@ -96,9 +96,23 @@ static char const legacyPrefix[] = "org.openoffice.legacy."; OSL_ASSERT(i2 >= 0); d.fileName = ::rtl::OUString( value.getStr() + i1 + 1, i2 - i1 - 1, RTL_TEXTENCODING_UTF8); - d.mediaType = ::rtl::OUString( - value.getStr() + i2 + 1, value.getLength() - i2 - 1, - RTL_TEXTENCODING_UTF8); + sal_Int32 i3 = value.indexOf(separator, i2 + 1); + + if (i3 < 0) + { + //Before ActivePackages::Data::version was added + d.mediaType = ::rtl::OUString( + value.getStr() + i2 + 1, value.getLength() - i2 - 1, + RTL_TEXTENCODING_UTF8); + } + else + { + d.mediaType = ::rtl::OUString( + value.getStr() + i2 + 1, i3 - i2 -1, RTL_TEXTENCODING_UTF8); + d.version = ::rtl::OUString( + value.getStr() + i3 + 1, value.getLength() - i3 - 1, + RTL_TEXTENCODING_UTF8); + } return d; } @@ -172,6 +186,8 @@ void ActivePackages::put(::rtl::OUString const & id, Data const & data) { b.append(::rtl::OUStringToOString(data.fileName, RTL_TEXTENCODING_UTF8)); b.append(separator); b.append(::rtl::OUStringToOString(data.mediaType, RTL_TEXTENCODING_UTF8)); + b.append(separator); + b.append(::rtl::OUStringToOString(data.version, RTL_TEXTENCODING_UTF8)); m_map.put(newKey(id), b.makeStringAndClear()); } diff --git a/desktop/source/deployment/manager/dp_activepackages.hxx b/desktop/source/deployment/manager/dp_activepackages.hxx index 1c58f76be245..36060d26bd02 100644 --- a/desktop/source/deployment/manager/dp_activepackages.hxx +++ b/desktop/source/deployment/manager/dp_activepackages.hxx @@ -42,9 +42,19 @@ namespace dp_manager { class ActivePackages { public: struct Data { + /* name of the temporary file (shared, user extension) or the name of + the folder of the bundled extension. + It does not contain the trailing '_' of the folder. + UTF-8 encoded + */ ::rtl::OUString temporaryName; + /* The file name (shared, user) or the folder name (bundled) + If the key is the file name, then file name is not encoded. + If the key is the idendifier then the file name is UTF-8 encoded. + */ ::rtl::OUString fileName; ::rtl::OUString mediaType; + ::rtl::OUString version; }; typedef ::std::vector< ::std::pair< ::rtl::OUString, Data > > Entries; diff --git a/desktop/source/deployment/manager/dp_extensionmanager.cxx b/desktop/source/deployment/manager/dp_extensionmanager.cxx new file mode 100644 index 000000000000..469245bef340 --- /dev/null +++ b/desktop/source/deployment/manager/dp_extensionmanager.cxx @@ -0,0 +1,1301 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include <cppuhelper/implbase1.hxx> + +#include "comphelper/servicedecl.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "rtl/bootstrap.hxx" +#include "com/sun/star/deployment/ExtensionManager.hpp" +#include "com/sun/star/deployment/XExtensionManager.hpp" +#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +#include "com/sun/star/deployment/XPackageManagerFactory.hpp" +#include "com/sun/star/deployment/XPackage.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/beans/Optional.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/beans/Ambiguous.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/io/XInputStream.hpp" +#include "comphelper/sequence.hxx" +#include "xmlscript/xml_helper.hxx" +#include "osl/diagnose.h" +#include "dp_interact.h" +#include "dp_resource.h" +#include "dp_ucb.h" +#include "dp_identifier.hxx" + +#include "dp_extensionmanager.hxx" +#include "dp_tmprepocmdenv.hxx" +#include <list> +#include <hash_map> +#include <algorithm> + +namespace deploy = com::sun::star::deployment; +namespace lang = com::sun::star::lang; +namespace registry = com::sun::star::registry; +namespace task = com::sun::star::task; +namespace ucb = com::sun::star::ucb; +namespace uno = com::sun::star::uno; +namespace beans = com::sun::star::beans; +namespace css = com::sun::star; + +//#define OUSTR(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +namespace { + +struct CompIdentifiers +{ + bool operator() (::std::vector<Reference<deploy::XPackage> > const & a, + ::std::vector<Reference<deploy::XPackage> > const & b) + { + + if (getName(a).compareTo(getName(b)) < 0) + return true; + return false; + } + + OUString getName(::std::vector<Reference<deploy::XPackage> > const & a); +}; + +OUString CompIdentifiers::getName(::std::vector<Reference<deploy::XPackage> > const & a) +{ + OSL_ASSERT(a.size() == 3); + //get the first non-null reference + Reference<deploy::XPackage> extension; + ::std::vector<Reference<deploy::XPackage> >::const_iterator it = a.begin(); + for (; it != a.end(); it++) + { + if (it->is()) + { + extension = *it; + break; + } + } + OSL_ASSERT(extension.is()); + return extension->getDisplayName(); +} +} //end namespace + +namespace dp_manager { + + + +//------------------------------------------------------------------------------ + +//ToDo: bundled extension +ExtensionManager::ExtensionManager( Reference< uno::XComponentContext > const& xContext) : + m_xContext( xContext ) +{ + Reference<deploy::XPackageManagerFactory> xPackageManagerFactory( + deploy::thePackageManagerFactory::get(m_xContext)); + m_userRepository = xPackageManagerFactory->getPackageManager(OUSTR("user")); + m_sharedRepository = xPackageManagerFactory->getPackageManager(OUSTR("shared")); + m_bundledRepository = xPackageManagerFactory->getPackageManager(OUSTR("bundled")); + m_tmpRepository = xPackageManagerFactory->getPackageManager(OUSTR("tmp")); + + m_repositoryNames.push_back(OUSTR("user")); + m_repositoryNames.push_back(OUSTR("shared")); + m_repositoryNames.push_back(OUSTR("bundled")); +} + +//------------------------------------------------------------------------------ + +ExtensionManager::~ExtensionManager() +{ +} + +Reference<task::XAbortChannel> ExtensionManager::createAbortChannel() + throw (uno::RuntimeException) +{ + return new dp_misc::AbortChannel; +} + +/* + Enters the XPackage objects into a map. They must be all from the + same repository. The value type of the map is a vector, where each vector + represents an extension with a particular identifier. The first member + is represents the user extension, the second the shared extension and the + third the bundled extension. + */ +void ExtensionManager::addExtensionsToMap( + id2extensions & mapExt, + uno::Sequence<Reference<deploy::XPackage> > const & seqExt, + OUString const & repository) +{ + //Determine the index in the vector where these extensions are to be + //added. + ::std::list<OUString>::const_iterator citNames = + m_repositoryNames.begin(); + int index = 0; + for (;citNames != m_repositoryNames.end(); citNames++, index++) + { + if (citNames->equals(repository)) + break; + } + + for (int i = 0; i < seqExt.getLength(); i++) + { + Reference<deploy::XPackage> const & xExtension = seqExt[i]; + OUString id = dp_misc::getIdentifier(xExtension); + id2extensions::iterator ivec = mapExt.find(id); + if (ivec == mapExt.end()) + { + ::std::vector<Reference<deploy::XPackage> > vec(3); + vec[index] = xExtension; + mapExt[id] = vec; + } + else + { + ivec->second[index] = xExtension; + } + } +} + +/* + returns a list containing extensions with the same identifier from + all repositories (user, shared, bundled) If one repository does not + have this extension, then the list contains an empty Referenc. The list + is ordered according to the priority of the repostories: + 1. user + 2. shared + 3. bundled + + The number of elements is always three, unless the number of repository + changes. + */ +::std::list<Reference<deploy::XPackage> > + ExtensionManager::getExtensionsWithSameId( + OUString const & identifier, OUString const & fileName) + +{ + ::std::list<Reference<deploy::XPackage> > extensionList; + try + { //will throw an exception if the extension does not exist + extensionList.push_back(m_userRepository->getDeployedPackage( + identifier, fileName, Reference<ucb::XCommandEnvironment>())); + } catch(lang::IllegalArgumentException &) + { + extensionList.push_back(Reference<deploy::XPackage>()); + } + try + { + extensionList.push_back(m_sharedRepository->getDeployedPackage( + identifier, fileName, Reference<ucb::XCommandEnvironment>())); + } catch (lang::IllegalArgumentException &) + { + extensionList.push_back(Reference<deploy::XPackage>()); + } + try + { + extensionList.push_back(m_bundledRepository->getDeployedPackage( + identifier, fileName, Reference<ucb::XCommandEnvironment>())); + } catch (lang::IllegalArgumentException &) + { + extensionList.push_back(Reference<deploy::XPackage>()); + } + OSL_ASSERT(extensionList.size() == 3); + return extensionList; +} + + +/* + +*/ +Reference<deploy::XPackage> ExtensionManager::getExtensionAndStatus( + ::rtl::OUString const & identifier, + ::rtl::OUString const & fileName, + ::rtl::OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv, + bool & out_bWasRegistered) +{ + Reference<deploy::XPackage> theExtension; + ::std::list<Reference<deploy::XPackage> > listExtensions = + getExtensionsWithSameId(identifier, fileName); + OSL_ASSERT(listExtensions.size() == m_repositoryNames.size()); + Reference<deploy::XPackage> xActiveExtension; + ::std::list<OUString>::const_iterator + inames = m_repositoryNames.begin(); + ::std::list<Reference<deploy::XPackage> >::const_iterator + iext = listExtensions.begin(); + for (; inames != m_repositoryNames.end(); inames++, iext++) + { + if (repository.equals(*inames)) + { + theExtension = *iext; + if (iext->is()) + { + beans::Optional<beans::Ambiguous<sal_Bool> > optRegistered = + (*iext)->isRegistered(xAbortChannel, xCmdEnv); + OSL_ENSURE(! optRegistered.Value.IsAmbiguous, + "Extension is not properly registered"); + //IsAmbiguous = true: only partly registered, but we assume + //that this is the active extension, and something went wrong when registering it + //previously. + if (optRegistered.IsPresent + && (optRegistered.Value.Value || optRegistered.Value.IsAmbiguous)) + out_bWasRegistered = true; + } + break; + } + } + return theExtension; +} + +/* + Determines if the user extension was disabled by the user. Currently a user + cannot disable extensions from other repositories. If an extension does not + contain any items which need to be registered then the extension cannot + actually be disabled (because it cannot be registered). In this case false is + returned. If there is no user extension then also false is returned. + + A user extension is regarded as disabled if there is an extension in a + repository with a lower priority that is registered. + */ +bool ExtensionManager::isUserExtensionDisabled( + OUString const & identifier, OUString const & fileName, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + +{ + bool bDisabled = false; + ::std::list<Reference<deploy::XPackage> > listExtensions = + getExtensionsWithSameId(identifier, fileName); + ::std::list<Reference<deploy::XPackage> >::const_iterator + iext = listExtensions.begin(); + bool bCheckOptional = false; + Reference<deploy::XPackage> xActive; + for (; iext != listExtensions.end(); iext++) + { + if (iext->is()) + { + if (!(*iext)->isRegistered(xAbortChannel, xCmdEnv).IsPresent) + { + // IsPresent must be the same for all extnesions + OSL_ASSERT(!bCheckOptional); + break; + } + else + { + bCheckOptional = true; + if ((*iext)->isRegistered(xAbortChannel, xCmdEnv).Value.Value) + { + xActive = *iext; + break; + } + } + } + Reference<deploy::XPackage> const & xUser = listExtensions.front(); + if (xUser.is() + && xActive.is() + && xUser != xActive) + bDisabled = true; + } + return bDisabled; +} +/* + This method determines the active extension (XPackage.registerPackage) with a + particular identifier. + + The parameter bUserDisabled determines if the user extension is disabled. + + When the user repository contains an extension with the given identifier and + it is not disabled by the user, then it is always registered. Otherwise an + extension is only registered when there is no registered extension in one of + the repositories with a higher priority. That is, if the extension is from + the shared repository and an active extension with the same identifer is in + the user repository, then the extension is not registered. Similarly a + bundled extension is not registered if there is an active extension with the + same identifier in the shared or user repository. +*/ +void ExtensionManager::activateExtension( + OUString const & identifier, OUString const & fileName, + bool bUserDisabled, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + ::std::list<Reference<deploy::XPackage> > listExtensions = + getExtensionsWithSameId(identifier, fileName); + OSL_ASSERT(listExtensions.size() == 3); + ::std::list<Reference<deploy::XPackage> >::const_iterator + iext = listExtensions.begin(); + //skip disabled user extension + if (listExtensions.front().is() && bUserDisabled) + iext++; + bool bActive = false; + for (; iext != listExtensions.end(); iext++) + { + if (iext->is()) + { + //get the registration value of the current iteration + beans::Optional<beans::Ambiguous<sal_Bool> > optReg = + (*iext)->isRegistered(xAbortChannel, xCmdEnv); + //If nothing can be registered then break + if (!optReg.IsPresent) + break; + + //If we have already determined an active extension then we must + //make sure to unregister all extensions with the same id in + //repositories with a lower priority + if (bActive) + { + (*iext)->revokePackage(xAbortChannel, xCmdEnv); + } + else + { + //This is the first extension in the ordered list, which becomes + //the active extension + bActive = true; + //Register if not already done. + //reregister if the value is ambiguous, which indicates that + //something went wrong during last registration. + (*iext)->registerPackage(xAbortChannel, xCmdEnv); + } + } + } +} + +Reference<deploy::XPackage> ExtensionManager::backupExtension( + OUString const & identifier, OUString const & fileName, + Reference<deploy::XPackageManager> const & xPackageManager, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + Reference<deploy::XPackage> xBackup; + Reference<ucb::XCommandEnvironment> tmpCmdEnv( + new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); + Reference<deploy::XPackage> xOldExtension; + xOldExtension = xPackageManager->getDeployedPackage( + identifier, fileName, tmpCmdEnv); + + if (xOldExtension.is()) + { + xBackup = m_tmpRepository->addPackage( + xOldExtension->getURL(), OUString(), + Reference<task::XAbortChannel>(), tmpCmdEnv); + + OSL_ENSURE(xBackup.is(), "Failed to backup extension"); + } + return xBackup; +} + +uno::Sequence< Reference<deploy::XPackageTypeInfo> > +ExtensionManager::getSupportedPackageTypes(OUString const & repository) + throw (uno::RuntimeException) +{ + if (repository.equals(OUSTR("user"))) + return m_userRepository->getSupportedPackageTypes(); + else if (repository.equals(OUSTR("shared"))) + return m_sharedRepository->getSupportedPackageTypes(); + else + return uno::Sequence< Reference<deploy::XPackageTypeInfo> >(); +} + +// Only add to shared and user repository +Reference<deploy::XPackage> ExtensionManager::addExtension( + OUString const & url, OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + Reference<deploy::XPackage> xNewExtension; + //Determine the repository to use + Reference<deploy::XPackageManager> xPackageManager; + if (repository.equals(OUSTR("user"))) + xPackageManager = m_userRepository; + else if (repository.equals(OUSTR("shared"))) + xPackageManager = m_sharedRepository; + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + ::osl::MutexGuard guard(m_mutex); + Reference<deploy::XPackage> xTmpExtension = + getTempExtension(url, xAbortChannel, xCmdEnv); + const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension); + const OUString sFileName = xTmpExtension->getName(); + const OUString sDisplayName = xTmpExtension->getDisplayName(); + const OUString sVersion = xTmpExtension->getVersion(); + + Reference<deploy::XPackage> xOldExtension; + bool bUserDisabled = false; + Reference<deploy::XPackage> xExtensionBackup; + + uno::Any excOccurred1; + uno::Any excOccurred2; + + try + { + //If we add a user extension and there is already one which was + //disabled by a user, then the newly installed one is enabled. If we + //add to another repository then the user extension remains + //disabled. + if (! repository.equals(OUSTR("user"))) + bUserDisabled = isUserExtensionDisabled( + sIdentifier, sFileName, xAbortChannel, xCmdEnv); + + bool bWasRegistered = false; + xOldExtension = getExtensionAndStatus( + sIdentifier, sFileName, repository, xAbortChannel, + xCmdEnv, bWasRegistered); + bool bCanInstall = false; + try + { + if (xOldExtension.is()) + { + //throws a CommandFailedException if the user cancels + //the action. + checkUpdate(sVersion, sDisplayName,xOldExtension, xCmdEnv); + } + else + { + //throws a CommandFailedException if the user cancels + //the action. + checkInstall(sDisplayName, xCmdEnv); + } + + bCanInstall = xTmpExtension->checkPrerequisites( + xAbortChannel, xCmdEnv, xOldExtension.is(), repository); + } + catch (deploy::DeploymentException& ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (...) { + excOccurred1 = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during addExtension, url: ") + + url, static_cast<OWeakObject*>(this), excOccurred1); + excOccurred1 <<= exc; + } + + if (bCanInstall) + { + if (xOldExtension.is()) + { + if (bWasRegistered) + xOldExtension->revokePackage(xAbortChannel, xCmdEnv); + //save the old user extension in case the user aborts + //store the extension in the tmp repository, this will overwrite + //xTmpPackage (same identifier). Do not let the user abort or + //interact + Reference<ucb::XCommandEnvironment> tmpCmdEnv( + new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); + //importing the old extension in the tmp repository will remove + //the xTmpExtension + xTmpExtension = 0; + xExtensionBackup = m_tmpRepository->importExtension( + xOldExtension, Reference<task::XAbortChannel>(), + tmpCmdEnv); + } + + xNewExtension = xPackageManager->addPackage( + url, OUString(), xAbortChannel, xCmdEnv); + activateExtension( + dp_misc::getIdentifier(xNewExtension), + xNewExtension->getName(), bUserDisabled, + xAbortChannel, xCmdEnv); + } + } + catch (deploy::DeploymentException& ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred2 = ::cppu::getCaughtException(); + } catch (...) { + excOccurred2 = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during addExtension, url: ") + + url, static_cast<OWeakObject*>(this), excOccurred2); + excOccurred2 <<= exc; + } + + if (excOccurred2.hasValue()) + { + //It does not matter what exception is thrown. We try to + //recover the original status. + //If the user aborted installation then a ucb::CommandAbortedException + //is thrown. + //Use a private AbortChannel so the user cannot interrupt. + try + { + Reference<ucb::XCommandEnvironment> tmpCmdEnv( + new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); + if (xExtensionBackup.is()) + { + Reference<deploy::XPackage> xRestored = + xPackageManager->importExtension( + xExtensionBackup, Reference<task::XAbortChannel>(), + tmpCmdEnv); + } + activateExtension( + sIdentifier, sFileName, bUserDisabled, + Reference<task::XAbortChannel>(), tmpCmdEnv); + if (xTmpExtension.is() || xExtensionBackup.is()) + m_tmpRepository->removePackage( + sIdentifier, OUString(), xAbortChannel, xCmdEnv); + } + catch (...) + { + } + ::cppu::throwException(excOccurred2); + } + if (xTmpExtension.is() || xExtensionBackup.is()) + m_tmpRepository->removePackage( + sIdentifier,OUString(), xAbortChannel, xCmdEnv); + + if (excOccurred1.hasValue()) + ::cppu::throwException(excOccurred1); + + return xNewExtension; +} + +void ExtensionManager::removeExtension( + OUString const & identifier, OUString const & fileName, + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + uno::Any excOccurred1; + Reference<deploy::XPackage> xExtensionBackup; + Reference<deploy::XPackageManager> xPackageManager; + bool bUserDisabled = false; + try + { +//Determine the repository to use + if (repository.equals(OUSTR("user"))) + xPackageManager = m_userRepository; + else if (repository.equals(OUSTR("shared"))) + xPackageManager = m_sharedRepository; + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + ::osl::MutexGuard guard(m_mutex); + //Backup the extension, in case the user cancels the action + + bUserDisabled = isUserExtensionDisabled( + identifier, fileName, xAbortChannel, xCmdEnv); + //Backup the extension, in case the user cancels the action + xExtensionBackup = backupExtension( + identifier, fileName, xPackageManager, xCmdEnv); + + //revoke the extension if it is active + Reference<deploy::XPackage> xOldExtension = + xPackageManager->getDeployedPackage( + identifier, fileName, xCmdEnv); + xOldExtension->revokePackage(xAbortChannel, xCmdEnv); + + xPackageManager->removePackage( + identifier, fileName, xAbortChannel, xCmdEnv); + activateExtension(identifier, fileName, bUserDisabled, + xAbortChannel, xCmdEnv); + } + catch (deploy::DeploymentException& ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred1 = ::cppu::getCaughtException(); + } catch (...) { + excOccurred1 = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during removeEtension"), + static_cast<OWeakObject*>(this), excOccurred1); + excOccurred1 <<= exc; + } + + if (excOccurred1.hasValue()) + { + //User aborted installation, restore the previous situation. + //Use a private AbortChannel so the user cannot interrupt. + try + { + Reference<ucb::XCommandEnvironment> tmpCmdEnv( + new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); + if (xExtensionBackup.is()) + { + Reference<deploy::XPackage> xRestored = + xPackageManager->importExtension( + xExtensionBackup, Reference<task::XAbortChannel>(), + tmpCmdEnv); + activateExtension( + identifier, fileName, bUserDisabled, Reference<task::XAbortChannel>(), + tmpCmdEnv); + + m_tmpRepository->removePackage( + dp_misc::getIdentifier(xExtensionBackup), + xExtensionBackup->getName(), xAbortChannel, xCmdEnv); + } + } + catch (...) + { + } + ::cppu::throwException(excOccurred1); + } + + if (xExtensionBackup.is()) + m_tmpRepository->removePackage( + dp_misc::getIdentifier(xExtensionBackup), + xExtensionBackup->getName(), xAbortChannel, xCmdEnv); +} + +// Only enable extensions from shared and user repository +void ExtensionManager::enableExtension( + Reference<deploy::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + if (!extension.is()) + return; + + OUString repository = extension->getRepositoryName(); + if (!repository.equals(OUSTR("user"))) + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + ::osl::MutexGuard guard(m_mutex); + + //if it is already registered or if it cannot be registered + //because it does not contain any files which need to be processed + //then there is nothing to do here + beans::Optional<beans::Ambiguous<sal_Bool> > reg = + extension->isRegistered(xAbortChannel, xCmdEnv); + if (!reg.IsPresent + || (!reg.Value.IsAmbiguous && reg.Value.Value)) + return; + } + catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), exc); + } + + uno::Any excOccurred; + try + { + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), + false, xAbortChannel, xCmdEnv); + } + catch (deploy::DeploymentException& ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (...) { + excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), excOccurred); + excOccurred <<= exc; + } + + if (excOccurred.hasValue()) + { + try + { + extension->revokePackage(Reference<task::XAbortChannel>(), xCmdEnv); + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), + true, xAbortChannel, xCmdEnv); + } + catch (...) + { + } + ::cppu::throwException(excOccurred); + } +} + +void ExtensionManager::disableExtension( + Reference<deploy::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + uno::Any excOccurred; + try + { + if (!extension.is()) + return; + + ::osl::MutexGuard guard(m_mutex); + OUString repository = extension->getRepositoryName(); + if (!repository.equals(OUSTR("user"))) + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + //if it is already registered or if it cannot be registered + //because it does not contain any files which need to be processed + //then there is nothing to do here + beans::Optional<beans::Ambiguous<sal_Bool> > reg = + extension->isRegistered(xAbortChannel, xCmdEnv); + if (!reg.IsPresent + || (!reg.Value.IsAmbiguous && !reg.Value.Value)) + return; + + extension->revokePackage(xAbortChannel, xCmdEnv); + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), + true, xAbortChannel, xCmdEnv); + } + catch (deploy::DeploymentException& ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandFailedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (ucb::CommandAbortedException & ) { + excOccurred = ::cppu::getCaughtException(); + } catch (lang::IllegalArgumentException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (uno::RuntimeException &) { + excOccurred = ::cppu::getCaughtException(); + } catch (...) { + excOccurred = ::cppu::getCaughtException(); + deploy::DeploymentException exc( + OUSTR("Extension Manager: exception during disableExtension"), + static_cast<OWeakObject*>(this), excOccurred); + excOccurred <<= exc; + } + + if (excOccurred.hasValue()) + { + try + { + activateExtension(dp_misc::getIdentifier(extension), + extension->getName(), + false, xAbortChannel, xCmdEnv); + } + catch (...) + { + } + ::cppu::throwException(excOccurred); + } +} + +uno::Sequence< Reference<deploy::XPackage> > + ExtensionManager::getDeployedExtensions( + OUString const & repository, + Reference<task::XAbortChannel> const &xAbort, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + if (repository.equals(OUSTR("user"))) + { + return m_userRepository->getDeployedPackages( + xAbort, xCmdEnv); + } + else if (repository.equals(OUSTR("shared"))) + { + return m_sharedRepository->getDeployedPackages( + xAbort, xCmdEnv); + } + else if (repository.equals(OUSTR("bundled"))) + { + return m_bundledRepository->getDeployedPackages( + xAbort, xCmdEnv); + } + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + +} + +Reference<deploy::XPackage> + ExtensionManager::getDeployedExtension( + OUString const & repository, + OUString const & identifier, + OUString const & filename, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + if (repository.equals(OUSTR("user"))) + { + return m_userRepository->getDeployedPackage( + identifier, filename, xCmdEnv); + } + else if (repository.equals(OUSTR("shared"))) + { + return m_sharedRepository->getDeployedPackage( + identifier, filename, xCmdEnv); + } + else if (repository.equals(OUSTR("bundled"))) + { + return m_bundledRepository->getDeployedPackage( + identifier, filename, xCmdEnv); + } + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); +} + +uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > + ExtensionManager::getAllExtensions( + Reference<task::XAbortChannel> const & xAbort, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > seqSeq; + try + { + id2extensions mapExt; + + uno::Sequence<Reference<deploy::XPackage> > userExt = + m_userRepository->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, userExt, OUSTR("user")); + uno::Sequence<Reference<deploy::XPackage> > sharedExt = + m_sharedRepository->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, sharedExt, OUSTR("shared")); + uno::Sequence<Reference<deploy::XPackage> > bundledExt = + m_bundledRepository->getDeployedPackages(xAbort, xCmdEnv); + addExtensionsToMap(mapExt, bundledExt, OUSTR("bundled")); + + //copy the values of the map to a vector for sorting + ::std::vector< ::std::vector<Reference<deploy::XPackage> > > + vecExtensions; + id2extensions::const_iterator mapIt = mapExt.begin(); + for (;mapIt != mapExt.end(); mapIt++) + vecExtensions.push_back(mapIt->second); + + //sort the element according to the identifier + ::std::sort(vecExtensions.begin(), vecExtensions.end(), CompIdentifiers()); + + ::std::vector< ::std::vector<Reference<deploy::XPackage> > >::const_iterator + citVecVec = vecExtensions.begin(); + sal_Int32 j = 0; + for (;citVecVec != vecExtensions.end(); citVecVec++, j++) + { + seqSeq[j] = comphelper::containerToSequence(*citVecVec); + } + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), exc); + } + + return seqSeq; +} + +void ExtensionManager::reinstallDeployedExtensions( + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, ucb::CommandAbortedException, + lang::IllegalArgumentException, uno::RuntimeException) +{ + try + { + Reference<deploy::XPackageManager> xPackageManager; + if (repository.equals(OUSTR("user"))) + xPackageManager = m_userRepository; + else if (repository.equals(OUSTR("shared"))) + xPackageManager = m_sharedRepository; + else if (repository.equals(OUSTR("bundled"))) + xPackageManager = m_bundledRepository; + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + ::osl::MutexGuard guard(m_mutex); + xPackageManager->reinstallDeployedPackages(xAbortChannel, xCmdEnv); + const uno::Sequence< Reference<deploy::XPackage> > extensions( + xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv)); + + for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos ) + { + try + { + const OUString id = dp_misc::getIdentifier(extensions[ pos ]); + const OUString fileName = extensions[ pos ]->getName(); + OSL_ASSERT(id.getLength()); + activateExtension( + id, fileName, + isUserExtensionDisabled(id, fileName, xAbortChannel, xCmdEnv), + xAbortChannel, xCmdEnv ); + } + catch (lang::DisposedException &) + { + } + } + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), exc); + } +} + +void ExtensionManager::synchronize( + OUString const & repository, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) + throw (deploy::DeploymentException, + ucb::CommandFailedException, + ucb::CommandAbortedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + Reference<deploy::XPackageManager> xPackageManager; + OUString file; + if (repository.equals(OUSTR("user"))) + { + xPackageManager = m_userRepository; + } + else if (repository.equals(OUSTR("shared"))) + { + xPackageManager = m_sharedRepository; + file = OUString ( + RTL_CONSTASCII_USTRINGPARAM( + "$SHARED_EXTENSIONS_USER/lastsynchronized")); + } + else if (repository.equals(OUSTR("bundled"))) + { + xPackageManager = m_bundledRepository; + file = OUString ( + RTL_CONSTASCII_USTRINGPARAM( + "$BUNDLED_EXTENSIONS_USER/lastsynchronized")); + } + else + throw lang::IllegalArgumentException( + OUSTR("No valid repository name provided."), + static_cast<cppu::OWeakObject*>(this), 0); + + ::osl::MutexGuard guard(m_mutex); + uno::Sequence<Reference<deploy::XPackage> > seqAddedExtensions; + uno::Sequence<Reference<deploy::XPackage> > seqRemovedExtensions; + xPackageManager->synchronize(seqAddedExtensions, seqRemovedExtensions, + xAbortChannel, xCmdEnv); + + //ToDo: optimize, only call activateExtension once per id. + //Determine which of the extensions was disabled by the user + //iterate of both sequences and add the ids of the user disabled + //to a map + for (sal_Int32 i = 0; i < seqRemovedExtensions.getLength(); i++) + { + try + { + Reference<deploy::XPackage> const & xExtension = seqRemovedExtensions[i]; + OSL_ASSERT(xExtension.is()); + const OUString id = dp_misc::getIdentifier(xExtension); + const OUString fileName = xExtension->getName(); + + bool bUserDisabled = isUserExtensionDisabled( + id, xExtension->getName(), xAbortChannel, xCmdEnv); + xExtension->revokePackage(xAbortChannel, xCmdEnv); + xPackageManager->removePackage( + id, fileName, xAbortChannel, xCmdEnv); + activateExtension( + id, fileName, bUserDisabled, xAbortChannel, xCmdEnv); + } + catch (...) + { + OSL_ENSURE(0, "Extensions Manager: synchronize"); + } + } + + for (sal_Int32 i = 0; i < seqAddedExtensions.getLength(); i++) + { + try + { + Reference<deploy::XPackage> const & xExtension = seqAddedExtensions[i]; + OSL_ASSERT(xExtension.is()); + const OUString id = dp_misc::getIdentifier(xExtension); + const OUString fileName = xExtension->getName(); + bool bUserDisabled = isUserExtensionDisabled( + id, fileName, xAbortChannel, xCmdEnv); + activateExtension( + id, fileName, bUserDisabled, xAbortChannel, xCmdEnv); + } + catch (...) + { + OSL_ENSURE(0, "Extensions Manager: synchronize"); + } + } + + //Write the lastmodified file + try { + ::rtl::Bootstrap::expandMacros(file); + ::ucbhelper::Content ucbStamp(file, xCmdEnv ); + dp_misc::erase_path( file, xCmdEnv ); + ::rtl::OString stamp("1" ); + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + ucbStamp.writeStream( xData, true /* replace existing */ ); + } + catch(...) + { + uno::Any exc(::cppu::getCaughtException()); + throw deploy::DeploymentException( + OUSTR("Failed to update") + file, + static_cast<OWeakObject*>(this), exc); + + } + } catch (deploy::DeploymentException& ) { + throw; + } catch (ucb::CommandFailedException & ) { + throw; + } catch (ucb::CommandAbortedException & ) { + throw; + } catch (lang::IllegalArgumentException &) { + throw; + } catch (uno::RuntimeException &) { + throw; + } catch (...) { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during enableExtension"), + static_cast<OWeakObject*>(this), exc); + } +} + +// Notify the user when a new extension is to be installed. This is only the +// case when one uses the system integration to install an extension (double +// clicking on .oxt file etc.)). The function must only be called if there is no +// extension with the same identifier already deployed. Then the checkUpdate +// function will inform the user that the extension is about to be installed In +// case the user cancels the installation a CommandFailed exception is +// thrown. +void ExtensionManager::checkInstall( + OUString const & displayName, + Reference<ucb::XCommandEnvironment> const & cmdEnv) +{ + uno::Any request( + deploy::InstallException( + OUSTR("Extension ") + displayName + + OUSTR(" is about to be installed."), + static_cast<OWeakObject *>(this), displayName)); + bool approve = false, abort = false; + if (! dp_misc::interactContinuation( + request, task::XInteractionApprove::static_type(), + cmdEnv, &approve, &abort )) + { + OSL_ASSERT( !approve && !abort ); + throw deploy::DeploymentException( + dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName, + static_cast<OWeakObject *>(this), request ); + } + if (abort || !approve) + throw ucb::CommandFailedException( + dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName, + static_cast<OWeakObject *>(this), request ); +} + +/* The function will make the user interaction in case there is an extension +installed with the same id. This function may only be called if there is already +an extension. +*/ +void ExtensionManager::checkUpdate( + OUString const & newVersion, + OUString const & newDisplayName, + Reference<deploy::XPackage> const & oldExtension, + Reference<ucb::XCommandEnvironment> const & xCmdEnv ) +{ + // package already deployed, interact --force: + uno::Any request( + (deploy::VersionException( + dp_misc::getResourceString( + RID_STR_PACKAGE_ALREADY_ADDED ) + newDisplayName, + static_cast<OWeakObject *>(this), newVersion, newDisplayName, + oldExtension ) ) ); + bool replace = false, abort = false; + if (! dp_misc::interactContinuation( + request, task::XInteractionApprove::static_type(), + xCmdEnv, &replace, &abort )) { + OSL_ASSERT( !replace && !abort ); + throw deploy::DeploymentException( + dp_misc::getResourceString( + RID_STR_ERROR_WHILE_ADDING) + newDisplayName, + static_cast<OWeakObject *>(this), request ); + } + if (abort || !replace) + throw ucb::CommandFailedException( + dp_misc::getResourceString( + RID_STR_PACKAGE_ALREADY_ADDED) + newDisplayName, + static_cast<OWeakObject *>(this), request ); +} + +Reference<deploy::XPackage> ExtensionManager::getTempExtension( + OUString const & url, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<ucb::XCommandEnvironment> const & /*xCmdEnv*/) + +{ + Reference<ucb::XCommandEnvironment> tmpCmdEnvA(new TmpRepositoryCommandEnv()); + Reference<deploy::XPackage> xTmpPackage = m_tmpRepository->addPackage( + url, OUString(), xAbortChannel, tmpCmdEnvA); + + if (!xTmpPackage.is()) + { + throw deploy::DeploymentException( + OUSTR("Extension Manager: Failed to create temporary XPackage for url: ") + url, + static_cast<OWeakObject*>(this), uno::Any()); + + } + return xTmpPackage; +} +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +namespace sdecl = comphelper::service_decl; +sdecl::class_<ExtensionManager> servicePIP; +extern sdecl::ServiceDecl const serviceDecl( + servicePIP, + // a private one: + "com.sun.star.comp.deployment.ExtensionManager", + "com.sun.star.comp.deployment.ExtensionManager"); + +//------------------------------------------------------------------------------ +bool singleton_entries( + uno::Reference< registry::XRegistryKey > const & xRegistryKey ) +{ + try { + uno::Reference< registry::XRegistryKey > xKey( + xRegistryKey->createKey( + serviceDecl.getImplementationName() + + // xxx todo: use future generated function to get singleton name + OUSTR("/UNO/SINGLETONS/" + "com.sun.star.deployment.ExtensionManager") ) ); + xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); + return true; + } + catch (registry::InvalidRegistryException & exc) { + (void) exc; // avoid warnings + OSL_ENSURE( 0, ::rtl::OUStringToOString( + exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); + return false; + } +} + +} // namespace dp_manager + + diff --git a/desktop/source/deployment/manager/dp_extensionmanager.hxx b/desktop/source/deployment/manager/dp_extensionmanager.hxx new file mode 100644 index 000000000000..386e2a7ceffd --- /dev/null +++ b/desktop/source/deployment/manager/dp_extensionmanager.hxx @@ -0,0 +1,287 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#if ! defined INCLUDED_DP_EXTENSIONMANAGER_H +#define INCLUDED_DP_EXTENSIONMANAGER_H + +#include "dp_manager.hrc" +#include "dp_misc.h" +#include "dp_interact.h" +#include "dp_activepackages.hxx" +#include "rtl/ref.hxx" +#include "cppuhelper/compbase1.hxx" +//#include "cppuhelper/implbase2.hxx" +#include "ucbhelper/content.hxx" +#include "com/sun/star/deployment/XPackageRegistry.hpp" +#include "com/sun/star/deployment/XPackageManager.hpp" +//#include <memory> +#include "osl/mutex.hxx" +#include <list> + + +namespace css = ::com::sun::star; + +namespace dp_manager { + +typedef ::std::hash_map< + ::rtl::OUString, + ::std::vector<css::uno::Reference<css::deployment::XPackage> >, + ::rtl::OUStringHash > id2extensions; + +class ExtensionManager : + public ::cppu::WeakImplHelper1< css::deployment::XExtensionManager > + +{ +private: + ::osl::Mutex m_mutex; + + public: + ExtensionManager( css::uno::Reference< css::uno::XComponentContext >const& xContext); + virtual ~ExtensionManager(); + + static css::uno::Sequence< ::rtl::OUString > getServiceNames(); + static ::rtl::OUString getImplName(); + +// // XInteractionHandler +// virtual void SAL_CALL handle( const uno::Reference< task::XInteractionRequest >& Request ) +// throw( uno::RuntimeException ); +// // XCommandEnvironment +// virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler() +// throw ( uno::RuntimeException ) { return static_cast<task::XInteractionHandler*>(this); }; + +// virtual uno::Reference< css_ucb::XProgressHandler > SAL_CALL getProgressHandler() +// throw ( uno::RuntimeException ) { return uno::Reference< css_ucb::XProgressHandler >(); }; +public: + // XComponent + //virtual void SAL_CALL dispose() throw (css::uno::RuntimeException); + //virtual void SAL_CALL addEventListener( + // css::uno::Reference<css::lang::XEventListener> const & xListener ) + // throw (css::uno::RuntimeException); + //virtual void SAL_CALL removeEventListener( + // css::uno::Reference<css::lang::XEventListener> const & xListener ) + // throw (css::uno::RuntimeException); + // + //// XModifyBroadcaster + //virtual void SAL_CALL addModifyListener( + // css::uno::Reference<css::util::XModifyListener> const & xListener ) + // throw (css::uno::RuntimeException); + //virtual void SAL_CALL removeModifyListener( + // css::uno::Reference<css::util::XModifyListener> const & xListener ) + // throw (css::uno::RuntimeException); + + // XPackageManager +// virtual ::rtl::OUString SAL_CALL getContext() +// throw (css::uno::RuntimeException); + virtual css::uno::Sequence< + css::uno::Reference<css::deployment::XPackageTypeInfo> > SAL_CALL + getSupportedPackageTypes(::rtl::OUString const & repository) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::task::XAbortChannel> SAL_CALL + createAbortChannel() throw (css::uno::RuntimeException); + + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL addExtension( + ::rtl::OUString const & url, ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL removeExtension( + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL enableExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL disableExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence< css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getDeployedExtensions( + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const &, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Reference< css::deployment::XPackage> + SAL_CALL getDeployedExtension( + ::rtl::OUString const & repository, + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual css::uno::Sequence< css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > > + SAL_CALL getAllExtensions( + css::uno::Reference<css::task::XAbortChannel> const &, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + + virtual void SAL_CALL reinstallDeployedExtensions( + ::rtl::OUString const & repository, + css::uno::Reference< css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + + virtual void SAL_CALL synchronize( + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + +private: + + struct ExtensionInfos + { + ::rtl::OUString identifier; + ::rtl::OUString fileName; + ::rtl::OUString displayName; + ::rtl::OUString version; + }; + + css::uno::Reference< css::uno::XComponentContext> m_xContext; + + css::uno::Reference<css::deployment::XPackageManager> m_userRepository; + css::uno::Reference<css::deployment::XPackageManager> m_sharedRepository; + css::uno::Reference<css::deployment::XPackageManager> m_bundledRepository; + css::uno::Reference<css::deployment::XPackageManager> m_tmpRepository; + + /* contains the names of all repositories (except tmp) in order of there + priority. That is, the first element is "user" follod by "shared" and + then "bundled" + */ + ::std::list< ::rtl::OUString > m_repositoryNames; + + css::uno::Reference<css::deployment::XPackage> getExtensionAndStatus( + ::rtl::OUString const & identifier, + ::rtl::OUString const & fileName, + ::rtl::OUString const & repository, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, + bool & out_bWasRegistered); + + bool isUserExtensionDisabled( + ::rtl::OUString const & identifier, + ::rtl::OUString const & fileName, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void activateExtension( + ::rtl::OUString const & identifier, + ::rtl::OUString const & fileName, + bool bUserDisabled, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + + ::std::list<css::uno::Reference<css::deployment::XPackage> > + getExtensionsWithSameId(::rtl::OUString const & identifier, + ::rtl::OUString const & fileName); + + css::uno::Reference<css::deployment::XPackage> backupExtension( + ::rtl::OUString const & identifier, ::rtl::OUString const & fileName, + css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + void checkInstall( + ::rtl::OUString const & displayName, + css::uno::Reference<css::ucb::XCommandEnvironment> const & cmdEnv); + + void checkUpdate( + ::rtl::OUString const & newVersion, + ::rtl::OUString const & newDisplayName, + css::uno::Reference<css::deployment::XPackage> const & oldExtension, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + css::uno::Reference<css::deployment::XPackage> getTempExtension( + ::rtl::OUString const & url, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + + + void addExtensionsToMap( + id2extensions & mapExt, + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > const & seqExt, + ::rtl::OUString const & repository); +}; + +} + + + + +#endif + diff --git a/desktop/source/deployment/manager/dp_manager.cxx b/desktop/source/deployment/manager/dp_manager.cxx index 3f13cb021aae..59e9f2049722 100644 --- a/desktop/source/deployment/manager/dp_manager.cxx +++ b/desktop/source/deployment/manager/dp_manager.cxx @@ -60,7 +60,12 @@ #include "com/sun/star/task/XInteractionApprove.hpp" #include "com/sun/star/ucb/UnsupportedCommandException.hpp" #include "boost/bind.hpp" +#include "tools/urlobj.hxx" + +#include "osl/file.hxx" #include <vector> +#include <list> +#include "dp_descriptioninfoset.hxx" using namespace ::dp_misc; @@ -91,6 +96,58 @@ struct MatchTempDir } }; +struct MatchExtension +{ + const ActivePackages::Data m_data; + MatchExtension(ActivePackages::Data const & data ) : m_data(data) {} + bool operator () ( OUString const & temporaryName ) const; +}; + +bool MatchExtension::operator () (OUString const & temporaryName) const +{ + //case 1: The temporary file and thus the extension folder are already + //removed. + return m_data.temporaryName.equals(temporaryName); +} + +namespace { +OUString getExtensionFolder(OUString const & parentFolder, + Reference<ucb::XCommandEnvironment> const & xCmdEnv) +{ + ::ucbhelper::Content tempFolder( + parentFolder, xCmdEnv ); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_ONLY ) ); + + OUString title; + while (xResultSet->next()) + { + title = Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString(1 /* Title */ ) ; + break; + } + return title; +} +/* adds an unencoded segment to the URL. + + Throws an com.sun.star.uno.Exception if this failed. +*/ +OUString appendURLSegement(OUString const & baseURL, OUString const & segment) +{ + OUString url; + INetURLObject inet(baseURL); + if (inet.insertName( + segment, false, INetURLObject::LAST_SEGMENT, true, + INetURLObject::ENCODE_ALL)) + url = inet.GetMainURL(INetURLObject::NO_DECODE); + else + throw Exception( + OUSTR("ExtensionManager: failed to add segment to URL"), 0); + return url; +} +} //______________________________________________________________________________ void PackageManagerImpl::initActivationLayer( Reference<XCommandEnvironment> const & xCmdEnv ) @@ -151,12 +208,23 @@ void PackageManagerImpl::initActivationLayer( // user|share: OSL_ASSERT( m_activePackages.getLength() > 0 ); m_activePackages_expanded = expandUnoRcUrl( m_activePackages ); - create_folder( 0, m_activePackages_expanded, xCmdEnv, !m_readOnly ); + m_registrationData_expanded = expandUnoRcUrl(m_registrationData); + create_folder( 0, m_activePackages_expanded, xCmdEnv, true); + + OUString dbName; + if (m_context.equals(OUSTR("user"))) + dbName = m_activePackages_expanded + OUSTR(".db"); + else + { + //Create the extension data base in the user installation + create_folder( 0, m_registrationData_expanded, xCmdEnv, true); + dbName = m_registrationData_expanded + OUSTR("/extensions.db"); + } + //The data base can always be written because it it always in the user installation m_activePackagesDB.reset( - new ActivePackages( - m_activePackages_expanded + OUSTR(".db"), m_readOnly ) ); + new ActivePackages( dbName, false ) ); - if (! m_readOnly) + if (! m_readOnly && ! m_context.equals(OUSTR("bundled"))) { // clean up activation layer, scan for zombie temp dirs: ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); @@ -169,11 +237,17 @@ void PackageManagerImpl::initActivationLayer( ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ) ); // get all temp directories: ::std::vector<OUString> tempEntries; - while (xResultSet->next()) { + while (xResultSet->next()) + { OUString title( Reference<sdbc::XRow>( xResultSet, UNO_QUERY_THROW )->getString( 1 /* Title */ ) ); + const char extensionRemoved[] = ".tmpremoved"; + if (title.endsWithAsciiL( + extensionRemoved, sizeof(extensionRemoved) - 1)) + continue; + tempEntries.push_back( ::rtl::Uri::encode( title, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, @@ -195,6 +269,9 @@ void PackageManagerImpl::initActivationLayer( false /* no throw: ignore errors */ ); erase_path( url, Reference<XCommandEnvironment>(), false /* no throw: ignore errors */ ); + //delete the xxx.tmpremoved file + erase_path(url + OUSTR("removed"), + Reference<XCommandEnvironment>(), false); } } } @@ -206,9 +283,9 @@ void PackageManagerImpl::initRegistryBackends() { if (m_registryCache.getLength() > 0) create_folder( 0, m_registryCache, - Reference<XCommandEnvironment>(), !m_readOnly ); + Reference<XCommandEnvironment>(), false); m_xRegistry.set( ::dp_registry::create( - m_context, m_registryCache, m_readOnly, + m_context, m_registryCache, false, m_xComponentContext ) ); } @@ -223,12 +300,14 @@ Reference<deployment::XPackageManager> PackageManagerImpl::create( OUString packages, logFile, stampURL; if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") )) { - that->m_activePackages = OUSTR("vnd.sun.star.expand:$UNO_" - "USER_PACKAGES_CACHE/uno_packages"); - that->m_registryCache = OUSTR("vnd.sun.star.expand:$UNO_" - "USER_PACKAGES_CACHE/registry"); - logFile = OUSTR("vnd.sun.star.expand:$UNO_" - "USER_PACKAGES_CACHE/log.txt"); + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/log.txt"); //We use the extension .sys for the file because on Windows Vista a sys //(as well as exe and dll) file //will not be written in the VirtualStore. For example if the process has no @@ -240,25 +319,42 @@ Reference<deployment::XPackageManager> PackageManagerImpl::create( //using virtualization it appears that he/she can. Then a shared extension can //be installed but is only visible for the user (because the extension is in //the virtual store). - stampURL = OUSTR("vnd.sun.star.expand:$UNO_" - "USER_PACKAGES_CACHE/stamp.sys"); + stampURL = OUSTR( + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/stamp.sys"); } else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) { - that->m_activePackages = OUSTR("vnd.sun.star.expand:$UNO_" - "SHARED_PACKAGES_CACHE/uno_packages"); - that->m_registryCache = OUSTR("vnd.sun.star.expand:$UNO_" - "SHARED_PACKAGES_CACHE/registry"); -// The current logging implementation does not work for shared, because it requires -// write access to the logfile. When two users run OOo at the same time on the same machine -// then the -// second will fail because it does not get write access. One cannot write into the -// user's home, because then people may complain that when installing shared extension -// stuff is written in their home. -// logFile = OUSTR("vnd.sun.star.expand:$UNO_" -// "SHARED_PACKAGES_CACHE/log.txt"); - //See description for stampURL for user packages. - stampURL = OUSTR("vnd.sun.star.expand:$UNO_" - "SHARED_PACKAGES_CACHE/stamp.sys"); + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/log.txt"); + stampURL = OUSTR( + "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/stamp.sys"); + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/registry"); + logFile = OUSTR( + "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/log.txt"); + //No stamp file. We assume that bundled is always readonly. It must not be + //modified from ExtensionManager but only by the installer + } + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("tmp") )) { + that->m_activePackages = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/extensions"); + that->m_registrationData = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS"); + that->m_registryCache = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/registry"); + stampURL = OUSTR( + "vnd.sun.star.expand:$TMP_EXTENSIONS/stamp.sys"); } else if (! context.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:/") )) { @@ -270,29 +366,15 @@ Reference<deployment::XPackageManager> PackageManagerImpl::create( Reference<XCommandEnvironment> xCmdEnv; try { - bool renewal = false; - + //There is no stampURL for the bundled folder if (stampURL.getLength() > 0) { - // currently no automatic renewal possible, because quickstarter - // already hinders from deleting registry directory... - #define CURRENT_STAMP "1" -// renewal = true; -// { -// ::ucbhelper::Content ucbStamp; -// if (create_ucb_content( -// &ucbStamp, stampURL, xCmdEnv, false /* no throw */ )) -// { -// OUString line; -// renewal = !readLine( &line, OUSTR(CURRENT_STAMP), ucbStamp, -// RTL_TEXTENCODING_ASCII_US ); -// } -// } - try { + //The osl file API does not allow to find out if one can write + //into a folder. Therefore we try to write a file. Then we delete + //it, so that it does not hinder uninstallation of OOo // probe writing: - erase_path( stampURL, xCmdEnv ); ::ucbhelper::Content ucbStamp( stampURL, xCmdEnv ); ::rtl::OString stamp( RTL_CONSTASCII_STRINGPARAM(CURRENT_STAMP) ); @@ -302,8 +384,15 @@ Reference<deployment::XPackageManager> PackageManagerImpl::create( reinterpret_cast<sal_Int8 const *>(stamp.getStr()), stamp.getLength() ) ) ); ucbStamp.writeStream( xData, true /* replace existing */ ); + that->m_readOnly = false; + erase_path( stampURL, xCmdEnv ); } catch (RuntimeException &) { + try { + erase_path( stampURL, xCmdEnv ); + } catch (...) + { + } throw; } catch (Exception &) { @@ -324,12 +413,6 @@ Reference<deployment::XPackageManager> PackageManagerImpl::create( xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv, that->m_xLogFile ) ); } - OSL_ENSURE( !that->m_readOnly || !renewal, - "### ought to reinstall all packages, but cannot write!" ); - if (!that->m_readOnly && renewal) // try to reinstall - that->reinstallDeployedPackages( - Reference<task::XAbortChannel>(), xCmdEnv ); - that->initRegistryBackends(); that->initActivationLayer( xCmdEnv ); @@ -484,7 +567,7 @@ OUString PackageManagerImpl::detectMediaType( try { Reference<deployment::XPackage> xPackage( m_xRegistry->bindPackage( - url, OUString(), ucbContent.getCommandEnvironment() ) ); + url, OUString(), false, ucbContent.getCommandEnvironment() ) ); const Reference<deployment::XPackageTypeInfo> xPackageType( xPackage->getPackageType() ); OSL_ASSERT( xPackageType.is() ); @@ -564,10 +647,18 @@ OUString PackageManagerImpl::insertToActivationLayer( title, NameClash::OVERWRITE )) throw RuntimeException( OUSTR("UCB transferContent() failed!"), 0 ); + // write to DB: + //bundled extensions should only be added by the synchronizeAddedExtensions + //functions. Moreover, there is no "temporary folder" for bundled extensions. + OSL_ASSERT(!m_context.equals(OUSTR("bundled"))); + DescriptionInfoset info = + dp_misc::getDescriptionInfoset( + appendURLSegement(destFolderContent.getURL(), title)); dbData->temporaryName = tempEntry; dbData->fileName = title; dbData->mediaType = mediaType; + dbData->version = info.getVersion(); return destFolder; } @@ -582,79 +673,35 @@ void PackageManagerImpl::insertToActivationLayerDB( /* The function returns true if there is an extension with the same id already installed which needs to be uninstalled, before the new extension can be installed. */ -bool PackageManagerImpl::checkUpdate( - Reference<deployment::XPackage> const & package, - Reference<XCommandEnvironment> const & origCmdEnv, - Reference<XCommandEnvironment> const & wrappedCmdEnv ) +bool PackageManagerImpl::isInstalled( + Reference<deployment::XPackage> const & package) { OUString id(dp_misc::getIdentifier(package)); OUString fn(package->getName()); - bool removeExisting = false; + bool bInstalled = false; if (m_activePackagesDB->has( id, fn )) { - // package already deployed, interact --force: - Any request( - (deployment::VersionException( - getResourceString( RID_STR_PACKAGE_ALREADY_ADDED ) + id, - static_cast<OWeakObject *>(this), package, - getDeployedPackage_( id, fn, origCmdEnv ) ) ) ); - bool replace = false, abort = false; - if (! interactContinuation( - request, task::XInteractionApprove::static_type(), - wrappedCmdEnv, &replace, &abort )) { - OSL_ASSERT( !replace && !abort ); - throw deployment::DeploymentException( - getResourceString(RID_STR_ERROR_WHILE_ADDING) + id, - static_cast<OWeakObject *>(this), request ); - } - if (abort || !replace) - throw CommandFailedException( - getResourceString(RID_STR_PACKAGE_ALREADY_ADDED) + id, - static_cast<OWeakObject *>(this), request ); - - // remove clashing package before registering new version: - removeExisting = true; + bInstalled = true; } - return removeExisting; + return bInstalled; } + +// XPackageManager //______________________________________________________________________________ -// Notify the user when a new extension is to be installed. This is only the case -//when unopkg gui extension1 is used (used by system integration (double click on .oxt -// file etc.)). In case there is already this extension then the function returns -//true. -//ToDo: Function always returns true or throws an exception -bool PackageManagerImpl::checkInstall( - Reference<deployment::XPackage> const & package, - Reference<XCommandEnvironment> const & cmdEnv) +Reference<deployment::XPackage> PackageManagerImpl::importExtension( + Reference<deployment::XPackage> const & extension, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<XCommandEnvironment> const & xCmdEnv_ ) + throw (deployment::DeploymentException, CommandFailedException, + CommandAbortedException, lang::IllegalArgumentException, + RuntimeException) { - OUString id(dp_misc::getIdentifier(package)); - if ( ! m_activePackagesDB->has( id, package->getName() )) - { - Any request( - deployment::InstallException( - OUSTR("Extension ") + id + OUSTR(" is about to be installed."), - static_cast<OWeakObject *>(this), package)); - bool approve = false, abort = false; - if (! interactContinuation( - request, task::XInteractionApprove::static_type(), - cmdEnv, &approve, &abort )) - { - OSL_ASSERT( !approve && !abort ); - throw deployment::DeploymentException( - getResourceString(RID_STR_ERROR_WHILE_ADDING) + id, - static_cast<OWeakObject *>(this), request ); - } - if (abort || !approve) - throw CommandFailedException( - getResourceString(RID_STR_ERROR_WHILE_ADDING) + id, - static_cast<OWeakObject *>(this), request ); - - } - return true; + return addPackage(extension->getURL(), OUString(), xAbortChannel, xCmdEnv_); } -// XPackageManager -//______________________________________________________________________________ +/* The function adds an extension but does not register it!!! + It may not do any user interaction. This is done in XExtensionManager::addExtension +*/ Reference<deployment::XPackage> PackageManagerImpl::addPackage( OUString const & url, OUString const & mediaType_, Reference<task::XAbortChannel> const & xAbortChannel, @@ -733,80 +780,39 @@ Reference<deployment::XPackage> PackageManagerImpl::addPackage( // bind activation package: - //Because every extension will be unpacked in a folder, which was created with a unique name - //we will always have two different XPackage objects, even if the second extension is the same. + //Because every shared/user extension will be unpacked in a folder, + //which was created with a unique name we will always have two different + //XPackage objects, even if the second extension is the same. //Therefore bindPackage does not need a guard here. xPackage = m_xRegistry->bindPackage( - makeURL( destFolder, title_enc ), mediaType, xCmdEnv ); + makeURL( destFolder, title_enc ), mediaType, false, xCmdEnv ); OSL_ASSERT( xPackage.is() ); if (xPackage.is()) { bool install = false; - OUString id; - try { - id = dp_misc::getIdentifier( xPackage ); - //checkInstall throws an exception if the user denies the installation - checkInstall(xPackage, xCmdEnv); - //checkUpdate throws an exception if the user cancels the interaction. - //For example, he may be asked if he wants to replace the older version - //with the new version. - //checkUpdates must be called before checkPrerequisites - bool bAlreadyInstalled = checkUpdate( - xPackage, xCmdEnv_, xCmdEnv ); - - if (xPackage->checkPrerequisites(xAbortChannel, xCmdEnv, bAlreadyInstalled, m_context)) + OUString const id = dp_misc::getIdentifier( xPackage ); + //This guard is used to prevent that an extension is + //installed twice. Do not use it in other functions. + //Imagine addPackage is called two times by different + //threads for the same extension quickly after each other. + //The second call would calculate "bAlreadyInstalled = + //false" if the first thread has not yet reached + //insertToActivationLayerDB. + ::osl::MutexGuard g(m_addMutex); + if (isInstalled(xPackage)) { - //This guard is used to prevent that an extension is installed twice. Do not use it in other - //functions. - //Imagine addPackage is called two times by different threads for the same extension quickly - //after each other. - //The second call would calculate "bAlreadyInstalled = false" if the first thread has not yet reached - //insertToActivationLayerDB. - ::osl::MutexGuard g(m_addMutex); - - //Holds the database data of the old extension, in case we need to roll back. - ActivePackages::Data oldDbData; - if (bAlreadyInstalled) - { - // Remove extension which is already installed. It is not removed from disk, only - // the different contents are being unregisterd. We remember the databas information - // in case we need to roll back this operation. - // When the user canceled the operation (CommandAbortedException) than the package is still - // fully functional. - // Do not guard the complete function with the getMutex - removePackage_(id, xPackage->getName(), xAbortChannel, - xCmdEnv, & oldDbData); - } - install = true; - const ::osl::MutexGuard guard( getMutex() ); - try - { - //throws CommandAbortedException if the user cancelled the installation. - xPackage->registerPackage(xAbortChannel, xCmdEnv); - } - catch(CommandAbortedException & ) - { //ToDo: Interaction so that the gui can display an appropriate string. - //See also removePackage_ - //User aborted installation, restore the previous situation. - //Use a private AbortChannel so the user cannot interrupt. - xPackage->revokePackage(new AbortChannel(), xCmdEnv); - if (bAlreadyInstalled) - { - OUString instFolder = makeURL( m_activePackages, oldDbData.temporaryName) - + OUSTR("_"); - Reference<deployment::XPackage> xOldPgk = m_xRegistry->bindPackage( - makeURL( instFolder, oldDbData.fileName ), oldDbData.mediaType, xCmdEnv ); - xOldPgk->registerPackage(new AbortChannel(), xCmdEnv); - insertToActivationLayerDB(dp_misc::getIdentifier( xOldPgk ), oldDbData); - } - throw; - } - //access to the database must be guarded. See removePackage_ - insertToActivationLayerDB(id, dbData); + //Do not guard the complete function with the getMutex + removePackage(id, xPackage->getName(), xAbortChannel, + xCmdEnv); } + install = true; + const ::osl::MutexGuard guard( getMutex() ); + //access to the database must be guarded. See removePackage_ + insertToActivationLayerDB(id, dbData); + } catch (...) { @@ -817,6 +823,7 @@ Reference<deployment::XPackage> PackageManagerImpl::addPackage( { deletePackageFromCache( xPackage, destFolder ); } + //ToDo: We should notify only if the extension is registered fireModified(); } return xPackage; @@ -861,41 +868,9 @@ void PackageManagerImpl::deletePackageFromCache( } //______________________________________________________________________________ -void PackageManagerImpl::removePackage_( - OUString const & id, OUString const & fileName, - Reference<task::XAbortChannel> const & xAbortChannel, - Reference<XCommandEnvironment> const & xCmdEnv, - ActivePackages::Data * out_dbData) -{ - Reference<deployment::XPackage> xPackage; - { - try { - const ::osl::MutexGuard guard(getMutex()); - xPackage = getDeployedPackage_(id, fileName, xCmdEnv ); - m_activePackagesDB->get(out_dbData, id, fileName); - beans::Optional< beans::Ambiguous<sal_Bool> > option( - xPackage->isRegistered( Reference<task::XAbortChannel>(), - xCmdEnv ) ); - if (!option.IsPresent || option.Value.IsAmbiguous || option.Value.Value) - xPackage->revokePackage( xAbortChannel, xCmdEnv ); - m_activePackagesDB->erase( id, fileName ); // to be removed upon next start - } - catch (CommandAbortedException &) - { - //ToDo: interaction, so that gui can show an appropriate string - //reregister the package - //Create our own XAbortChannel, so the user cannot interrupt the registration. - xPackage->registerPackage(new AbortChannel(), xCmdEnv); - throw; - } - } - try_dispose( xPackage ); -} - -//______________________________________________________________________________ void PackageManagerImpl::removePackage( OUString const & id, ::rtl::OUString const & fileName, - Reference<task::XAbortChannel> const & xAbortChannel, + Reference<task::XAbortChannel> const & /*xAbortChannel*/, Reference<XCommandEnvironment> const & xCmdEnv_ ) throw (deployment::DeploymentException, CommandFailedException, CommandAbortedException, lang::IllegalArgumentException, @@ -920,7 +895,39 @@ void PackageManagerImpl::removePackage( xCmdEnv.set( xCmdEnv_ ); try { - removePackage_( id, fileName, xAbortChannel, xCmdEnv, NULL); + Reference<deployment::XPackage> xPackage; + { + const ::osl::MutexGuard guard(getMutex()); + //Check if this extension exist and throw an IllegalArgumentException + //if it does not + xPackage = getDeployedPackage_(id, fileName, xCmdEnv ); + //Because the extension is only removed the next time the extension + //manager runs after restarting OOo, we need to indicate that a + //shared extension was "deleted". When a user starts OOo, then it + //will check if something changed in the shared repository. Based on + //the flag file it will then recognize, that the extension was + //deleted and can then update the extnesion database of the shared + //extensions in the user installation. + if (m_context.equals(OUSTR("shared"))) + { + ActivePackages::Data val; + m_activePackagesDB->get( & val, id, fileName); + OSL_ASSERT(val.temporaryName.getLength()); + OUString url(makeURL(m_activePackages_expanded, + val.temporaryName + OUSTR("removed"))); + ::ucbhelper::Content contentRemoved(url, xCmdEnv ); + ::rtl::OString stamp("1"); + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream( + ::rtl::ByteSequence( + reinterpret_cast<sal_Int8 const *>(stamp.getStr()), + stamp.getLength() ) ) ); + contentRemoved.writeStream( xData, true /* replace existing */ ); + } + m_activePackagesDB->erase( id, fileName ); // to be removed upon next start + } + try_dispose( xPackage ); + fireModified(); } catch (RuntimeException &) { @@ -955,10 +962,16 @@ OUString PackageManagerImpl::getDeployPath( ActivePackages::Data const & data ) { ::rtl::OUStringBuffer buf; buf.append( data.temporaryName ); - buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("_/") ); - buf.append( ::rtl::Uri::encode( data.fileName, rtl_UriCharClassPchar, + //The bundled extensions are not contained in an additional folder + //with a unique name. data.temporaryName contains already the + //UTF8 encoded folder name. See PackageManagerImpl::synchronize + if (!m_context.equals(OUSTR("bundled"))) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("_/") ); + buf.append( ::rtl::Uri::encode( data.fileName, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 ) ); + } return makeURL( m_activePackages, buf.makeStringAndClear() ); } @@ -998,7 +1011,7 @@ Reference<deployment::XPackage> PackageManagerImpl::getDeployedPackage_( } } return m_xRegistry->bindPackage( - getDeployPath( data ), data.mediaType, xCmdEnv ); + getDeployPath( data ), data.mediaType, false, xCmdEnv ); } //______________________________________________________________________________ @@ -1124,8 +1137,12 @@ PackageManagerImpl::getDeployedPackages( } //______________________________________________________________________________ + + +//ToDo: the function must not call registerPackage, do this in +//XExtensionManager.reinstallDeployedExtensions void PackageManagerImpl::reinstallDeployedPackages( - Reference<task::XAbortChannel> const & xAbortChannel, + Reference<task::XAbortChannel> const & /*xAbortChannel*/, Reference<XCommandEnvironment> const & xCmdEnv_ ) throw (deployment::DeploymentException, CommandFailedException, CommandAbortedException, @@ -1167,12 +1184,7 @@ void PackageManagerImpl::reinstallDeployedPackages( if (xUpdatable.is()) xUpdatable->update(); - // reregister all: - const ::osl::MutexGuard guard( getMutex() ); - const Sequence< Reference<deployment::XPackage> > packages( - getDeployedPackages_( xCmdEnv ) ); - for ( sal_Int32 pos = 0; pos < packages.getLength(); ++pos ) - packages[ pos ]->registerPackage( xAbortChannel, xCmdEnv ); + //registering is done by the ExtensionManager service. } catch (RuntimeException &) { throw; @@ -1205,6 +1217,242 @@ void PackageManagerImpl::reinstallDeployedPackages( { return m_readOnly; } +void PackageManagerImpl::synchronizeRemovedExtensions( + Sequence<Reference<deployment::XPackage> > & out_removedExtensions, + Reference<task::XAbortChannel> const & /*xAbortChannel*/, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) +{ + + //find all which are in the extension data base but which + //are removed already. + OSL_ASSERT(!m_context.equals(OUSTR("user"))); + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + + //Iterate over the contents of the extension folder and gather the + //temp file names (shared) or the folder names of the bundled extension. + ::ucbhelper::ResultSetInclude includeType = ::ucbhelper::INCLUDE_DOCUMENTS_ONLY; + if (m_context.equals(OUSTR("bundled"))) + includeType = ::ucbhelper::INCLUDE_FOLDERS_ONLY; + ::ucbhelper::Content tempFolder( + m_activePackages_expanded, xCmdEnv ); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), includeType) ); + // get all temp directories: + ::std::vector<OUString> tempEntries; + while (xResultSet->next()) { + OUString title( + Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + //also add the xxx.tmpremoved files for remove shared extensions + //this does not matter + tempEntries.push_back( ::rtl::Uri::encode( + title, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ); + } + + typedef ActivePackages::Entries::const_iterator ITActive; + bool bShared = m_context.equals(OUSTR("shared")); + ::std::vector<Reference<deployment::XPackage> > removedExtensions; + for (ITActive i = id2temp.begin(); i != id2temp.end(); i++) + { + //Get the URL to the extensions folder, first make the url for the + //shared repository including the temporary name +// OUString url(m_activePackages_expanded + OUSTR("/") +// + i->second.temporaryName); +// if (bShared) +// url = appendURLSegement(m_activePackages_expanded + OUSTR("/") +// + i->second.temporaryName + OUSTR("_"), +// i->second.fileName); + OUString url = makeURL(m_activePackages, i->second.temporaryName); + if (bShared) + url = makeURLAppendSysPathSegment( url + OUSTR("_"), i->second.fileName); + + const MatchExtension match(i->second); + bool bRemoved = false; + if (::std::find_if(tempEntries.begin(), tempEntries.end(), match) == + tempEntries.end()) + { + //The the URL from the data base entry does not exist anymore. That is the + //folder was removed. + bRemoved = true; + } + else + { + //The folder is in the extension database, but it can still be deleted. + //look for the xxx.tmpremoved file + if (bShared) + { + ::ucbhelper::Content contentRemoved; + if (create_ucb_content( + &contentRemoved, + m_activePackages_expanded + OUSTR("/") + + i->second.temporaryName + OUSTR("removed"), + Reference<XCommandEnvironment>(), false)) + { + bRemoved = true; + } + } + if (!bRemoved) + { + //There may be another extensions at the same place + dp_misc::DescriptionInfoset infoset = + dp_misc::getDescriptionInfoset(url); + OSL_ENSURE(infoset.hasDescription(), + "Extension Manager: bundled and shared extensions " + "must have an identifer and a version"); + if ( ! i->first.equals(*(infoset.getIdentifier())) + || ! i->second.version.equals(infoset.getVersion())) + { + bRemoved = true; + } + } + } + if (bRemoved) + { + Reference<deployment::XPackage> xPackage = m_xRegistry->bindPackage( + url, i->second.mediaType, true, xCmdEnv ); + OSL_ASSERT(xPackage.is()); //Even if the files are removed, we must get the object. + removedExtensions.push_back(xPackage); + } + } + out_removedExtensions = ::comphelper::containerToSequence(removedExtensions); +} + +void PackageManagerImpl::synchronizeAddedExtensions( + Sequence<Reference<deployment::XPackage> > & out_addedExtensions, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) +{ + // clean up activation layer, scan for zombie temp dirs: + ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); + + ::ucbhelper::Content tempFolder( + m_activePackages_expanded, xCmdEnv ); + Reference<sdbc::XResultSet> xResultSet( + tempFolder.createCursor( + Sequence<OUString>( &StrTitle::get(), 1 ), + ::ucbhelper::INCLUDE_FOLDERS_ONLY ) ); + + + ::std::vector<Reference<deployment::XPackage> > addedExtensions; + while (xResultSet->next()) + { + OUString title( + Reference<sdbc::XRow>( + xResultSet, UNO_QUERY_THROW )->getString( + 1 /* Title */ ) ); + //The temporary folders of user and shared have an '_' at then end. + //But the name in ActivePackages.temporaryName is saved without. + OUString title2 = title; + bool bNotBundled = !m_context.equals(OUSTR("bundled")); + if (bNotBundled) + { + OSL_ASSERT(title2[title2.getLength() -1] == '_'); + title2 = title2.copy(0, title2.getLength() -1); + } + OUString titleEncoded = ::rtl::Uri::encode( + title2, rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); + + const MatchTempDir match(titleEncoded); + if (::std::find_if( id2temp.begin(), id2temp.end(), match ) == + id2temp.end()) + { + + // The folder was not found in the data base, so it must be + // an added extension + OUString url(m_activePackages_expanded + OUSTR("/") + titleEncoded); + OUString sExtFolder; + if (bNotBundled) //that is, shared + { + //Check if the extension was not "deleted" already which is indicated + //by a xxx.tmpremoved file + ::ucbhelper::Content contentRemoved; + if (create_ucb_content(&contentRemoved, url + OUSTR("removed"), + Reference<XCommandEnvironment>(), false)) + continue; + sExtFolder = getExtensionFolder( + m_activePackages_expanded + + OUString(OUSTR("/")) + titleEncoded + OUSTR("_"), xCmdEnv); + url = appendURLSegement(m_activePackages_expanded, title); + url = appendURLSegement(url, sExtFolder); + } + Reference<deployment::XPackage> xPackage = m_xRegistry->bindPackage( + url, OUString(), false, xCmdEnv ); + if (xPackage.is()) + { + try + { + //ToDo: We need to prevent that removed shared extensions are + //added again. This can happen if there is still the folder of the + //extension. However, there is the "removed" flag file which indicates + //that the extension was removed. + //Prepare the database entry + ActivePackages::Data dbData; + //There is no temporary folder for bundled extensions. It is therefore + //an empty string. + dbData.temporaryName = titleEncoded; + if (bNotBundled) + dbData.fileName = sExtFolder; + else + dbData.fileName = title; + dbData.mediaType = xPackage->getPackageType()->getMediaType(); + dbData.version = xPackage->getVersion(); + OSL_ENSURE(dbData.version.getLength() > 0, + "Extension Manager: bundled and shared extensions must have " + "an identifier and a version"); + + OUString id = dp_misc::getIdentifier( xPackage ); + sal_Bool bAlreadyInstalled = sal_False; + if (xPackage->checkPrerequisites( + xAbortChannel, xCmdEnv, bAlreadyInstalled, m_context)) + { + const ::osl::MutexGuard guard( getMutex() ); + //access to the database must be guarded. See removePackage_ + insertToActivationLayerDB(id, dbData); + } + else + { + //ToDo: Remember that this failed. For example, the user + //could have declined the license. Then the next time the + //extension folder is investigated we do not want to + //try to install the extension again. + } + addedExtensions.push_back(xPackage); + } + catch (...) + { + } + } + } + } + out_addedExtensions = ::comphelper::containerToSequence(addedExtensions); +} + +void PackageManagerImpl::synchronize( + Sequence<Reference<deployment::XPackage> > & out_addedExtensions, + Sequence<Reference<deployment::XPackage> > & out_removedExtensions, + Reference<task::XAbortChannel> const & xAbortChannel, + Reference<css::ucb::XCommandEnvironment> const & xCmdEnv) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException) +{ + + check(); + if (m_context.equals(OUSTR("user"))) + return; + synchronizeRemovedExtensions( + out_removedExtensions, xAbortChannel, xCmdEnv); + synchronizeAddedExtensions( + out_addedExtensions, xAbortChannel, xCmdEnv); +} + //############################################################################## diff --git a/desktop/source/deployment/manager/dp_manager.h b/desktop/source/deployment/manager/dp_manager.h index ffa7252d7883..1249fe7e29d4 100644 --- a/desktop/source/deployment/manager/dp_manager.h +++ b/desktop/source/deployment/manager/dp_manager.h @@ -53,6 +53,8 @@ class PackageManagerImpl : private ::dp_misc::MutexHolder, public t_pm_helper { css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; ::rtl::OUString m_context; + ::rtl::OUString m_registrationData; + ::rtl::OUString m_registrationData_expanded; ::rtl::OUString m_registryCache; bool m_readOnly; @@ -83,16 +85,20 @@ class PackageManagerImpl : private ::dp_misc::MutexHolder, public t_pm_helper css::uno::Reference<css::deployment::XPackage> const & xPackage, ::rtl::OUString const & destFolder ); - bool checkUpdate( - css::uno::Reference<css::deployment::XPackage> const & package, - css::uno::Reference<css::ucb::XCommandEnvironment> const & origCmdEnv, - css::uno::Reference<css::ucb::XCommandEnvironment> const & - wrappedCmdEnv ); + bool isInstalled( + css::uno::Reference<css::deployment::XPackage> const & package); - bool checkInstall( - css::uno::Reference<css::deployment::XPackage> const & package, - css::uno::Reference<css::ucb::XCommandEnvironment> const & cmdEnv); + void synchronizeRemovedExtensions( + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > & + out_removedExtensions, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); + void synchronizeAddedExtensions( + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > & + out_AddedExtensions, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv); class CmdEnvWrapperImpl : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment, @@ -135,7 +141,7 @@ protected: : t_pm_helper( getMutex() ), m_xComponentContext( xComponentContext ), m_context( context ), - m_readOnly( false ) + m_readOnly( true ) {} public: @@ -180,17 +186,15 @@ public: css::lang::IllegalArgumentException, css::uno::RuntimeException); - /* Unregisters the package but does not remove it from disk. - When the operation is canceled by the user, a CommandAbortedException - is thrown. Then the package is still fully functional. - @param out_oldData - can be NULL - */ - void removePackage_( - ::rtl::OUString const & id, ::rtl::OUString const & fileName, + virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL importExtension( + css::uno::Reference<css::deployment::XPackage> const & extension, css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, - css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv, - ActivePackages::Data * out_oldData); + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); virtual void SAL_CALL removePackage( ::rtl::OUString const & id, ::rtl::OUString const & fileName, @@ -242,6 +246,17 @@ public: virtual ::sal_Bool SAL_CALL isReadOnly( ) throw (::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL synchronize( + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > & out_xAddedExtensions, + css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > & out_xRemovedExtensions, + css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, + css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw (css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::ucb::CommandAbortedException, + css::uno::RuntimeException); + }; //______________________________________________________________________________ diff --git a/desktop/source/deployment/manager/dp_managerfac.cxx b/desktop/source/deployment/manager/dp_managerfac.cxx index d4c9df1d57af..f6fde6b07d60 100644 --- a/desktop/source/deployment/manager/dp_managerfac.cxx +++ b/desktop/source/deployment/manager/dp_managerfac.cxx @@ -53,6 +53,7 @@ class PackageManagerFactoryImpl : private MutexHolder, public t_pmfac_helper Reference<deployment::XPackageManager> m_xUserMgr; Reference<deployment::XPackageManager> m_xSharedMgr; + Reference<deployment::XPackageManager> m_xBundledMgr; typedef ::std::hash_map< OUString, WeakReference<deployment::XPackageManager>, ::rtl::OUStringHash > t_string2weakref; @@ -141,6 +142,7 @@ void PackageManagerFactoryImpl::disposing() // the below are already disposed: m_xUserMgr.clear(); m_xSharedMgr.clear(); + m_xBundledMgr.clear(); } // XPackageManagerFactory @@ -172,6 +174,8 @@ PackageManagerFactoryImpl::getPackageManager( OUString const & context ) m_xUserMgr = xRet; else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) m_xSharedMgr = xRet; + else if (context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) + m_xBundledMgr = xRet; } else { diff --git a/desktop/source/deployment/manager/dp_tmprepocmdenv.cxx b/desktop/source/deployment/manager/dp_tmprepocmdenv.cxx new file mode 100644 index 000000000000..3a4a6f1d2b72 --- /dev/null +++ b/desktop/source/deployment/manager/dp_tmprepocmdenv.cxx @@ -0,0 +1,166 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "com/sun/star/deployment/VersionException.hpp" +#include "com/sun/star/deployment/LicenseIndividualAgreementException.hpp" +#include "com/sun/star/deployment/LicenseException.hpp" +#include "com/sun/star/deployment/InstallException.hpp" +#include "com/sun/star/task/XInteractionApprove.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/ucb/XCommandEnvironment.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "dp_tmprepocmdenv.hxx" + +namespace deployment = com::sun::star::deployment; +namespace lang = com::sun::star::lang; +namespace task = com::sun::star::task; +namespace ucb = com::sun::star::ucb; +namespace uno = com::sun::star::uno; +namespace css = com::sun::star; + +#define OUSTR(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +using ::com::sun::star::uno::Reference; +using ::rtl::OUString; + +namespace dp_manager { + +TmpRepositoryCommandEnv::TmpRepositoryCommandEnv() +{ +} + +TmpRepositoryCommandEnv::TmpRepositoryCommandEnv( + Reference< css::task::XInteractionHandler> const & handler) + : m_forwardHandler(handler) +{ +} + +TmpRepositoryCommandEnv::~TmpRepositoryCommandEnv() +{ +} +// XCommandEnvironment +//______________________________________________________________________________ +Reference<task::XInteractionHandler> TmpRepositoryCommandEnv::getInteractionHandler() +throw (uno::RuntimeException) +{ + return this; +} + +//______________________________________________________________________________ +Reference<ucb::XProgressHandler> TmpRepositoryCommandEnv::getProgressHandler() +throw (uno::RuntimeException) +{ + return this; +} + +// XInteractionHandler +void TmpRepositoryCommandEnv::handle( + Reference< task::XInteractionRequest> const & xRequest ) + throw (uno::RuntimeException) +{ + uno::Any request( xRequest->getRequest() ); + OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION ); + + deployment::VersionException verExc; + deployment::LicenseException licExc; + deployment::InstallException instExc; + deployment::LicenseIndividualAgreementException licAgreementExc; + + + bool approve = false; + bool abort = false; + + if ((request >>= verExc) + || (request >>= licExc) + || (request >>= instExc) + || (request >>= licAgreementExc)) + { + approve = true; + } + + if (approve == false && abort == false) + { + if (m_forwardHandler.is()) + m_forwardHandler->handle(xRequest); + else + approve = true; + } + else + { + // select: + uno::Sequence< Reference< task::XInteractionContinuation > > conts( + xRequest->getContinuations() ); + Reference< task::XInteractionContinuation > const * pConts = + conts.getConstArray(); + sal_Int32 len = conts.getLength(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + if (approve) { + Reference< task::XInteractionApprove > xInteractionApprove( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionApprove.is()) { + xInteractionApprove->select(); + // don't query again for ongoing continuations: + approve = false; + } + } + else if (abort) { + Reference< task::XInteractionAbort > xInteractionAbort( + pConts[ pos ], uno::UNO_QUERY ); + if (xInteractionAbort.is()) { + xInteractionAbort->select(); + // don't query again for ongoing continuations: + abort = false; + } + } + } + } +} + +// XProgressHandler +void TmpRepositoryCommandEnv::push( uno::Any const & /*Status*/ ) +throw (uno::RuntimeException) +{ +} + + +void TmpRepositoryCommandEnv::update( uno::Any const & /*Status */) +throw (uno::RuntimeException) +{ +} + +void TmpRepositoryCommandEnv::pop() throw (uno::RuntimeException) +{ +} + + +} // namespace dp_manager + + diff --git a/desktop/source/deployment/manager/dp_tmprepocmdenv.hxx b/desktop/source/deployment/manager/dp_tmprepocmdenv.hxx new file mode 100644 index 000000000000..22111bc1e081 --- /dev/null +++ b/desktop/source/deployment/manager/dp_tmprepocmdenv.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_TMPREPOSITORYCOMMANDENVIRONMENT_HXX +#define INCLUDED_DP_TMPREPOSITORYCOMMANDENVIRONMENT_HXX + + +#include "cppuhelper/compbase3.hxx" +//#include "cppuhelper/implbase2.hxx" +#include "ucbhelper/content.hxx" + + + +namespace css = ::com::sun::star; + +namespace dp_manager { + +/** + This command environment is to be used when an extension is temporarily + stored in the "tmp" repository. It prevents all kind of user interaction. + */ +class TmpRepositoryCommandEnv + : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment, + css::task::XInteractionHandler, + css::ucb::XProgressHandler > +{ + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::task::XInteractionHandler> m_forwardHandler; +public: + virtual ~TmpRepositoryCommandEnv(); + TmpRepositoryCommandEnv(); + TmpRepositoryCommandEnv( + css::uno::Reference< css::task::XInteractionHandler> const & handler); + + // XCommandEnvironment + virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (css::uno::RuntimeException); + virtual css::uno::Reference<css::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (css::uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); + + // XProgressHandler + virtual void SAL_CALL push( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL update( css::uno::Any const & Status ) + throw (css::uno::RuntimeException); + virtual void SAL_CALL pop() throw (css::uno::RuntimeException); +}; + +} + + + + +#endif + diff --git a/desktop/source/deployment/manager/makefile.mk b/desktop/source/deployment/manager/makefile.mk index a9ff47881fc3..cb99325bde52 100644 --- a/desktop/source/deployment/manager/makefile.mk +++ b/desktop/source/deployment/manager/makefile.mk @@ -45,7 +45,9 @@ SLOFILES = \ $(SLO)$/dp_activepackages.obj \ $(SLO)$/dp_manager.obj \ $(SLO)$/dp_managerfac.obj \ - $(SLO)$/dp_informationprovider.obj + $(SLO)$/dp_informationprovider.obj \ + $(SLO)$/dp_extensionmanager.obj \ + $(SLO)$/dp_tmprepocmdenv.obj .INCLUDE : ..$/target.pmk .INCLUDE : target.mk diff --git a/desktop/source/deployment/misc/dp_descriptioninfoset.cxx b/desktop/source/deployment/misc/dp_descriptioninfoset.cxx index 28f45918e9e2..d97b400f4609 100644 --- a/desktop/source/deployment/misc/dp_descriptioninfoset.cxx +++ b/desktop/source/deployment/misc/dp_descriptioninfoset.cxx @@ -35,6 +35,7 @@ #include "comphelper/sequence.hxx" #include "comphelper/makesequence.hxx" +#include "comphelper/processfactory.hxx" #include "boost/optional.hpp" #include "com/sun/star/beans/Optional.hpp" #include "com/sun/star/lang/XMultiComponentFactory.hpp" @@ -47,17 +48,23 @@ #include "com/sun/star/xml/dom/DOMException.hpp" #include "com/sun/star/xml/dom/XNode.hpp" #include "com/sun/star/xml/dom/XNodeList.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" #include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" #include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" #include "cppuhelper/weak.hxx" +#include "cppuhelper/exc_hlp.hxx" #include "rtl/ustring.h" #include "rtl/ustring.hxx" #include "sal/types.h" - +#include "ucbhelper/content.hxx" namespace { namespace css = ::com::sun::star; +using css::uno::Reference; +using ::rtl::OUString; class EmptyNodeList: public ::cppu::WeakImplHelper1< css::xml::dom::XNodeList > { @@ -110,10 +117,251 @@ css::uno::Reference< css::xml::dom::XNode > EmptyNodeList::item(::sal_Int32) } } +/**The class uses the UCB to access the description.xml file in an + extension. The UCB must have been initialized already. It also + requires that the extension has already be unzipped to a particular + location. + */ +class ExtensionDescription +{ +public: + /**throws an exception if the description.xml is not + available, cannot be read, does not contain the expected data, + or any other error occured. Therefore it shoult only be used with + new extensions. + + Throws com::sun::star::uno::RuntimeException, + com::sun::star::deployment::DeploymentException, + dp_registry::backend::bundle::NoDescriptionException. + */ + ExtensionDescription( + const css::uno::Reference<css::uno::XComponentContext>& xContext, + const ::rtl::OUString& installDir, + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv); + + ~ExtensionDescription(); + + css::uno::Reference<css::xml::dom::XNode> getRootElement() const + { + return m_xRoot; + } + + ::rtl::OUString getExtensionRootUrl() const + { + return m_sExtensionRootUrl; + } + + +private: + css::uno::Reference<css::xml::dom::XNode> m_xRoot; + ::rtl::OUString m_sExtensionRootUrl; +}; + +class NoDescriptionException +{ +}; + +class FileDoesNotExistFilter + : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment, + css::task::XInteractionHandler > + +{ + //css::uno::Reference<css::task::XInteractionHandler> m_xHandler; + bool m_bExist; + css::uno::Reference< css::ucb::XCommandEnvironment > m_xCommandEnv; + +public: + virtual ~FileDoesNotExistFilter(); + FileDoesNotExistFilter( + const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv); + + bool exist(); + // XCommandEnvironment + virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL + getInteractionHandler() throw (css::uno::RuntimeException); + virtual css::uno::Reference<css::ucb::XProgressHandler > + SAL_CALL getProgressHandler() throw (css::uno::RuntimeException); + + // XInteractionHandler + virtual void SAL_CALL handle( + css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException); +}; + +ExtensionDescription::ExtensionDescription( + const Reference<css::uno::XComponentContext>& xContext, + const OUString& installDir, + const Reference< css::ucb::XCommandEnvironment >& xCmdEnv) +{ + try { + m_sExtensionRootUrl = installDir; + //may throw ::com::sun::star::ucb::ContentCreationException + //If there is no description.xml then ucb will start an interaction which + //brings up a dialog.We want to prevent this. Therefore we wrap the xCmdEnv + //and filter the respective exception out. + OUString sDescriptionUri(installDir + OUSTR("/description.xml")); + Reference<css::ucb::XCommandEnvironment> xFilter = + static_cast<css::ucb::XCommandEnvironment*>( + new FileDoesNotExistFilter(xCmdEnv)); + ::ucbhelper::Content descContent(sDescriptionUri, xFilter); + + //throws an com::sun::star::uno::Exception if the file is not available + Reference<css::io::XInputStream> xIn; + try + { //throws com.sun.star.ucb.InteractiveAugmentedIOException + xIn = descContent.openStream(); + } + catch (css::uno::Exception& ) + { + if ( ! static_cast<FileDoesNotExistFilter*>(xFilter.get())->exist()) + throw NoDescriptionException(); + throw; + } + if (!xIn.is()) + { + throw css::uno::Exception( + OUSTR("Could not get XInputStream for description.xml of extension ") + + sDescriptionUri, 0); + } + + //get root node of description.xml + Reference<css::xml::dom::XDocumentBuilder> xDocBuilder( + xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.dom.DocumentBuilder"), + xContext ), css::uno::UNO_QUERY); + if (!xDocBuilder.is()) + throw css::uno::Exception(OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0); + + if (xDocBuilder->isNamespaceAware() == sal_False) + { + throw css::uno::Exception( + OUSTR("Service com.sun.star.xml.dom.DocumentBuilder is not namespace aware."), 0); + } + + Reference<css::xml::dom::XDocument> xDoc = xDocBuilder->parse(xIn); + if (!xDoc.is()) + { + throw css::uno::Exception(sDescriptionUri + OUSTR(" contains data which cannot be parsed. "), 0); + } + + //check for proper root element and namespace + Reference<css::xml::dom::XElement> xRoot = xDoc->getDocumentElement(); + if (!xRoot.is()) + { + throw css::uno::Exception( + sDescriptionUri + OUSTR(" contains no root element."), 0); + } + + if ( ! xRoot->getTagName().equals(OUSTR("description"))) + { + throw css::uno::Exception( + sDescriptionUri + OUSTR(" does not contain the root element <description>."), 0); + } + + m_xRoot = Reference<css::xml::dom::XNode>( + xRoot, css::uno::UNO_QUERY_THROW); + OUString nsDescription = xRoot->getNamespaceURI(); + + //check if this namespace is supported + if ( ! nsDescription.equals(OUSTR("http://openoffice.org/extensions/description/2006"))) + { + throw css::uno::Exception(sDescriptionUri + OUSTR(" contains a root element with an unsupported namespace. "), 0); + } + } catch (css::uno::RuntimeException &) { + throw; + } catch (css::deployment::DeploymentException &) { + throw; + } catch (css::uno::Exception & e) { + css::uno::Any a(cppu::getCaughtException()); + throw css::deployment::DeploymentException( + e.Message, Reference< css::uno::XInterface >(), a); + } +} + +ExtensionDescription::~ExtensionDescription() +{ +} + +//====================================================================== +FileDoesNotExistFilter::FileDoesNotExistFilter( + const Reference< css::ucb::XCommandEnvironment >& xCmdEnv): + m_bExist(true), m_xCommandEnv(xCmdEnv) +{} + +FileDoesNotExistFilter::~FileDoesNotExistFilter() +{ +}; + +bool FileDoesNotExistFilter::exist() +{ + return m_bExist; +} + // XCommandEnvironment +Reference<css::task::XInteractionHandler > + FileDoesNotExistFilter::getInteractionHandler() throw (css::uno::RuntimeException) +{ + return static_cast<css::task::XInteractionHandler*>(this); +} + +Reference<css::ucb::XProgressHandler > + FileDoesNotExistFilter::getProgressHandler() throw (css::uno::RuntimeException) +{ + return m_xCommandEnv.is() + ? m_xCommandEnv->getProgressHandler() + : Reference<css::ucb::XProgressHandler>(); +} + +// XInteractionHandler +//If the interaction was caused by a non-existing file which is specified in the ctor +//of FileDoesNotExistFilter, then we do nothing +void FileDoesNotExistFilter::handle( + Reference<css::task::XInteractionRequest > const & xRequest ) + throw (css::uno::RuntimeException) +{ + css::uno::Any request( xRequest->getRequest() ); + + css::ucb::InteractiveAugmentedIOException ioexc; + if ((request>>= ioexc) && ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING ) + { + m_bExist = false; + return; + } + Reference<css::task::XInteractionHandler> xInteraction; + if (m_xCommandEnv.is()) { + xInteraction = m_xCommandEnv->getInteractionHandler(); + } + if (xInteraction.is()) { + xInteraction->handle(xRequest); + } +} + } namespace dp_misc { +DescriptionInfoset getDescriptionInfoset(OUString const & sExtensionFolderURL) +{ + Reference< css::xml::dom::XNode > root; + Reference<css::uno::XComponentContext> context = + comphelper_getProcessComponentContext(); + OSL_ASSERT(context.is()); + try { + root = + ExtensionDescription( + context, sExtensionFolderURL, + Reference< css::ucb::XCommandEnvironment >()). + getRootElement(); + } catch (NoDescriptionException &) { + } catch (css::deployment::DeploymentException & e) { + throw css::uno::RuntimeException( + (OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.deployment.DeploymentException: ")) + + e.Message), 0); + } + return DescriptionInfoset(context, root); +} + DescriptionInfoset::DescriptionInfoset( css::uno::Reference< css::uno::XComponentContext > const & context, css::uno::Reference< css::xml::dom::XNode > const & element): diff --git a/desktop/source/deployment/misc/dp_misc.cxx b/desktop/source/deployment/misc/dp_misc.cxx index 3ed2d554b59f..1f1fde7ca7bf 100644 --- a/desktop/source/deployment/misc/dp_misc.cxx +++ b/desktop/source/deployment/misc/dp_misc.cxx @@ -197,6 +197,19 @@ OUString makeURL( OUString const & baseURL, OUString const & relPath_ ) return buf.makeStringAndClear(); } +OUString makeURLAppendSysPathSegment( OUString const & baseURL, OUString const & relPath_ ) +{ + OUString segment = relPath_; + OSL_ASSERT(segment.indexOf(static_cast<sal_Unicode>('/')) == -1); + + ::rtl::Uri::encode( + segment, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8); + return makeURL(baseURL, segment); +} + + + //============================================================================== OUString expandUnoRcTerm( OUString const & term_ ) { @@ -467,4 +480,22 @@ void TRACE(::rtl::OString const & sText) #endif } +bool hasExtensionRepositoryChanged(::rtl::OUString const & repository) +{ + if (repository.equals(OUSTR("shared"))) + { + //get the extensions folder + OUString folder(RTL_CONSTASCII_USTRINGPARAM("BUNDLED_EXTENSIONS")); + ::rtl::Bootstrap::expandMacros(folder); + } + else if (repository.equals(OUSTR("bundled"))) + { + } + else + throw lang::IllegalArgumentException( + OUSTR("Invalid repository name."), 0, 0); + + return false; +} + } diff --git a/desktop/source/deployment/misc/dp_version.cxx b/desktop/source/deployment/misc/dp_version.cxx index 1668ebe4a0b7..c0da0533b54c 100644 --- a/desktop/source/deployment/misc/dp_version.cxx +++ b/desktop/source/deployment/misc/dp_version.cxx @@ -70,11 +70,5 @@ namespace dp_misc { return ::dp_misc::EQUAL; } -::dp_misc::Order comparePackageVersions( - css::uno::Reference< css::deployment::XPackage > const & package1, - css::uno::Reference< css::deployment::XPackage > const & package2) -{ - return compareVersions(package1->getVersion(), package2->getVersion()); -} } diff --git a/desktop/source/deployment/misc/makefile.mk b/desktop/source/deployment/misc/makefile.mk index e191169202fd..9a7f1d62e001 100644 --- a/desktop/source/deployment/misc/makefile.mk +++ b/desktop/source/deployment/misc/makefile.mk @@ -75,7 +75,8 @@ SHL1STDLIBS = \ $(TOOLSLIB) \ $(UCBHELPERLIB) \ $(UNOTOOLSLIB) \ - $(XMLSCRIPTLIB) + $(XMLSCRIPTLIB) \ + $(COMPHELPERLIB) .IF "$(GUI)"=="OS2" SHL1IMPLIB = ideploymentmisc$(DLLPOSTFIX) LIB1TARGET = $(SLB)$/_deplmisc.lib diff --git a/desktop/source/deployment/registry/component/dp_compbackenddb.cxx b/desktop/source/deployment/registry/component/dp_compbackenddb.cxx new file mode 100644 index 000000000000..edaf642a2ab1 --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_compbackenddb.cxx @@ -0,0 +1,142 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_compbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/component-registry/2010" +#define ROOT_ELEMENT_NAME "component-backend-db" + +namespace dp_registry { +namespace backend { +namespace component { + +ComponentBackendDb::ComponentBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString ComponentBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ComponentBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +void ComponentBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + +#if OSL_DEBUG_LEVEL > 0 + //There must not be yet an entry with the same url + OUString sExpression( + OUSTR("reg:component[@url = \"") + url + OUSTR("\"]")); + Reference<css::xml::dom::XNode> _extensionNode = + getXPathAPI()->selectSingleNode(root, sExpression); + OSL_ASSERT(! _extensionNode.is()); +#endif + Reference<css::xml::dom::XElement> componentElement( + doc->createElement(OUSTR("component"))); + + componentElement->setAttribute(OUSTR("url"), url); + + Reference<css::xml::dom::XNode> componentNode( + componentElement, UNO_QUERY_THROW); + + root->appendChild(componentNode); + + Reference<css::xml::dom::XNode> javaTypeLibNode( + doc->createElement(OUSTR("java-type-library")), UNO_QUERY_THROW); + + componentNode->appendChild(javaTypeLibNode); + + Reference<css::xml::dom::XNode> javaTypeLibValueNode( + doc->createTextNode(OUString::valueOf((sal_Bool) data.javaTypeLibrary)), + UNO_QUERY_THROW); + javaTypeLibNode->appendChild(javaTypeLibValueNode); + + writeSimpleList( + data.implementationNames, + OUSTR("implementation-names"), + OUSTR("name"), + componentNode); + + writeVectorOfPair( + data.singletons, + OUSTR("singletons"), + OUSTR("item"), + OUSTR("key"), + OUSTR("value"), + componentNode); + + save(); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +void ComponentBackendDb::removeEntry(::rtl::OUString const & url) +{ + OUString sExpression( + OUSTR("reg:component[@url = \"") + url + OUSTR("\"]")); + removeElement(sExpression); +} + + + +} // namespace bundle +} // namespace backend +} // namespace dp_registry + diff --git a/desktop/source/deployment/registry/component/dp_compbackenddb.hxx b/desktop/source/deployment/registry/component/dp_compbackenddb.hxx new file mode 100644 index 000000000000..0dde24beed3f --- /dev/null +++ b/desktop/source/deployment/registry/component/dp_compbackenddb.hxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_COMPBACKENDDB_HXX +#define INCLUDED_DP_COMPBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "rtl/string.hxx" +#include <vector> +#include <list> +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { +namespace component { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + The format looks like this: + +<?xml version="1.0"?> +<component-backend-db xmlns="http://openoffice.org/extensionmanager/component-registry/2010"> + <component url="vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages/5CD5.tmp_/leaves1.oxt/extensionoptions.jar"> + <java-type-library>true</java-type-library> + <implementation-names> + <name>com.sun.star.comp.extensionoptions.OptionsEventHandler$_OptionsEventHandler</name> + ... + </implementation-names> + <singletons> + <item> + <key>com.sun.star.java.theJavaVirtualMachine</key> + <value>com.sun.star.java.JavaVirtualMachine</value> + </item> + ... + </singletons> + </component> + + <component ...> + ... +</component-backend-db> + */ +class ComponentBackendDb: public dp_registry::backend::BackendDb +{ +public: + struct Data + { + Data(): javaTypeLibrary(false) {}; + + ::std::list< ::rtl::OUString> implementationNames; + /* every singleton has a key and a value + */ + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString> >singletons; + bool javaTypeLibrary; + }; + +public: + + ComponentBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + void removeEntry(::rtl::OUString const & url); + + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getRootElementName(); + + +}; + + + +} +} +} +#endif + diff --git a/desktop/source/deployment/registry/component/dp_component.cxx b/desktop/source/deployment/registry/component/dp_component.cxx index e6781e2a1746..e4e5efff9e81 100644 --- a/desktop/source/deployment/registry/component/dp_component.cxx +++ b/desktop/source/deployment/registry/component/dp_component.cxx @@ -58,7 +58,7 @@ #include <vector> #include <memory> #include <algorithm> - +#include "dp_compbackenddb.hxx" using namespace ::dp_misc; using namespace ::com::sun::star; @@ -74,6 +74,9 @@ namespace { typedef ::std::list<OUString> t_stringlist; typedef ::std::vector< ::std::pair<OUString, OUString> > t_stringpairvec; +#define IMPLEMENTATION_NAME "com.sun.star.comp.deployment.component.PackageRegistryBackend" +inline OUString makeRcTerm( OUString const & url ); + /** return a vector of bootstrap variables which have been provided as command arguments. */ @@ -153,9 +156,9 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend ::rtl::Reference<PackageRegistryBackend> const & myBackend, OUString const & url, OUString const & name, Reference<deployment::XPackageTypeInfo> const & xPackageType, - OUString const & loader ) + OUString const & loader, bool bUseDb ) : Package( myBackend, url, name, name /* display-name */, - xPackageType ), + xPackageType, bUseDb ), m_loader( loader ), m_registered( REG_UNINIT ) {} @@ -187,9 +190,9 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend ::rtl::Reference<PackageRegistryBackend> const & myBackend, OUString const & url, OUString const & name, Reference<deployment::XPackageTypeInfo> const & xPackageType, - bool jarFile ) + bool jarFile, bool bUseDb ) : Package( myBackend, url, name, name /* display-name */, - xPackageType ), + xPackageType, bUseDb), m_jarFile( jarFile ) {} }; @@ -212,6 +215,7 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend // PackageRegistryBackend virtual Reference<deployment::XPackage> bindPackage_( OUString const & url, OUString const & mediaType, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ); virtual void SAL_CALL disposing(); @@ -230,6 +234,12 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend OUString m_commonRDB_RO; OUString m_nativeRDB_RO; + std::auto_ptr<ComponentBackendDb> m_backendDb; + + void addDataToDb(OUString const & url, ComponentBackendDb::Data const & data); + void deleteDataFromDb(OUString const & url); + + //These rdbs are for writing new service entries. The rdb files are copies //which are created when services are added or removed. Reference<registry::XSimpleRegistry> m_xCommonRDB; @@ -371,59 +381,59 @@ void BackendImpl::disposing() } } + void BackendImpl::initServiceRdbFiles() { const Reference<XCommandEnvironment> xCmdEnv; - if (! m_readOnly) + + ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv ); + ::ucbhelper::Content oldRDB; + // switch common rdb: + if (m_commonRDB_RO.getLength() > 0) { - ::ucbhelper::Content cacheDir( getCachePath(), xCmdEnv ); - ::ucbhelper::Content oldRDB; - // switch common rdb: - if (m_commonRDB_RO.getLength() > 0) - { - create_ucb_content( - &oldRDB, makeURL( getCachePath(), m_commonRDB_RO), - xCmdEnv, false /* no throw */ ); - } - m_commonRDB = m_commonRDB_RO.equalsAsciiL( - RTL_CONSTASCII_STRINGPARAM("common.rdb") ) - ? OUSTR("common_.rdb") : OUSTR("common.rdb"); - if (oldRDB.get().is()) - { - if (! cacheDir.transferContent( + create_ucb_content( + &oldRDB, makeURL( getCachePath(), m_commonRDB_RO), + xCmdEnv, false /* no throw */ ); + } + m_commonRDB = m_commonRDB_RO.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("common.rdb") ) + ? OUSTR("common_.rdb") : OUSTR("common.rdb"); + if (oldRDB.get().is()) + { + if (! cacheDir.transferContent( oldRDB, ::ucbhelper::InsertOperation_COPY, m_commonRDB, NameClash::OVERWRITE )) - { - - throw RuntimeException( - OUSTR("UCB transferContent() failed!"), 0 ); - } - oldRDB = ::ucbhelper::Content(); - } - // switch native rdb: - if (m_nativeRDB_RO.getLength() > 0) { - create_ucb_content( - &oldRDB, makeURL(getCachePath(), m_nativeRDB_RO), - xCmdEnv, false /* no throw */ ); + + throw RuntimeException( + OUSTR("UCB transferContent() failed!"), 0 ); } - const OUString plt_rdb( getPlatformString() + OUSTR(".rdb") ); - const OUString plt_rdb_( getPlatformString() + OUSTR("_.rdb") ); - m_nativeRDB = m_nativeRDB_RO.equals( plt_rdb ) ? plt_rdb_ : plt_rdb; - if (oldRDB.get().is()) - { - if (! cacheDir.transferContent( + oldRDB = ::ucbhelper::Content(); + } + // switch native rdb: + if (m_nativeRDB_RO.getLength() > 0) + { + create_ucb_content( + &oldRDB, makeURL(getCachePath(), m_nativeRDB_RO), + xCmdEnv, false /* no throw */ ); + } + const OUString plt_rdb( getPlatformString() + OUSTR(".rdb") ); + const OUString plt_rdb_( getPlatformString() + OUSTR("_.rdb") ); + m_nativeRDB = m_nativeRDB_RO.equals( plt_rdb ) ? plt_rdb_ : plt_rdb; + if (oldRDB.get().is()) + { + if (! cacheDir.transferContent( oldRDB, ::ucbhelper::InsertOperation_COPY, m_nativeRDB, NameClash::OVERWRITE )) - throw RuntimeException( + throw RuntimeException( OUSTR("UCB transferContent() failed!"), 0 ); - } - - // UNO is bootstrapped, flush for next process start: - m_unorc_modified = true; - unorc_flush( Reference<XCommandEnvironment>() ); } + // UNO is bootstrapped, flush for next process start: + m_unorc_modified = true; + unorc_flush( Reference<XCommandEnvironment>() ); + + // common rdb for java, native rdb for shared lib components if (m_commonRDB.getLength() > 0) { m_xCommonRDB.set( @@ -433,7 +443,8 @@ void BackendImpl::initServiceRdbFiles() m_xComponentContext ), UNO_QUERY_THROW ); m_xCommonRDB->open( makeURL( expandUnoRcUrl(getCachePath()), m_commonRDB ), - m_readOnly, !m_readOnly ); +// m_readOnly, !m_readOnly ); + false, true); } if (m_nativeRDB.getLength() > 0) { m_xNativeRDB.set( @@ -443,7 +454,8 @@ void BackendImpl::initServiceRdbFiles() m_xComponentContext ), UNO_QUERY_THROW ); m_xNativeRDB->open( makeURL( expandUnoRcUrl(getCachePath()), m_nativeRDB ), - m_readOnly, !m_readOnly ); +// m_readOnly, !m_readOnly ); + false, true); } } @@ -562,9 +574,25 @@ BackendImpl::BackendImpl( initServiceRdbFiles_RO(); + OUString dbFile = makeURL(getCachePath(), OUSTR("backenddb.xml")); + m_backendDb.reset( + new ComponentBackendDb(getComponentContext(), dbFile)); } } +void BackendImpl::addDataToDb( + OUString const & url, ComponentBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +void BackendImpl::deleteDataFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + // XPackageRegistry //______________________________________________________________________________ Sequence< Reference<deployment::XPackageTypeInfo> > @@ -577,6 +605,7 @@ BackendImpl::getSupportedPackageTypes() throw (RuntimeException) //______________________________________________________________________________ Reference<deployment::XPackage> BackendImpl::bindPackage_( OUString const & url, OUString const & mediaType_, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) { OUString mediaType(mediaType_); @@ -649,17 +678,20 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( if (value.EqualsIgnoreCaseAscii("native")) { return new BackendImpl::ComponentPackageImpl( this, url, name, m_xDynComponentTypeInfo, - OUSTR("com.sun.star.loader.SharedLibrary") ); + OUSTR("com.sun.star.loader.SharedLibrary"), + bNoFileAccess ); } if (value.EqualsIgnoreCaseAscii("Java")) { return new BackendImpl::ComponentPackageImpl( this, url, name, m_xJavaComponentTypeInfo, - OUSTR("com.sun.star.loader.Java2") ); + OUSTR("com.sun.star.loader.Java2"), + bNoFileAccess ); } if (value.EqualsIgnoreCaseAscii("Python")) { return new BackendImpl::ComponentPackageImpl( this, url, name, m_xPythonComponentTypeInfo, - OUSTR("com.sun.star.loader.Python") ); + OUSTR("com.sun.star.loader.Python"), + bNoFileAccess); } } } @@ -675,12 +707,12 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( { return new BackendImpl::TypelibraryPackageImpl( this, url, name, m_xRDBTypelibTypeInfo, - false /* rdb */ ); + false /* rdb */, bNoFileAccess); } if (value.EqualsIgnoreCaseAscii("Java")) { return new BackendImpl::TypelibraryPackageImpl( this, url, name, m_xJavaTypelibTypeInfo, - true /* jar */ ); + true /* jar */, bNoFileAccess); } } } @@ -785,18 +817,11 @@ void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv ) return; ::rtl::OStringBuffer buf; - // UNO_USER_PACKAGES_CACHE, UNO_SHARED_PACKAGES_CACHE have to be resolved - // locally: - if (m_eContext == CONTEXT_USER) { - buf.append( RTL_CONSTASCII_STRINGPARAM( - "UNO_USER_PACKAGES_CACHE=$ORIGIN/../..") ); - } - else if (m_eContext == CONTEXT_SHARED) { - buf.append( RTL_CONSTASCII_STRINGPARAM( - "UNO_SHARED_PACKAGES_CACHE=$ORIGIN/../..") ); - } - else - OSL_ASSERT(0); + + buf.append(RTL_CONSTASCII_STRINGPARAM("ORIGIN=")); + OUString sOrigin = makeRcTerm(m_cachePath); + ::rtl::OString osOrigin = ::rtl::OUStringToOString(sOrigin, RTL_TEXTENCODING_UTF8); + buf.append(osOrigin); buf.append(LF); if (! m_jar_typelibs.empty()) @@ -852,6 +877,9 @@ void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv ) // write native rc: ::rtl::OStringBuffer buf2; + buf2.append(RTL_CONSTASCII_STRINGPARAM("ORIGIN=")); + buf2.append(osOrigin); + buf2.append(LF); buf2.append( RTL_CONSTASCII_STRINGPARAM("UNO_SERVICES=?$ORIGIN/") ); buf2.append( ::rtl::OUStringToOString( sNativeRDB, RTL_TEXTENCODING_ASCII_US ) ); @@ -886,7 +914,7 @@ void BackendImpl::unorc_flush( Reference<XCommandEnvironment> const & xCmdEnv ) inline OUString makeRcTerm( OUString const & url ) { OSL_ASSERT( url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM( - "vnd.sun.star.expand:") ) ); + "vnd.sun.star.expand:") ) ); if (url.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.expand:") )) { // cut protocol: OUString rcterm( url.copy( sizeof ("vnd.sun.star.expand:") - 1 ) ); @@ -1186,6 +1214,8 @@ void BackendImpl::ComponentPackageImpl::processPackage_( bool isJavaTypelib = java && !jarManifestHeaderPresent( url, OUSTR("UNO-Type-Path"), xCmdEnv ); + ComponentBackendDb::Data data; + data.javaTypeLibrary = isJavaTypelib; if (doRegisterPackage) { if (! m_xRemoteContext.is()) { @@ -1210,12 +1240,17 @@ void BackendImpl::ComponentPackageImpl::processPackage_( //only write to unorc if registration was successful. //It may fail if there is no suitable java. if (isJavaTypelib) + { that->addToUnoRc( java, url, xCmdEnv ); + data.javaTypeLibrary = true; + } t_stringlist implNames; t_stringpairvec singletons; - const Reference<loader::XImplementationLoader> xLoader( + const Reference<loader::XImplementationLoader> xLoader( getComponentInfo( &implNames, &singletons, m_xRemoteContext ) ); + data.implementationNames = implNames; + data.singletons = singletons; // factories live insertion: const Reference<container::XSet> xSet( @@ -1280,6 +1315,7 @@ void BackendImpl::ComponentPackageImpl::processPackage_( } m_registered = REG_REGISTERED; + getMyBackend()->addDataToDb(url, data); } else // revokePackage() { @@ -1364,6 +1400,7 @@ void BackendImpl::ComponentPackageImpl::processPackage_( } m_registered = REG_NOT_REGISTERED; + getMyBackend()->deleteDataFromDb(url); } } @@ -1490,7 +1527,7 @@ namespace sdecl = comphelper::service_decl; sdecl::class_<BackendImpl, sdecl::with_args<true> > serviceBI; extern sdecl::ServiceDecl const serviceDecl( serviceBI, - "com.sun.star.comp.deployment.component.PackageRegistryBackend", + IMPLEMENTATION_NAME, BACKEND_SERVICE_NAME ); } // namespace component diff --git a/desktop/source/deployment/registry/component/makefile.mk b/desktop/source/deployment/registry/component/makefile.mk index 4c4016f9bf6c..b7ee5c203cd5 100644 --- a/desktop/source/deployment/registry/component/makefile.mk +++ b/desktop/source/deployment/registry/component/makefile.mk @@ -40,7 +40,8 @@ SRC1FILES = \ INCPRE += ..$/..$/inc SLOFILES = \ - $(SLO)$/dp_component.obj + $(SLO)$/dp_component.obj \ + $(SLO)$/dp_compbackenddb.obj .INCLUDE : ..$/..$/target.pmk .INCLUDE : target.mk diff --git a/desktop/source/deployment/registry/configuration/dp_configuration.cxx b/desktop/source/deployment/registry/configuration/dp_configuration.cxx index 460ba5e9fed0..7118e6d1b2d5 100644 --- a/desktop/source/deployment/registry/configuration/dp_configuration.cxx +++ b/desktop/source/deployment/registry/configuration/dp_configuration.cxx @@ -94,9 +94,9 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend ::rtl::Reference<PackageRegistryBackend> const & myBackend, OUString const & url, OUString const & name, Reference<deployment::XPackageTypeInfo> const & xPackageType, - bool isSchema ) + bool isSchema, bool bUseDb) : Package( myBackend, url, name, name /* display-name */, - xPackageType ), + xPackageType, bUseDb), m_isSchema( isSchema ) {} }; @@ -113,7 +113,7 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend // PackageRegistryBackend virtual Reference<deployment::XPackage> bindPackage_( - OUString const & url, OUString const & mediaType, + OUString const & url, OUString const & mediaType, sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ); ::std::auto_ptr<PersistentMap> m_registeredPackages; @@ -199,7 +199,7 @@ BackendImpl::BackendImpl( m_registeredPackages.reset( new PersistentMap( makeURL( getCachePath(), OUSTR("registered_packages.db") ), - m_readOnly ) ); + false ) ); } } @@ -215,6 +215,7 @@ BackendImpl::getSupportedPackageTypes() throw (RuntimeException) //______________________________________________________________________________ Reference<deployment::XPackage> BackendImpl::bindPackage_( OUString const & url, OUString const & mediaType_, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) { OUString mediaType( mediaType_ ); @@ -255,14 +256,14 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( return new PackageImpl( this, url, ucbContent.getPropertyValue( StrTitle::get() ).get<OUString>(), - m_xConfDataTypeInfo, false /* data file */ ); + m_xConfDataTypeInfo, false /* data file */, bNoFileAccess); } else if (subType.EqualsIgnoreCaseAscii( "vnd.sun.star.configuration-schema")) { return new PackageImpl( this, url, ucbContent.getPropertyValue( StrTitle::get() ).get<OUString>(), - m_xConfSchemaTypeInfo, true /* schema file */ ); + m_xConfSchemaTypeInfo, true /* schema file */, bNoFileAccess); } } } diff --git a/desktop/source/deployment/registry/dp_backend.cxx b/desktop/source/deployment/registry/dp_backend.cxx index c06b30be1669..31bb30de7315 100644 --- a/desktop/source/deployment/registry/dp_backend.cxx +++ b/desktop/source/deployment/registry/dp_backend.cxx @@ -88,6 +88,10 @@ PackageRegistryBackend::PackageRegistryBackend( m_eContext = CONTEXT_USER; else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) m_eContext = CONTEXT_SHARED; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("bundled") )) + m_eContext = CONTEXT_BUNDLED; + else if (m_context.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("tmp") )) + m_eContext = CONTEXT_TMP; else if (m_context.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:/") )) m_eContext = CONTEXT_DOCUMENT; @@ -127,24 +131,29 @@ void PackageRegistryBackend::disposing() // XPackageRegistry //______________________________________________________________________________ Reference<deployment::XPackage> PackageRegistryBackend::bindPackage( - OUString const & url, OUString const & mediaType, + OUString const & url, OUString const & mediaType, sal_Bool bNoFileAccess , Reference<XCommandEnvironment> const & xCmdEnv ) throw (deployment::DeploymentException, CommandFailedException, lang::IllegalArgumentException, RuntimeException) { ::osl::ResettableMutexGuard guard( getMutex() ); check(); - t_string2ref::const_iterator const iFind( m_bound.find( url ) ); - if (iFind != m_bound.end()) { - Reference<deployment::XPackage> xPackage( iFind->second ); - if (xPackage.is()) - return xPackage; + if (!bNoFileAccess) + { + //We only save those object which were created with bNoFileAccess = false + t_string2ref::const_iterator const iFind( m_bound.find( url ) ); + if (iFind != m_bound.end()) + { + Reference<deployment::XPackage> xPackage( iFind->second ); + if (xPackage.is()) + return xPackage; + } } guard.clear(); Reference<deployment::XPackage> xNewPackage; try { - xNewPackage = bindPackage_( url, mediaType, xCmdEnv ); + xNewPackage = bindPackage_( url, mediaType, bNoFileAccess, xCmdEnv ); } catch (RuntimeException &) { throw; @@ -166,19 +175,23 @@ Reference<deployment::XPackage> PackageRegistryBackend::bindPackage( } guard.reset(); - ::std::pair< t_string2ref::iterator, bool > insertion( - m_bound.insert( t_string2ref::value_type( url, xNewPackage ) ) ); - if (insertion.second) - { // first insertion - OSL_ASSERT( Reference<XInterface>(insertion.first->second) - == xNewPackage ); - } - else - { // found existing entry - Reference<deployment::XPackage> xPackage( insertion.first->second ); - if (xPackage.is()) - return xPackage; - insertion.first->second = xNewPackage; + if (!bNoFileAccess) + { + //We only save those object which were created with bNoFileAccess = false + ::std::pair< t_string2ref::iterator, bool > insertion( + m_bound.insert( t_string2ref::value_type( url, xNewPackage ) ) ); + if (insertion.second) + { // first insertion + OSL_ASSERT( Reference<XInterface>(insertion.first->second) + == xNewPackage ); + } + else + { // found existing entry + Reference<deployment::XPackage> xPackage( insertion.first->second ); + if (xPackage.is()) + return xPackage; + insertion.first->second = xNewPackage; + } } guard.clear(); xNewPackage->addEventListener( this ); // listen for disposing events @@ -197,13 +210,15 @@ Package::Package( ::rtl::Reference<PackageRegistryBackend> const & myBackend, OUString const & url, OUString const & name, OUString const & displayName, - Reference<deployment::XPackageTypeInfo> const & xPackageType ) + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bUseDb) : t_PackageBase( getMutex() ), m_myBackend( myBackend ), m_url( url ), m_name( name ), m_displayName( displayName ), - m_xPackageType( xPackageType ) + m_xPackageType( xPackageType ), + m_bUseDb(bUseDb) { } @@ -542,7 +557,29 @@ void Package::revokePackage( lang::IllegalArgumentException, RuntimeException) { processPackage_impl( false /* revoke */, xAbortChannel, xCmdEnv ); + +} + +PackageRegistryBackend * Package::getMyBackend() const +{ + PackageRegistryBackend * pBackend = m_myBackend.get(); + if (NULL == pBackend) + { + //May throw a DisposedException + check(); + //We should never get here... + throw RuntimeException( + OUSTR("Failed to get the BackendImpl"), + static_cast<OWeakObject*>(const_cast<Package *>(this))); + } + return pBackend; } +OUString Package::getRepositoryName() + throw (RuntimeException) +{ + PackageRegistryBackend * backEnd = getMyBackend(); + return backEnd->getContext(); + } //############################################################################## diff --git a/desktop/source/deployment/registry/dp_backenddb.cxx b/desktop/source/deployment/registry/dp_backenddb.cxx new file mode 100644 index 000000000000..fb0b99c3363c --- /dev/null +++ b/desktop/source/deployment/registry/dp_backenddb.cxx @@ -0,0 +1,332 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "rtl/string.h" +#include "rtl/strbuf.hxx" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "osl/file.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "com/sun/star/io/XActiveDataSource.hpp" +#include "com/sun/star/io/XActiveDataControl.hpp" +#include "dp_ucb.h" +#include "dp_misc.h" +#include "ucbhelper/content.hxx" +#include "xmlscript/xml_helper.hxx" +#include "dp_backenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + + +namespace dp_registry { +namespace backend { + +BackendDb::BackendDb( + Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url): + m_xContext(xContext) +{ + m_urlDb = dp_misc::expandUnoRcUrl(url); +} + +void BackendDb::save() +{ + Reference<css::io::XActiveDataSource> xDataSource(m_doc,css::uno::UNO_QUERY_THROW); + ::rtl::ByteSequence bytes; + xDataSource->setOutputStream(::xmlscript::createOutputStream(&bytes)); + Reference<css::io::XActiveDataControl> xDataControl(m_doc,css::uno::UNO_QUERY_THROW); + xDataControl->start(); + + Reference<css::io::XInputStream> xData( + ::xmlscript::createInputStream(bytes)); + ::ucbhelper::Content ucbDb(m_urlDb, 0); + ucbDb.writeStream(xData, true /*replace existing*/); +} + +css::uno::Reference<css::xml::dom::XDocument> BackendDb::getDocument() +{ + if (!m_doc.is()) + { + Reference<css::xml::dom::XDocumentBuilder> xDocBuilder( + m_xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.dom.DocumentBuilder"), + m_xContext ), css::uno::UNO_QUERY); + if (!xDocBuilder.is()) + throw css::uno::RuntimeException( + OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0); + + ::osl::DirectoryItem item; + ::osl::File::RC err = ::osl::DirectoryItem::get(m_urlDb, item); + if (err == ::osl::File::E_None) + { + m_doc = xDocBuilder->parseURI(m_urlDb); + } + else if (err == ::osl::File::E_NOENT) + { + //Create a new document and insert some basic stuff + m_doc = xDocBuilder->newDocument(); + Reference<css::xml::dom::XElement> rootNode = + m_doc->createElement(getRootElementName()); + rootNode->setAttribute( + OUSTR("xmlns"), getDbNSName()); + m_doc->appendChild(Reference<css::xml::dom::XNode>( + rootNode, UNO_QUERY_THROW)); + save(); + } + else + throw css::uno::RuntimeException( + OUSTR("Extension manager could not access database file:" ) + + m_urlDb, 0); + + if (!m_doc.is()) + throw css::uno::RuntimeException( + OUSTR("Extension manager could not get root node of data base file: ") + + m_urlDb, 0); + } + + return m_doc; +} + +Reference<css::xml::xpath::XXPathAPI> BackendDb::getXPathAPI() +{ + if (!m_xpathApi.is()) + { + m_xpathApi = Reference< css::xml::xpath::XXPathAPI >( + m_xContext->getServiceManager()->createInstanceWithContext( + OUSTR("com.sun.star.xml.xpath.XPathAPI"), + m_xContext), css::uno::UNO_QUERY); + + if (!m_xpathApi.is()) + throw css::uno::RuntimeException( + OUSTR(" Could not create service com.sun.star.xml.xpath.XPathAPI"), 0); + + m_xpathApi->registerNS( + OUSTR("reg"), getDbNSName()); + } + + return m_xpathApi; +} + +// OUString BackendDb::getDbNSName() +// { +// return OUString(); +// } + + +// OUString BackendDb::getRootElementName() +// { +// return OUString(); +// } + +void BackendDb::removeElement(::rtl::OUString const & sXPathExpression) +{ + try + { + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + //find the extension element that is to be removed + Reference<css::xml::dom::XNode> aNode = + xpathApi->selectSingleNode(root, sXPathExpression); + OSL_ASSERT(aNode.is()); + if (aNode.is()) + { + root->removeChild(aNode); + save(); + } + +#if OSL_DEBUG_LEVEL > 0 + //There must not be any other entry with the same url + Reference<css::xml::dom::XNode> nextNode = + xpathApi->selectSingleNode(root, sXPathExpression); + OSL_ASSERT(! nextNode.is()); +#endif + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } + +} + +void BackendDb::writeVectorOfPair( + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > const & vecPairs, + OUString const & sVectorTagName, + OUString const & sPairTagName, + OUString const & sFirstTagName, + OUString const & sSecondTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent) +{ + try{ + + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::dom::XElement> vectorNode( + doc->createElement(sVectorTagName)); + + xParent->appendChild( + Reference<css::xml::dom::XNode>( + vectorNode, css::uno::UNO_QUERY_THROW)); + typedef ::std::vector< ::std::pair< OUString, OUString > >::const_iterator CIT; + for (CIT i = vecPairs.begin(); i != vecPairs.end(); i++) + { + Reference<css::xml::dom::XElement> pairNode( + doc->createElement(sPairTagName)); + + vectorNode->appendChild( + Reference<css::xml::dom::XNode>( + pairNode, css::uno::UNO_QUERY_THROW)); + + Reference<css::xml::dom::XElement> firstNode( + doc->createElement(sFirstTagName)); + + pairNode->appendChild( + Reference<css::xml::dom::XNode>( + firstNode, css::uno::UNO_QUERY_THROW)); + + Reference<css::xml::dom::XText> firstTextNode( + doc->createTextNode( i->first)); + + firstNode->appendChild( + Reference<css::xml::dom::XNode>( + firstTextNode, css::uno::UNO_QUERY_THROW)); + + Reference<css::xml::dom::XElement> secondNode( + doc->createElement(sSecondTagName)); + + pairNode->appendChild( + Reference<css::xml::dom::XNode>( + secondNode, css::uno::UNO_QUERY_THROW)); + + Reference<css::xml::dom::XText> secondTextNode( + doc->createTextNode( i->second)); + + secondNode->appendChild( + Reference<css::xml::dom::XNode>( + secondTextNode, css::uno::UNO_QUERY_THROW)); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +::std::vector< ::std::pair< OUString, OUString > > +BackendDb::readVectorOfPair( + Reference<css::xml::dom::XNode> const & parent, + OUString const & sListTagName, + OUString const & sPairTagName, + OUString const & sFirstTagName, + OUString const & sSecondTagName) +{ + OSL_ASSERT(parent.is()); + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + OUString sExprPairs( + sListTagName + OUSTR("/") + sPairTagName); + Reference<css::xml::dom::XNodeList> listPairs = + xpathApi->selectNodeList(parent, sExprPairs); + + ::std::vector< ::std::pair< OUString, OUString > > retVector; + sal_Int32 length = listPairs->getLength(); + for (sal_Int32 i = 0; i < length; i++) + { + Reference<css::xml::dom::XNode> aPair = listPairs->item(i); + OUString sExprFirst(sFirstTagName + OUSTR("/text()")); + Reference<css::xml::dom::XNode> first = + xpathApi->selectSingleNode(aPair, sExprFirst); + + OUString sExprSecond(sSecondTagName + OUSTR("/text()")); + Reference<css::xml::dom::XNode> second = + xpathApi->selectSingleNode(aPair, sExprSecond); + OSL_ASSERT(first.is() && second.is()); + + retVector.push_back(::std::make_pair( + first->getNodeValue(), second->getNodeValue())); + } + return retVector; +} + +void BackendDb::writeSimpleList( + ::std::list< ::rtl::OUString> const & list, + OUString const & sListTagName, + OUString const & sMemberTagName, + Reference<css::xml::dom::XNode> const & xParent) +{ + try + { + Reference<css::xml::dom::XDocument> doc = getDocument(); + + Reference<css::xml::dom::XElement> listNode( + doc->createElement(sListTagName)); + + xParent->appendChild( + Reference<css::xml::dom::XNode>( + listNode, css::uno::UNO_QUERY_THROW)); + + typedef ::std::list<OUString>::const_iterator ITC_ITEMS; + for (ITC_ITEMS i = list.begin(); i != list.end(); i++) + { + Reference<css::xml::dom::XNode> memberNode( + doc->createElement(sMemberTagName), css::uno::UNO_QUERY_THROW); + + listNode->appendChild(memberNode); + + Reference<css::xml::dom::XNode> textNode( + doc->createTextNode( *i), css::uno::UNO_QUERY_THROW); + + memberNode->appendChild(textNode); + } + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } + +} + +} // namespace backend +} // namespace dp_registry + diff --git a/desktop/source/deployment/registry/dp_registry.cxx b/desktop/source/deployment/registry/dp_registry.cxx index c56131a1015c..9ea13ad2c91f 100644 --- a/desktop/source/deployment/registry/dp_registry.cxx +++ b/desktop/source/deployment/registry/dp_registry.cxx @@ -126,7 +126,7 @@ public: // XPackageRegistry virtual Reference<deployment::XPackage> SAL_CALL bindPackage( - OUString const & url, OUString const & mediaType, + OUString const & url, OUString const & mediaType, sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) throw (deployment::DeploymentException, CommandFailedException, lang::IllegalArgumentException, RuntimeException); @@ -361,9 +361,24 @@ Reference<deployment::XPackageRegistry> PackageRegistryImpl::create( // Always register as last, because we want to add extensions also as folders // and as a default we accept every folder, which was not recognized by the other // backends. - that->insertBackend( + Reference<deployment::XPackageRegistry> extensionBackend = ::dp_registry::backend::bundle::create( - that, context, cachePath, readOnly, xComponentContext ) ); + that, context, cachePath, readOnly, xComponentContext); + that->insertBackend(extensionBackend); + + Reference<lang::XServiceInfo> xServiceInfo( + extensionBackend, UNO_QUERY_THROW ); + + OSL_ASSERT(xServiceInfo.is()); + OUString registryCachePath( + makeURL( cachePath, + ::rtl::Uri::encode( + xServiceInfo->getImplementationName(), + rtl_UriCharClassPchar, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 ) ) ); + create_folder( 0, registryCachePath, Reference<XCommandEnvironment>()); + #if OSL_DEBUG_LEVEL > 1 // dump tables: @@ -443,7 +458,7 @@ void PackageRegistryImpl::update() throw (RuntimeException) // XPackageRegistry //______________________________________________________________________________ Reference<deployment::XPackage> PackageRegistryImpl::bindPackage( - OUString const & url, OUString const & mediaType_, + OUString const & url, OUString const & mediaType_, sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) throw (deployment::DeploymentException, CommandFailedException, lang::IllegalArgumentException, RuntimeException) @@ -482,7 +497,7 @@ Reference<deployment::XPackage> PackageRegistryImpl::bindPackage( for ( ; iPos != iEnd; ++iPos ) { try { - return (*iPos)->bindPackage( url, mediaType, xCmdEnv ); + return (*iPos)->bindPackage( url, mediaType, bNoFileAccess, xCmdEnv ); } catch (lang::IllegalArgumentException &) { } @@ -511,7 +526,7 @@ Reference<deployment::XPackage> PackageRegistryImpl::bindPackage( getResourceString(RID_STR_UNSUPPORTED_MEDIA_TYPE) + mediaType, static_cast<OWeakObject *>(this), static_cast<sal_Int16>(-1) ); } - return iFind->second->bindPackage( url, mediaType, xCmdEnv ); + return iFind->second->bindPackage( url, mediaType, bNoFileAccess, xCmdEnv ); } } diff --git a/desktop/source/deployment/registry/executable/dp_executable.cxx b/desktop/source/deployment/registry/executable/dp_executable.cxx index 8c95d5874b4c..a5fe1b99746f 100644 --- a/desktop/source/deployment/registry/executable/dp_executable.cxx +++ b/desktop/source/deployment/registry/executable/dp_executable.cxx @@ -72,9 +72,9 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend inline ExecutablePackageImpl( ::rtl::Reference<PackageRegistryBackend> const & myBackend, OUString const & url, OUString const & name, - Reference<deployment::XPackageTypeInfo> const & xPackageType) + Reference<deployment::XPackageTypeInfo> const & xPackageType, bool bUseDb) : Package( myBackend, url, name, name /* display-name */, - xPackageType ) //, + xPackageType, bUseDb) //, {} }; friend class ExecutablePackageImpl; @@ -84,7 +84,7 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend // PackageRegistryBackend virtual Reference<deployment::XPackage> bindPackage_( - OUString const & url, OUString const & mediaType, + OUString const & url, OUString const & mediaType, sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ); Reference<deployment::XPackageTypeInfo> m_xExecutableTypeInfo; @@ -125,7 +125,7 @@ BackendImpl::getSupportedPackageTypes() throw (RuntimeException) // PackageRegistryBackend Reference<deployment::XPackage> BackendImpl::bindPackage_( - OUString const & url, OUString const & mediaType, + OUString const & url, OUString const & mediaType, sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) { if (mediaType.getLength() == 0) @@ -147,7 +147,7 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.executable")) { return new BackendImpl::ExecutablePackageImpl( - this, url, name, m_xExecutableTypeInfo); + this, url, name, m_xExecutableTypeInfo, bNoFileAccess); } } } diff --git a/desktop/source/deployment/registry/help/dp_help.cxx b/desktop/source/deployment/registry/help/dp_help.cxx index 2b0d91250e4a..05ff8dda0e01 100644 --- a/desktop/source/deployment/registry/help/dp_help.cxx +++ b/desktop/source/deployment/registry/help/dp_help.cxx @@ -78,8 +78,9 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend inline PackageImpl( ::rtl::Reference<PackageRegistryBackend> const & myBackend, OUString const & url, OUString const & name, - Reference<deployment::XPackageTypeInfo> const & xPackageType ) - : Package( myBackend, url, name, name, xPackageType ) + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool bUseDb) + : Package( myBackend, url, name, name, xPackageType, bUseDb) {} }; friend class PackageImpl; @@ -87,6 +88,7 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend // PackageRegistryBackend virtual Reference<deployment::XPackage> bindPackage_( OUString const & url, OUString const & mediaType, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ); void implProcessHelp( Reference< deployment::XPackage > xPackage, bool doRegisterPackage ); @@ -138,6 +140,7 @@ BackendImpl::getSupportedPackageTypes() throw (RuntimeException) //______________________________________________________________________________ Reference<deployment::XPackage> BackendImpl::bindPackage_( OUString const & url, OUString const & mediaType_, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) { // we don't support auto detection: @@ -156,8 +159,10 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( if (subType.EqualsIgnoreCaseAscii( "vnd.sun.star.help")) { - return new PackageImpl( this, url, - ucbContent.getPropertyValue( StrTitle::get() ).get<OUString>(), m_xHelpTypeInfo ); + return new PackageImpl( + this, url, + ucbContent.getPropertyValue( StrTitle::get() ).get<OUString>(), + m_xHelpTypeInfo, bNoFileAccess); } } } diff --git a/desktop/source/deployment/registry/inc/dp_backend.h b/desktop/source/deployment/registry/inc/dp_backend.h index fe52c8ffc7e3..09b25caedc2b 100644 --- a/desktop/source/deployment/registry/inc/dp_backend.h +++ b/desktop/source/deployment/registry/inc/dp_backend.h @@ -62,6 +62,7 @@ typedef ::cppu::WeakComponentImplHelper1< //============================================================================== class Package : protected ::dp_misc::MutexHolder, public t_PackageBase { + PackageRegistryBackend * getMyBackend() const; void processPackage_impl( bool registerPackage, css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel, @@ -73,6 +74,7 @@ protected: ::rtl::OUString m_name; ::rtl::OUString m_displayName; const css::uno::Reference<css::deployment::XPackageTypeInfo> m_xPackageType; + const bool m_bUseDb; void check() const; void fireModified(); @@ -101,7 +103,8 @@ protected: ::rtl::OUString const & name, ::rtl::OUString const & displayName, css::uno::Reference<css::deployment::XPackageTypeInfo> const & - xPackageType ); + xPackageType, + bool bUseDb); public: @@ -233,6 +236,9 @@ public: css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) throw (css::ucb::CommandFailedException, css::ucb::CommandAbortedException, css::uno::RuntimeException); + + virtual ::rtl::OUString SAL_CALL getRepositoryName() + throw (css::uno::RuntimeException); }; typedef ::cppu::WeakComponentImplHelper2< @@ -243,7 +249,6 @@ typedef ::cppu::WeakComponentImplHelper2< class PackageRegistryBackend : protected ::dp_misc::MutexHolder, public t_BackendBase { - ::rtl::OUString m_cachePath; //The map held originally WeakReferences. The map entries are removed in the disposing //function, which is called when the XPackages are destructed or they are //explicitely disposed. The latter happens, for example, when a extension is @@ -257,13 +262,14 @@ class PackageRegistryBackend t_string2ref m_bound; protected: + ::rtl::OUString m_cachePath; css::uno::Reference<css::uno::XComponentContext> m_xComponentContext; ::rtl::OUString m_context; // currently only for library containers: enum context { CONTEXT_UNKNOWN, - CONTEXT_USER, CONTEXT_SHARED, + CONTEXT_USER, CONTEXT_SHARED,CONTEXT_BUNDLED, CONTEXT_TMP, CONTEXT_DOCUMENT } m_eContext; bool m_readOnly; @@ -276,6 +282,7 @@ protected: // @@@ to be implemented by specific backend: virtual css::uno::Reference<css::deployment::XPackage> bindPackage_( ::rtl::OUString const & url, ::rtl::OUString const & mediaType, + sal_Bool bNoFileAccess, css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) = 0; @@ -299,6 +306,8 @@ public: inline ::rtl::OUString const & getCachePath() const { return m_cachePath; } inline bool transientMode() const { return m_cachePath.getLength() == 0; } + inline ::rtl::OUString getContext() const {return m_context; } + // XEventListener virtual void SAL_CALL disposing( css::lang::EventObject const & evt ) throw (css::uno::RuntimeException); @@ -306,6 +315,7 @@ public: // XPackageRegistry virtual css::uno::Reference<css::deployment::XPackage> SAL_CALL bindPackage( ::rtl::OUString const & url, ::rtl::OUString const & mediaType, + sal_Bool bNoFileAccess, css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv ) throw (css::deployment::DeploymentException, css::ucb::CommandFailedException, diff --git a/desktop/source/deployment/registry/inc/dp_backenddb.hxx b/desktop/source/deployment/registry/inc/dp_backenddb.hxx new file mode 100644 index 000000000000..3005ffcafb5b --- /dev/null +++ b/desktop/source/deployment/registry/inc/dp_backenddb.hxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if ! defined INCLUDED_DP_BACKENDDB_HXX +#define INCLUDED_DP_BACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include <list> + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { + +class BackendDb +{ +private: + + css::uno::Reference<css::xml::dom::XDocument> m_doc; + css::uno::Reference<css::xml::xpath::XXPathAPI> m_xpathApi; + + BackendDb(BackendDb const &); + BackendDb & operator = (BackendDb const &); + +protected: + const css::uno::Reference<css::uno::XComponentContext> m_xContext; + ::rtl::OUString m_urlDb; + +protected: + + /* caller must make sure that only one thread accesses the function + */ + css::uno::Reference<css::xml::dom::XDocument> getDocument(); + + /* the namespace prefix is "reg" (without quotes) + */ + css::uno::Reference<css::xml::xpath::XXPathAPI> getXPathAPI(); + void save(); + void removeElement(::rtl::OUString const & sXPathExpression); + + void writeSimpleList( + ::std::list< ::rtl::OUString> const & list, + ::rtl::OUString const & sListTagName, + ::rtl::OUString const & sMemberTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + void writeVectorOfPair( + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > const & vecPairs, + ::rtl::OUString const & sVectorTagName, + ::rtl::OUString const & sPairTagName, + ::rtl::OUString const & sFirstTagName, + ::rtl::OUString const & sSecondTagName, + css::uno::Reference<css::xml::dom::XNode> const & xParent); + + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > + readVectorOfPair( + css::uno::Reference<css::xml::dom::XNode> const & parent, + ::rtl::OUString const & sListTagName, + ::rtl::OUString const & sPairTagName, + ::rtl::OUString const & sFirstTagName, + ::rtl::OUString const & sSecondTagName); + + + + /* returns the namespace which is to be written as xmlns attribute + into the root element. + */ + virtual ::rtl::OUString getDbNSName()=0; + /* returns the name of the root element without any namespace prefix. + */ + virtual ::rtl::OUString getRootElementName()=0; + + +public: + BackendDb(css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + virtual ~BackendDb() {}; + +}; + +} +} +#endif + diff --git a/desktop/source/deployment/registry/makefile.mk b/desktop/source/deployment/registry/makefile.mk index de0e943654d9..e45cec272ca7 100644 --- a/desktop/source/deployment/registry/makefile.mk +++ b/desktop/source/deployment/registry/makefile.mk @@ -41,7 +41,8 @@ INCPRE += inc SLOFILES = \ $(SLO)$/dp_backend.obj \ - $(SLO)$/dp_registry.obj + $(SLO)$/dp_registry.obj \ + $(SLO)$/dp_backenddb.obj .INCLUDE : ..$/target.pmk .INCLUDE : target.mk diff --git a/desktop/source/deployment/registry/package/dp_description.cxx b/desktop/source/deployment/registry/package/dp_description.cxx deleted file mode 100644 index 7c05bfd90a5b..000000000000 --- a/desktop/source/deployment/registry/package/dp_description.cxx +++ /dev/null @@ -1,205 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_desktop.hxx" - -#include "dp_description.hxx" - -#include "cppuhelper/exc_hlp.hxx" -#include "ucbhelper/content.hxx" -#include "com/sun/star/deployment/DeploymentException.hpp" -#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" -#include "com/sun/star/uno/XComponentContext.hpp" -#include "com/sun/star/ucb/CommandFailedException.hpp" -#include "com/sun/star/ucb/InteractiveAugmentedIOException.hpp" -#include "com/sun/star/ucb/IOErrorCode.hpp" - -#include "com/sun/star/beans/PropertyValue.hpp" - - -#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) - -namespace css = com::sun::star; -namespace cssu = com::sun::star::uno; - -namespace dp_registry { -namespace backend { -namespace bundle { - -ExtensionDescription::ExtensionDescription( - const cssu::Reference<cssu::XComponentContext>& xContext, - const ::rtl::OUString& installDir, - const cssu::Reference< css::ucb::XCommandEnvironment >& xCmdEnv) -{ - try { - m_sExtensionRootUrl = installDir; - //may throw ::com::sun::star::ucb::ContentCreationException - //If there is no description.xml then ucb will start an interaction which - //brings up a dialog.We want to prevent this. Therefore we wrap the xCmdEnv - //and filter the respective exception out. - ::rtl::OUString sDescriptionUri(installDir + OUSTR("/description.xml")); - cssu::Reference<css::ucb::XCommandEnvironment> xFilter = - static_cast<css::ucb::XCommandEnvironment*>( - new FileDoesNotExistFilter(xCmdEnv)); - ::ucbhelper::Content descContent(sDescriptionUri, xFilter); - - //throws an com::sun::star::uno::Exception if the file is not available - cssu::Reference<css::io::XInputStream> xIn; - try - { //throws com.sun.star.ucb.InteractiveAugmentedIOException - xIn = descContent.openStream(); - } - catch (cssu::Exception& ) - { - if ( ! static_cast<FileDoesNotExistFilter*>(xFilter.get())->exist()) - throw NoDescriptionException(); - throw; - } - if (!xIn.is()) - { - throw cssu::Exception( - OUSTR("Could not get XInputStream for description.xml of extension ") + - sDescriptionUri, 0); - } - - //get root node of description.xml - cssu::Reference<css::xml::dom::XDocumentBuilder> xDocBuilder( - xContext->getServiceManager()->createInstanceWithContext( - OUSTR("com.sun.star.xml.dom.DocumentBuilder"), - xContext ), cssu::UNO_QUERY); - if (!xDocBuilder.is()) - throw css::uno::Exception(OUSTR(" Could not create service com.sun.star.xml.dom.DocumentBuilder"), 0); - - if (xDocBuilder->isNamespaceAware() == sal_False) - { - throw cssu::Exception( - OUSTR("Service com.sun.star.xml.dom.DocumentBuilder is not namespace aware."), 0); - } - - cssu::Reference<css::xml::dom::XDocument> xDoc = xDocBuilder->parse(xIn); - if (!xDoc.is()) - { - throw cssu::Exception(sDescriptionUri + OUSTR(" contains data which cannot be parsed. "), 0); - } - - //check for proper root element and namespace - cssu::Reference<css::xml::dom::XElement> xRoot = xDoc->getDocumentElement(); - if (!xRoot.is()) - { - throw cssu::Exception( - sDescriptionUri + OUSTR(" contains no root element."), 0); - } - - if ( ! xRoot->getTagName().equals(OUSTR("description"))) - { - throw cssu::Exception( - sDescriptionUri + OUSTR(" does not contain the root element <description>."), 0); - } - - m_xRoot = cssu::Reference<css::xml::dom::XNode>( - xRoot, cssu::UNO_QUERY_THROW); - ::rtl::OUString nsDescription = xRoot->getNamespaceURI(); - - //check if this namespace is supported - if ( ! nsDescription.equals(OUSTR("http://openoffice.org/extensions/description/2006"))) - { - throw cssu::Exception(sDescriptionUri + OUSTR(" contains a root element with an unsupported namespace. "), 0); - } - } catch (css::uno::RuntimeException &) { - throw; - } catch (css::deployment::DeploymentException &) { - throw; - } catch (css::uno::Exception & e) { - css::uno::Any a(cppu::getCaughtException()); - throw css::deployment::DeploymentException( - e.Message, css::uno::Reference< css::uno::XInterface >(), a); - } -} - -ExtensionDescription::~ExtensionDescription() -{ -} - -//====================================================================== -FileDoesNotExistFilter::FileDoesNotExistFilter( - const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv): - m_bExist(true), m_xCommandEnv(xCmdEnv) -{} - -FileDoesNotExistFilter::~FileDoesNotExistFilter() -{ -}; - -bool FileDoesNotExistFilter::exist() -{ - return m_bExist; -} - // XCommandEnvironment -cssu::Reference<css::task::XInteractionHandler > - FileDoesNotExistFilter::getInteractionHandler() throw (css::uno::RuntimeException) -{ - return static_cast<css::task::XInteractionHandler*>(this); -} - -cssu::Reference<css::ucb::XProgressHandler > - FileDoesNotExistFilter::getProgressHandler() throw (css::uno::RuntimeException) -{ - return m_xCommandEnv.is() - ? m_xCommandEnv->getProgressHandler() - : cssu::Reference<css::ucb::XProgressHandler>(); -} - -// XInteractionHandler -//If the interaction was caused by a non-existing file which is specified in the ctor -//of FileDoesNotExistFilter, then we do nothing -void FileDoesNotExistFilter::handle( - cssu::Reference<css::task::XInteractionRequest > const & xRequest ) - throw (css::uno::RuntimeException) -{ - cssu::Any request( xRequest->getRequest() ); - - css::ucb::InteractiveAugmentedIOException ioexc; - if ((request>>= ioexc) && ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING ) - { - m_bExist = false; - return; - } - css::uno::Reference<css::task::XInteractionHandler> xInteraction; - if (m_xCommandEnv.is()) { - xInteraction = m_xCommandEnv->getInteractionHandler(); - } - if (xInteraction.is()) { - xInteraction->handle(xRequest); - } -} - - -} // namespace bundle -} // namespace backend -} // namespace dp_registry - diff --git a/desktop/source/deployment/registry/package/dp_description.hxx b/desktop/source/deployment/registry/package/dp_description.hxx deleted file mode 100644 index eb74c454af75..000000000000 --- a/desktop/source/deployment/registry/package/dp_description.hxx +++ /dev/null @@ -1,125 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#if !defined INCLUDED_DESKTOP_EXTENSION_DESCRIPTION_HXX -#define INCLUDED_DESKTOP_EXTENSION_DESCRIPTION_HXX - - - -#include "com/sun/star/uno/Reference.hxx" - -#include "com/sun/star/ucb/XCommandEnvironment.hpp" -#include "com/sun/star/uno/XComponentContext.hpp" -#include "com/sun/star/xml/dom/XNode.hpp" -#include "com/sun/star/task/XInteractionHandler.hpp" -#include "cppuhelper/implbase2.hxx" - - -namespace css = ::com::sun::star; - -namespace dp_registry { -namespace backend { -namespace bundle { - -/**The class uses the UCB to access the description.xml file in an - extension. The UCB must have been initialized already. It also - requires that the extension has already be unzipped to a particular - location. - */ -class ExtensionDescription -{ -public: - /**throws an exception if the description.xml is not - available, cannot be read, does not contain the expected data, - or any other error occured. Therefore it shoult only be used with - new extensions. - - Throws com::sun::star::uno::RuntimeException, - com::sun::star::deployment::DeploymentException, - dp_registry::backend::bundle::NoDescriptionException. - */ - ExtensionDescription( - const css::uno::Reference<css::uno::XComponentContext>& xContext, - const ::rtl::OUString& installDir, - const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv); - - ~ExtensionDescription(); - - css::uno::Reference<css::xml::dom::XNode> getRootElement() const - { - return m_xRoot; - } - - ::rtl::OUString getExtensionRootUrl() const - { - return m_sExtensionRootUrl; - } - - -private: - css::uno::Reference<css::xml::dom::XNode> m_xRoot; - ::rtl::OUString m_sExtensionRootUrl; -}; - -class NoDescriptionException -{ -}; - -class FileDoesNotExistFilter - : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment, - css::task::XInteractionHandler > - -{ - //css::uno::Reference<css::task::XInteractionHandler> m_xHandler; - bool m_bExist; - css::uno::Reference< css::ucb::XCommandEnvironment > m_xCommandEnv; - -public: - virtual ~FileDoesNotExistFilter(); - FileDoesNotExistFilter( - const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv); - - bool exist(); - // XCommandEnvironment - virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL - getInteractionHandler() throw (css::uno::RuntimeException); - virtual css::uno::Reference<css::ucb::XProgressHandler > - SAL_CALL getProgressHandler() throw (css::uno::RuntimeException); - - // XInteractionHandler - virtual void SAL_CALL handle( - css::uno::Reference<css::task::XInteractionRequest > const & xRequest ) - throw (css::uno::RuntimeException); -}; - - -} // namespace bundle -} // namespace backend -} // namespace dp_registry - - -#endif // INCLUDED_DESKTOP_LICENSE_INTERACT_HXX diff --git a/desktop/source/deployment/registry/package/dp_extbackenddb.cxx b/desktop/source/deployment/registry/package/dp_extbackenddb.cxx new file mode 100644 index 000000000000..97cfc136049c --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_extbackenddb.cxx @@ -0,0 +1,177 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_desktop.hxx" + +#include "rtl/string.h" +#include "rtl/bootstrap.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/xml/dom/XDocumentBuilder.hpp" +#include "com/sun/star/xml/xpath/XXPathAPI.hpp" +#include "dp_misc.h" + +#include "dp_extbackenddb.hxx" + + +namespace css = ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + +#define EXTENSION_REG_NS "http://openoffice.org/extensionmanager/extension-registry/2010" +#define ROOT_ELEMENT_NAME "extension-backend-db" + +// /extension-backend-db/extension +#define EXTENSION_ELEMENT "extension" + +// /extension-backend-db/extension/extension-items +#define EXTENSION_ITEMS "extension-items" + +// /extension-backend-db/extension/extension-items/item +#define EXTENSION_ITEMS_ITEM "item" + +// /extension-backend-db/extension/extension-items/item/url +#define ITEM_URL "url" + +// /extension-backend-db/extension/extension-items/item/media-type +#define ITEM_MEDIA_TYP "media-type" + + +namespace dp_registry { +namespace backend { +namespace bundle { + +ExtensionBackendDb::ExtensionBackendDb( + Reference<XComponentContext> const & xContext, + ::rtl::OUString const & url):BackendDb(xContext, url) +{ + +} + +OUString ExtensionBackendDb::getDbNSName() +{ + return OUSTR(EXTENSION_REG_NS); +} + +OUString ExtensionBackendDb::getRootElementName() +{ + return OUSTR(ROOT_ELEMENT_NAME); +} + +void ExtensionBackendDb::addEntry(::rtl::OUString const & url, Data const & data) +{ + try{ + + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + +#if OSL_DEBUG_LEVEL > 0 + //There must not be yet an entry with the same url + OUString sExpression( + OUSTR("reg:extension[@url = \"") + url + OUSTR("\"]")); + Reference<css::xml::dom::XNode> _extensionNode = + getXPathAPI()->selectSingleNode(root, sExpression); + OSL_ASSERT(! _extensionNode.is()); +#endif + // <extension url="file:///..."> + Reference<css::xml::dom::XElement> extensionNode( + doc->createElement(OUSTR("extension"))); + + extensionNode->setAttribute(OUSTR("url"), url); + + Reference<css::xml::dom::XNode> extensionNodeNode( + extensionNode, css::uno::UNO_QUERY_THROW); + root->appendChild(extensionNodeNode); + + // <identifier>...</identifier> + Reference<css::xml::dom::XNode> identifierNode( + doc->createElement(OUSTR("identifier")), UNO_QUERY_THROW); + extensionNodeNode->appendChild(identifierNode); + + Reference<css::xml::dom::XNode> identifierValue( + doc->createTextNode(data.identifier), UNO_QUERY_THROW); + identifierNode->appendChild(identifierValue); + + + writeVectorOfPair( + data.items, + OUSTR("extension-items"), + OUSTR("item"), + OUSTR("url"), + OUSTR("media-type"), + extensionNodeNode); + save(); + } + catch(css::uno::Exception &) + { + Any exc( ::cppu::getCaughtException() ); + throw css::deployment::DeploymentException( + OUSTR("Extension Manager: failed to write data entry in backend db: ") + + m_urlDb, 0, exc); + } +} + +void ExtensionBackendDb::removeEntry(::rtl::OUString const & url) +{ + OUString sExpression( + OUSTR("reg:extension[@url = \"") + url + OUSTR("\"]")); + removeElement(sExpression); +} + +ExtensionBackendDb::Data ExtensionBackendDb::getEntry(::rtl::OUString const & url) +{ + ExtensionBackendDb::Data retData; + const OUString sExpression( + OUSTR("reg:extension[@url = \"") + url + OUSTR("\"]")); + Reference<css::xml::dom::XDocument> doc = getDocument(); + Reference<css::xml::dom::XNode> root = doc->getFirstChild(); + + Reference<css::xml::xpath::XXPathAPI> xpathApi = getXPathAPI(); + //find the extension element that is to be removed + Reference<css::xml::dom::XNode> aNode = + xpathApi->selectSingleNode(root, sExpression); + OSL_ASSERT(aNode.is()); + + const OUString sExprIdentifier(OUSTR("reg:identifier/text()")); + + Reference<css::xml::dom::XNode> idValueNode = + xpathApi->selectSingleNode(aNode, sExprIdentifier); + retData.identifier = idValueNode->getNodeValue(); + + retData.items = + readVectorOfPair( + aNode, + OUSTR("reg:extension-items"), + OUSTR("reg:item"), OUSTR("reg:url"), OUSTR("reg:media-type")); + return retData; +} + +} // namespace bundle +} // namespace backend +} // namespace dp_registry + diff --git a/desktop/source/deployment/registry/package/dp_extbackenddb.hxx b/desktop/source/deployment/registry/package/dp_extbackenddb.hxx new file mode 100644 index 000000000000..156e34155040 --- /dev/null +++ b/desktop/source/deployment/registry/package/dp_extbackenddb.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#if ! defined INCLUDED_DP_EXTBACKENDDB_HXX +#define INCLUDED_DP_EXTBACKENDDB_HXX + +#include "rtl/ustring.hxx" +#include "rtl/string.hxx" +#include <vector> +#include "dp_backenddb.hxx" + +namespace css = ::com::sun::star; + +namespace com { namespace sun { namespace star { + namespace uno { + class XComponentContext; + } + namespace xml { namespace dom { + class XDocument; + class XNode; + }} + namespace xml { namespace xpath { + class XXPathAPI; + }} +}}} + +namespace dp_registry { +namespace backend { +namespace bundle { + +/* The XML file stores the extensions which are currently registered. + They will be removed when they are revoked. + */ +class ExtensionBackendDb: public dp_registry::backend::BackendDb +{ +public: + struct Data + { + ::rtl::OUString identifier; + /* every element consists of a pair of the url to the item (jar,rdb, etc) + and the media type + */ + ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString> > items; + typedef ::std::vector< + ::std::pair< ::rtl::OUString, ::rtl::OUString> >::const_iterator ITC_ITEMS; + + }; + +public: + + ExtensionBackendDb( css::uno::Reference<css::uno::XComponentContext> const & xContext, + ::rtl::OUString const & url); + + void addEntry(::rtl::OUString const & url, Data const & data); + void removeEntry(::rtl::OUString const & url); + Data getEntry(::rtl::OUString const & url); + + virtual ::rtl::OUString getDbNSName(); + + virtual ::rtl::OUString getRootElementName(); +}; + + + +} +} +} +#endif + diff --git a/desktop/source/deployment/registry/package/dp_package.cxx b/desktop/source/deployment/registry/package/dp_package.cxx index b0b4a918c7a3..8fe7874f247f 100644 --- a/desktop/source/deployment/registry/package/dp_package.cxx +++ b/desktop/source/deployment/registry/package/dp_package.cxx @@ -34,7 +34,6 @@ #include "dp_interact.h" #include "dp_dependencies.hxx" #include "dp_platform.hxx" -#include "dp_description.hxx" #include "dp_descriptioninfoset.hxx" #include "dp_identifier.hxx" #include "rtl/uri.hxx" @@ -74,7 +73,7 @@ #include <vector> #include <stdio.h> - +#include "dp_extbackenddb.hxx" using namespace ::dp_misc; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -106,6 +105,8 @@ class BackendImpl : public ImplBaseT Sequence< Reference<deployment::XPackage> > m_bundle; Sequence< Reference<deployment::XPackage> > * m_pBundle; + ExtensionBackendDb::Data m_data; + Reference<deployment::XPackage> bindBundleItem( OUString const & url, OUString const & mediaType, Reference<XCommandEnvironment> const & xCmdEnv, @@ -122,20 +123,20 @@ class BackendImpl : public ImplBaseT ::rtl::Reference<AbortChannel> const & abortChannel, Reference<XCommandEnvironment> const & xCmdEnv, bool skip_registration = false ); - + ::std::vector<Reference<deployment::XPackage> > getPackagesFromDb(); bool checkPlatform( css::uno::Reference< css::ucb::XCommandEnvironment > const & environment); bool checkDependencies( css::uno::Reference< css::ucb::XCommandEnvironment > const & environment, - ExtensionDescription const & description); + DescriptionInfoset const & description); // throws css::uno::RuntimeException, // css::deployment::DeploymentException ::sal_Bool checkLicense( css::uno::Reference< css::ucb::XCommandEnvironment > const & xCmdEnv, - ExtensionDescription const& description, bool bInstalled, + DescriptionInfoset const & description, bool bInstalled, OUString const & aContextName ) throw (css::deployment::DeploymentException, css::ucb::CommandFailedException, @@ -169,13 +170,8 @@ class BackendImpl : public ImplBaseT OUString const & url, OUString const & name, Reference<deployment::XPackageTypeInfo> const & xPackageType, - bool legacyBundle ) - : Package( myBackend, url, name, name /* display-name */, - xPackageType ), - m_url_expanded( expandUnoRcUrl( url ) ), - m_legacyBundle( legacyBundle ), - m_pBundle( 0 ) - {} + bool legacyBundle, + bool useDb); // XPackage virtual sal_Bool SAL_CALL isBundle() throw (RuntimeException); @@ -228,9 +224,16 @@ class BackendImpl : public ImplBaseT const Reference<deployment::XPackageTypeInfo> m_xLegacyBundleTypeInfo; Sequence< Reference<deployment::XPackageTypeInfo> > m_typeInfos; + std::auto_ptr<ExtensionBackendDb> m_backendDb; + + void addDataToDb(OUString const & url, ExtensionBackendDb::Data const & data); + ExtensionBackendDb::Data readDataFromDb(OUString const & url); + void deleteDataFromDb(OUString const & url); + // PackageRegistryBackend virtual Reference<deployment::XPackage> bindPackage_( OUString const & url, OUString const & mediaType, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ); virtual void SAL_CALL disposing(); @@ -291,6 +294,14 @@ BackendImpl::BackendImpl( { m_typeInfos[ 0 ] = m_xBundleTypeInfo; m_typeInfos[ 1 ] = m_xLegacyBundleTypeInfo; + + if (!transientMode()) + { + OUString dbFile = makeURL(getCachePath(), getImplementationName()); + dbFile = makeURL(dbFile, OUSTR("backenddb.xml")); + m_backendDb.reset( + new ExtensionBackendDb(getComponentContext(), dbFile)); + } } //______________________________________________________________________________ @@ -333,6 +344,7 @@ BackendImpl::getSupportedPackageTypes() throw (RuntimeException) //______________________________________________________________________________ Reference<deployment::XPackage> BackendImpl::bindPackage_( OUString const & url, OUString const & mediaType_, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) { OUString mediaType( mediaType_ ); @@ -381,19 +393,21 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( { if (type.EqualsIgnoreCaseAscii("application")) { - ::ucbhelper::Content ucbContent( url, xCmdEnv ); + ::ucbhelper::Content ucbContent; + OUString name; + //In case a XPackage is created for a removed extension, we cannot + //obtain the name + if (create_ucb_content(&ucbContent, url, xCmdEnv, false )) + name = ucbContent.getPropertyValue( + StrTitle::get() ).get<OUString>(); if (subType.EqualsIgnoreCaseAscii("vnd.sun.star.package-bundle")) { return new PackageImpl( - this, url, ucbContent.getPropertyValue( - StrTitle::get() ).get<OUString>(), - m_xBundleTypeInfo, false ); + this, url, name, m_xBundleTypeInfo, false, bNoFileAccess); } else if (subType.EqualsIgnoreCaseAscii( "vnd.sun.star.legacy-package-bundle")) { return new PackageImpl( - this, url, ucbContent.getPropertyValue( - StrTitle::get() ).get<OUString>(), - m_xLegacyBundleTypeInfo, true ); + this, url, name, m_xLegacyBundleTypeInfo, true, bNoFileAccess); } } } @@ -403,8 +417,48 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( static_cast<sal_Int16>(-1) ); } +void BackendImpl::addDataToDb( + OUString const & url, ExtensionBackendDb::Data const & data) +{ + if (m_backendDb.get()) + m_backendDb->addEntry(url, data); +} + +ExtensionBackendDb::Data BackendImpl::readDataFromDb( + OUString const & url) +{ + ExtensionBackendDb::Data data; + if (m_backendDb.get()) + data = m_backendDb->getEntry(url); + return data; +} + +void BackendImpl::deleteDataFromDb(OUString const & url) +{ + if (m_backendDb.get()) + m_backendDb->removeEntry(url); +} + + //############################################################################## +BackendImpl::PackageImpl::PackageImpl( + ::rtl::Reference<PackageRegistryBackend> const & myBackend, + OUString const & url, + OUString const & name, + Reference<deployment::XPackageTypeInfo> const & xPackageType, + bool legacyBundle, + bool useDb) + : Package( myBackend, url, name, name /* display-name */, + xPackageType, useDb ), + m_url_expanded( expandUnoRcUrl( url ) ), + m_legacyBundle( legacyBundle ), + m_pBundle( 0 ) +{ + if (useDb) + m_data = getMyBackend()->readDataFromDb(url); +} + BackendImpl * BackendImpl::PackageImpl::getMyBackend() const { BackendImpl * pBackend = static_cast<BackendImpl *>(m_myBackend.get()); @@ -510,23 +564,7 @@ OUString BackendImpl::PackageImpl::getTextFromURL( DescriptionInfoset BackendImpl::PackageImpl::getDescriptionInfoset() { - css::uno::Reference< css::xml::dom::XNode > root; - try { - root = - ExtensionDescription( - getMyBackend()->getComponentContext(), m_url_expanded, - css::uno::Reference< css::ucb::XCommandEnvironment >()). - getRootElement(); - } catch (NoDescriptionException &) { - } catch (css::deployment::DeploymentException & e) { - throw RuntimeException( - (OUString( - RTL_CONSTASCII_USTRINGPARAM( - "com.sun.star.deployment.DeploymentException: ")) + - e.Message), - static_cast< OWeakObject * >(this)); - } - return DescriptionInfoset(getMyBackend()->getComponentContext(), root); + return dp_misc::getDescriptionInfoset(m_url_expanded); } bool BackendImpl::PackageImpl::checkPlatform( @@ -561,14 +599,11 @@ bool BackendImpl::PackageImpl::checkPlatform( bool BackendImpl::PackageImpl::checkDependencies( css::uno::Reference< css::ucb::XCommandEnvironment > const & environment, - ExtensionDescription const & description) + DescriptionInfoset const & description) { css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > - unsatisfied( - dp_misc::Dependencies::check( - DescriptionInfoset( - getMyBackend()->getComponentContext(), - description.getRootElement()))); + unsatisfied(dp_misc::Dependencies::check(description)); + if (unsatisfied.getLength() == 0) { return true; } else { @@ -590,7 +625,7 @@ bool BackendImpl::PackageImpl::checkDependencies( ::sal_Bool BackendImpl::PackageImpl::checkLicense( css::uno::Reference< css::ucb::XCommandEnvironment > const & xCmdEnv, - ExtensionDescription const & desc, bool bInstalled, OUString const & aContextName) + DescriptionInfoset const & info, bool bInstalled, OUString const & aContextName) throw (css::deployment::DeploymentException, css::ucb::CommandFailedException, css::ucb::CommandAbortedException, @@ -598,7 +633,6 @@ bool BackendImpl::PackageImpl::checkDependencies( { try { - DescriptionInfoset info = getDescriptionInfoset(); ::boost::optional<SimpleLicenseAttributes> simplLicAttr = info.getSimpleLicenseAttributes(); if (! simplLicAttr) @@ -610,7 +644,7 @@ bool BackendImpl::PackageImpl::checkDependencies( if (sLic.getLength() == 0) throw css::deployment::DeploymentException( OUSTR("Could not obtain path to license. Possible error in description.xml"), 0, Any()); - OUString sHref = desc.getExtensionRootUrl() + OUSTR("/") + sLic; + OUString sHref = m_url_expanded + OUSTR("/") + sLic; OUString sLicense = getTextFromURL(xCmdEnv, sHref); ////determine who has to agree to the license //check correct value for attribute @@ -693,19 +727,13 @@ bool BackendImpl::PackageImpl::checkDependencies( css::ucb::CommandAbortedException, css::uno::RuntimeException) { - std::auto_ptr<ExtensionDescription> spDescription; - try { - spDescription.reset( - new ExtensionDescription( - getMyBackend()->getComponentContext(), - m_url_expanded, - xCmdEnv)); - } catch (NoDescriptionException& ) { + DescriptionInfoset info = getDescriptionInfoset(); + if (!info.hasDescription()) return sal_True; - } + return checkPlatform(xCmdEnv) - && checkDependencies(xCmdEnv, *spDescription) - && checkLicense(xCmdEnv, *spDescription, bInstalled, aContextName); + && checkDependencies(xCmdEnv, info) + && checkLicense(xCmdEnv, info, bInstalled, aContextName); } ::sal_Bool BackendImpl::PackageImpl::checkDependencies( @@ -714,23 +742,25 @@ bool BackendImpl::PackageImpl::checkDependencies( css::ucb::CommandFailedException, css::uno::RuntimeException) { - std::auto_ptr<ExtensionDescription> spDescription; - try { - spDescription.reset( - new ExtensionDescription( getMyBackend()->getComponentContext(), m_url_expanded, xCmdEnv )); - } catch (NoDescriptionException& ) { + DescriptionInfoset info = getDescriptionInfoset(); + if (!info.hasDescription()) return sal_True; - } - return checkDependencies(xCmdEnv, *spDescription); + + return checkDependencies(xCmdEnv, info); } beans::Optional<OUString> BackendImpl::PackageImpl::getIdentifier() throw (RuntimeException) { + OUString identifier; + if (m_bUseDb) + identifier = m_data.identifier; + else + identifier = dp_misc::generateIdentifier( + getDescriptionInfoset().getIdentifier(), m_name); + return beans::Optional<OUString>( - true, - dp_misc::generateIdentifier( - getDescriptionInfoset().getIdentifier(), m_name)); + true, identifier); } OUString BackendImpl::PackageImpl::getVersion() throw (RuntimeException) @@ -793,6 +823,7 @@ void BackendImpl::PackageImpl::processPackage_( if (doRegisterPackage) { + ExtensionBackendDb::Data data; const sal_Int32 len = bundle.getLength(); for ( sal_Int32 pos = 0; pos < len; ++pos ) { @@ -870,7 +901,12 @@ void BackendImpl::PackageImpl::processPackage_( ::cppu::throwException(exc); } } + data.items.push_back( + ::std::make_pair(xPackage->getURL(), + xPackage->getPackageType()->getMediaType())); } + data.identifier = getIdentifier().Value; + getMyBackend()->addDataToDb(getURL(), data); } else { @@ -914,6 +950,7 @@ void BackendImpl::PackageImpl::processPackage_( // selected } } + getMyBackend()->deleteDataFromDb(getURL()); } } @@ -1139,58 +1176,66 @@ Sequence< Reference<deployment::XPackage> > BackendImpl::PackageImpl::getBundle( if (pBundle == 0) { t_packagevec bundle; - try { - if (m_legacyBundle) - { - // .zip legacy packages allow script.xlb, dialog.xlb in bundle - // root folder: - OUString mediaType; - // probe for script.xlb: - if (create_ucb_content( - 0, makeURL( m_url_expanded, OUSTR("script.xlb") ), - xCmdEnv, false /* no throw */ )) { - mediaType = OUSTR("application/vnd.sun.star.basic-library"); + if (m_bUseDb) + { + bundle = getPackagesFromDb(); + } + else + { + try { + if (m_legacyBundle) + { + // .zip legacy packages allow script.xlb, dialog.xlb in bundle + // root folder: + OUString mediaType; + // probe for script.xlb: + if (create_ucb_content( + 0, makeURL( m_url_expanded, OUSTR("script.xlb") ), + xCmdEnv, false /* no throw */ )) { + mediaType = OUSTR("application/vnd.sun.star.basic-library"); + } + // probe for dialog.xlb: + else if (create_ucb_content( + 0, makeURL( m_url_expanded, OUSTR("dialog.xlb") ), + xCmdEnv, false /* no throw */ )) + mediaType = OUSTR("application/vnd.sun.star." + "dialog-library"); + + if (mediaType.getLength() > 0) { + const Reference<deployment::XPackage> xPackage( + bindBundleItem( getURL(), mediaType, xCmdEnv ) ); + if (xPackage.is()) + bundle.push_back( xPackage ); + // continue scanning: + } + scanLegacyBundle( bundle, getURL(), + AbortChannel::get(xAbortChannel), xCmdEnv ); } - // probe for dialog.xlb: - else if (create_ucb_content( - 0, makeURL( m_url_expanded, OUSTR("dialog.xlb") ), - xCmdEnv, false /* no throw */ )) - mediaType = OUSTR("application/vnd.sun.star." - "dialog-library"); - - if (mediaType.getLength() > 0) { - const Reference<deployment::XPackage> xPackage( - bindBundleItem( getURL(), mediaType, xCmdEnv ) ); - if (xPackage.is()) - bundle.push_back( xPackage ); - // continue scanning: + else + { + // .oxt: + scanBundle( bundle, AbortChannel::get(xAbortChannel), xCmdEnv ); } - scanLegacyBundle( bundle, getURL(), - AbortChannel::get(xAbortChannel), xCmdEnv ); + } - else - { - // .oxt: - scanBundle( bundle, AbortChannel::get(xAbortChannel), xCmdEnv ); + catch (RuntimeException &) { + throw; + } + catch (CommandFailedException &) { + throw; + } + catch (CommandAbortedException &) { + throw; + } + catch (deployment::DeploymentException &) { + throw; + } + catch (Exception &) { + Any exc( ::cppu::getCaughtException() ); + throw deployment::DeploymentException( + OUSTR("error scanning bundle: ") + getURL(), + static_cast<OWeakObject *>(this), exc ); } - } - catch (RuntimeException &) { - throw; - } - catch (CommandFailedException &) { - throw; - } - catch (CommandAbortedException &) { - throw; - } - catch (deployment::DeploymentException &) { - throw; - } - catch (Exception &) { - Any exc( ::cppu::getCaughtException() ); - throw deployment::DeploymentException( - OUSTR("error scanning bundle: ") + getURL(), - static_cast<OWeakObject *>(this), exc ); } // sort: schema before config data, typelibs before components: @@ -1267,7 +1312,7 @@ Reference<deployment::XPackage> BackendImpl::PackageImpl::bindBundleItem( Reference<deployment::XPackage>xPackage; try { xPackage.set( getMyBackend()->m_xRootRegistry->bindPackage( - url, mediaType, xCmdEnv ) ); + url, mediaType, false, xCmdEnv ) ); OSL_ASSERT( xPackage.is() ); } catch (RuntimeException &) { @@ -1523,6 +1568,13 @@ OUString BackendImpl::PackageImpl::getDisplayName() throw (RuntimeException) return sName; } +::std::vector<Reference<deployment::XPackage> > BackendImpl::PackageImpl::getPackagesFromDb() +{ + //get the data base entry for this extension + + return ::std::vector<Reference<deployment::XPackage> >(); +} + } // anon namespace //============================================================================== diff --git a/desktop/source/deployment/registry/package/makefile.mk b/desktop/source/deployment/registry/package/makefile.mk index ccadc2070301..203ce176d289 100644 --- a/desktop/source/deployment/registry/package/makefile.mk +++ b/desktop/source/deployment/registry/package/makefile.mk @@ -41,7 +41,7 @@ INCPRE += ..$/..$/inc SLOFILES = \ $(SLO)$/dp_package.obj \ - $(SLO)$/dp_description.obj + $(SLO)$/dp_extbackenddb.obj .INCLUDE : ..$/..$/target.pmk .INCLUDE : target.mk diff --git a/desktop/source/deployment/registry/script/dp_script.cxx b/desktop/source/deployment/registry/script/dp_script.cxx index 4af0cbb84130..6d503d33d51d 100644 --- a/desktop/source/deployment/registry/script/dp_script.cxx +++ b/desktop/source/deployment/registry/script/dp_script.cxx @@ -88,13 +88,15 @@ class BackendImpl : public t_helper ::rtl::Reference<BackendImpl> const & myBackend, OUString const & url, Reference<XCommandEnvironment> const &xCmdEnv, - OUString const & scriptURL, OUString const & dialogURL ); + OUString const & scriptURL, OUString const & dialogURL, + bool bUseDb); }; friend class PackageImpl; // PackageRegistryBackend virtual Reference<deployment::XPackage> bindPackage_( OUString const & url, OUString const & mediaType, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ); rtl::OUString getRegisteredFlagFileURL( Reference< deployment::XPackage > xPackage ); @@ -123,11 +125,11 @@ BackendImpl::PackageImpl::PackageImpl( ::rtl::Reference<BackendImpl> const & myBackend, OUString const & url, Reference<XCommandEnvironment> const &xCmdEnv, - OUString const & scriptURL, OUString const & dialogURL ) + OUString const & scriptURL, OUString const & dialogURL, bool bUseDb ) : Package( myBackend.get(), url, OUString(), OUString(), // will be late-initialized scriptURL.getLength() > 0 ? myBackend->m_xBasicLibTypeInfo - : myBackend->m_xDialogLibTypeInfo ), + : myBackend->m_xDialogLibTypeInfo, bUseDb), m_scriptURL( scriptURL ), m_dialogURL( dialogURL ) { @@ -189,6 +191,7 @@ BackendImpl::getSupportedPackageTypes() throw (RuntimeException) //______________________________________________________________________________ Reference<deployment::XPackage> BackendImpl::bindPackage_( OUString const & url, OUString const & mediaType_, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) { OUString mediaType( mediaType_ ); @@ -231,13 +234,15 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( } return new PackageImpl( this, url, xCmdEnv, makeURL( url, OUSTR("script.xlb") ), - dialogURL ); + dialogURL, bNoFileAccess); } else if (subType.EqualsIgnoreCaseAscii( "vnd.sun.star.dialog-library")) { - return new PackageImpl( this, url, xCmdEnv, - OUString() /* no script lib */, - makeURL( url, OUSTR("dialog.xlb") ) ); + return new PackageImpl( + this, url, xCmdEnv, + OUString() /* no script lib */, + makeURL( url, OUSTR("dialog.xlb") ), + bNoFileAccess); } } } diff --git a/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx b/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx index 52ced6908bd8..47b6430f1a1e 100644 --- a/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx +++ b/desktop/source/deployment/registry/sfwk/dp_sfwk.cxx @@ -81,8 +81,9 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend Reference<XCommandEnvironment> const & xCmdEnv ); public: - PackageImpl( ::rtl::Reference<BackendImpl> const & myBackend, - OUString const & url, OUString const & libType ); + PackageImpl( + ::rtl::Reference<BackendImpl> const & myBackend, + OUString const & url, OUString const & libType, bool bUseDb); // XPackage virtual OUString SAL_CALL getDescription() throw (RuntimeException); }; @@ -91,6 +92,7 @@ class BackendImpl : public ::dp_registry::backend::PackageRegistryBackend // PackageRegistryBackend virtual Reference<deployment::XPackage> bindPackage_( OUString const & url, OUString const & mediaType, + sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ); const Reference<deployment::XPackageTypeInfo> m_xTypeInfo; @@ -131,9 +133,9 @@ OUString BackendImpl::PackageImpl::getDescription() throw (RuntimeException) //______________________________________________________________________________ BackendImpl::PackageImpl::PackageImpl( ::rtl::Reference<BackendImpl> const & myBackend, - OUString const & url, OUString const & libType ) + OUString const & url, OUString const & libType, bool bUseDb) : Package( myBackend.get(), url, OUString(), OUString(), - myBackend->m_xTypeInfo ), + myBackend->m_xTypeInfo, bUseDb ), m_descr(libType) { initPackageHandler(); @@ -217,7 +219,7 @@ BackendImpl::getSupportedPackageTypes() throw (RuntimeException) // PackageRegistryBackend //______________________________________________________________________________ Reference<deployment::XPackage> BackendImpl::bindPackage_( - OUString const & url, OUString const & mediaType_, + OUString const & url, OUString const & mediaType_, sal_Bool bNoFileAccess, Reference<XCommandEnvironment> const & xCmdEnv ) { OUString mediaType( mediaType_ ); @@ -294,7 +296,7 @@ Reference<deployment::XPackage> BackendImpl::bindPackage_( dp_misc::TRACE(OUSTR(" BackEnd detected lang = ") + lang + OUSTR("\n")); dp_misc::TRACE(OUSTR(" for url ") + sParcelDescURL + OUSTR("\n") ); dp_misc::TRACE("******************************\n"); - return new PackageImpl( this, url, sfwkLibType ); + return new PackageImpl( this, url, sfwkLibType, bNoFileAccess); } } } @@ -322,6 +324,10 @@ void BackendImpl::PackageImpl:: initPackageHandler() { aContext <<= OUSTR("share"); } + else if ( that->m_eContext == CONTEXT_BUNDLED ) + { + aContext <<= OUSTR("bundled"); + } else { OSL_ASSERT( 0 ); diff --git a/desktop/source/pkgchk/unopkg/unopkg_app.cxx b/desktop/source/pkgchk/unopkg/unopkg_app.cxx index 2acd4f79a781..807260fe4663 100644 --- a/desktop/source/pkgchk/unopkg/unopkg_app.cxx +++ b/desktop/source/pkgchk/unopkg/unopkg_app.cxx @@ -41,7 +41,8 @@ #include "cppuhelper/implbase1.hxx" #include "cppuhelper/exc_hlp.hxx" #include "comphelper/anytostring.hxx" -#include "com/sun/star/deployment/thePackageManagerFactory.hpp" +#include "com/sun/star/deployment/ExtensionManager.hpp" + #include "com/sun/star/deployment/ui/PackageManagerDialog.hpp" #include "com/sun/star/ui/dialogs/XExecutableDialog.hpp" #include "com/sun/star/lang/DisposedException.hpp" @@ -149,12 +150,13 @@ void DialogClosedListenerImpl::dialogClosed( // installed with OOo 2.2 or later could not normally be found via its file // name. Reference<deployment::XPackage> findPackage( - Reference<deployment::XPackageManager> const & manager, + OUString const & repository, + Reference<deployment::XExtensionManager> const & manager, Reference<ucb::XCommandEnvironment > const & environment, OUString const & idOrFileName ) { Sequence< Reference<deployment::XPackage> > ps( - manager->getDeployedPackages( + manager->getDeployedExtensions(repository, Reference<task::XAbortChannel>(), environment ) ); for ( sal_Int32 i = 0; i < ps.getLength(); ++i ) if ( dp_misc::getIdentifier( ps[i] ) == idOrFileName ) @@ -214,7 +216,7 @@ extern "C" int unopkg_main() bool subcmd_add = false; bool subcmd_gui = false; OUString logFile; - OUString deploymentContext; + OUString repository; OUString cmdArg; ::std::vector<OUString> cmdPackages; @@ -279,7 +281,7 @@ extern "C" int unopkg_main() !readOption( &option_force, info_force, &nPos ) && !readOption( &option_bundled, info_bundled, &nPos ) && !readOption( &option_suppressLicense, info_suppressLicense, &nPos ) && - !readArgument( &deploymentContext, info_context, &nPos ) && + !readArgument( &repository, info_context, &nPos ) && !isBootstrapVariable(&nPos)) { osl_getCommandArg( nPos, &cmdArg.pData ); @@ -313,24 +315,30 @@ extern "C" int unopkg_main() } //make sure the bundled option was provided together with shared - if (option_bundled && !option_shared) - { - dp_misc::writeConsoleError( - "\nERROR: option --bundled can only be used together with --shared!"); - return 1; - } +// if (option_bundled && !option_shared) +// { +// dp_misc::writeConsoleError( +// "\nERROR: option --bundled can only be used together with --shared!"); +// return 1; +// } xComponentContext = getUNO( disposeGuard, option_verbose, option_shared, subcmd_gui, xLocalComponentContext ); - if (deploymentContext.getLength() == 0) { - deploymentContext = option_shared ? OUSTR("shared") : OUSTR("user"); + if (repository.getLength() == 0) + { + if (option_shared) + repository = OUSTR("shared"); + else if (option_bundled) + repository = OUSTR("bundled"); + else + repository = OUSTR("user"); } else { - if (deploymentContext.equalsAsciiL( + if (repository.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) { option_shared = true; } @@ -343,10 +351,9 @@ extern "C" int unopkg_main() } } - Reference<deployment::XPackageManagerFactory> xPackageManagerFactory( - deployment::thePackageManagerFactory::get( xComponentContext ) ); - Reference<deployment::XPackageManager> xPackageManager( - xPackageManagerFactory->getPackageManager( deploymentContext ) ); + + Reference<deployment::XExtensionManager> xExtensionManager( + deployment::ExtensionManager::get( xComponentContext ) ); Reference< ::com::sun::star::ucb::XCommandEnvironment > xCmdEnv( createCmdEnv( xComponentContext, logFile, @@ -362,25 +369,23 @@ extern "C" int unopkg_main() OUString const & cmdPackage = cmdPackages[ pos ]; if (subcmd_add) { - Reference<deployment::XPackage> xPackage( - xPackageManager->addPackage( - cmdPackage, OUString() /* to be detected */, - Reference<task::XAbortChannel>(), xCmdEnv ) ); - OSL_ASSERT( xPackage.is() ); + xExtensionManager->addExtension( + cmdPackage, repository, + Reference<task::XAbortChannel>(), xCmdEnv); } else { try { - xPackageManager->removePackage( - cmdPackage, cmdPackage, + xExtensionManager->removeExtension( + cmdPackage, cmdPackage, repository, Reference<task::XAbortChannel>(), xCmdEnv ); } catch (lang::IllegalArgumentException &) { Reference<deployment::XPackage> p( - findPackage( - xPackageManager, xCmdEnv, cmdPackage ) ); + findPackage(repository, + xExtensionManager, xCmdEnv, cmdPackage ) ); //Todo. temporary preventing exception in bundled case. //In case of a bundled extension, remove would be called as a result of //uninstalling a rpm. Then we do not want to show an error when the @@ -389,8 +394,9 @@ extern "C" int unopkg_main() if ( !p.is() && !option_bundled) throw; else if (p.is()) - xPackageManager->removePackage( + xExtensionManager->removeExtension( ::dp_misc::getIdentifier(p), p->getName(), + repository, Reference<task::XAbortChannel>(), xCmdEnv ); } } @@ -399,18 +405,18 @@ extern "C" int unopkg_main() else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("reinstall") )) { - xPackageManager->reinstallDeployedPackages( - Reference<task::XAbortChannel>(), xCmdEnv ); + xExtensionManager->reinstallDeployedExtensions( + repository, Reference<task::XAbortChannel>(), xCmdEnv); } else if (subCommand.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("list") )) { Sequence< Reference<deployment::XPackage> > packages; if (cmdPackages.empty()) { - packages = xPackageManager->getDeployedPackages( - Reference<task::XAbortChannel>(), xCmdEnv ); + packages = xExtensionManager->getDeployedExtensions( + repository, Reference<task::XAbortChannel>(), xCmdEnv ); dp_misc::writeConsole( - OUSTR("all deployed ") + deploymentContext + OUSTR(" packages:\n")); + OUSTR("all deployed ") + repository + OUSTR(" packages:\n")); } else { @@ -418,13 +424,13 @@ extern "C" int unopkg_main() for ( ::std::size_t pos = 0; pos < cmdPackages.size(); ++pos ) try { - packages[ pos ] = xPackageManager->getDeployedPackage( - cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); + packages[ pos ] = xExtensionManager->getDeployedExtension( + repository, cmdPackages[ pos ], cmdPackages[ pos ], xCmdEnv ); } catch (lang::IllegalArgumentException &) { - packages[ pos ] = findPackage( - xPackageManager, xCmdEnv, cmdPackages[ pos ] ); + packages[ pos ] = findPackage(repository, + xExtensionManager, xCmdEnv, cmdPackages[ pos ] ); if ( !packages[ pos ].is() ) throw; } diff --git a/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx b/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx index e4a503d98732..d23dcbf9577d 100644 --- a/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx +++ b/desktop/source/pkgchk/unopkg/unopkg_cmdenv.cxx @@ -320,7 +320,7 @@ void CommandEnvironmentImpl::handle( deployment::VersionException nc_exc; if (request >>= nc_exc) { approve = m_option_force_overwrite || - (::dp_misc::comparePackageVersions(nc_exc.New, nc_exc.Deployed) + (::dp_misc::compareVersions(nc_exc.NewVersion, nc_exc.Deployed->getVersion()) == ::dp_misc::GREATER); abort = !approve; } |