2010-05-04 12:37:01 +02:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
|
|
|
* 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"
|
2010-04-20 10:04:52 +02:00
|
|
|
#include "com/sun/star/util/XModifyBroadcaster.hpp"
|
2010-05-04 12:37:01 +02:00
|
|
|
#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"
|
2010-04-19 11:33:33 +02:00
|
|
|
#include "dp_descriptioninfoset.hxx"
|
2010-05-04 12:37:01 +02:00
|
|
|
#include "dp_extensionmanager.hxx"
|
2010-04-19 11:33:33 +02:00
|
|
|
#include "dp_commandenvironments.hxx"
|
|
|
|
#include "dp_properties.hxx"
|
2010-04-20 10:04:52 +02:00
|
|
|
#include "boost/bind.hpp"
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
#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;
|
2010-04-20 10:04:52 +02:00
|
|
|
namespace util = com::sun::star::util;
|
2010-05-04 12:37:01 +02:00
|
|
|
namespace css = com::sun::star;
|
|
|
|
|
2010-04-20 10:04:52 +02:00
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
//#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();
|
|
|
|
}
|
2010-05-21 09:42:27 +02:00
|
|
|
|
|
|
|
void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const & xCmdEnv)
|
|
|
|
{
|
|
|
|
//Write the lastmodified file
|
|
|
|
try {
|
|
|
|
::rtl::Bootstrap::expandMacros(url);
|
|
|
|
::ucbhelper::Content ucbStamp(url, xCmdEnv );
|
|
|
|
dp_misc::erase_path( url, 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") + url, 0, exc);
|
|
|
|
}
|
|
|
|
}
|
2010-10-07 17:20:55 +02:00
|
|
|
|
|
|
|
class ExtensionRemoveGuard
|
|
|
|
{
|
|
|
|
css::uno::Reference<css::deployment::XPackage> m_extension;
|
|
|
|
css::uno::Reference<css::deployment::XPackageManager> m_xPackageManager;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ExtensionRemoveGuard(
|
|
|
|
css::uno::Reference<css::deployment::XPackage> const & extension,
|
|
|
|
css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager):
|
|
|
|
m_extension(extension), m_xPackageManager(xPackageManager) {}
|
|
|
|
~ExtensionRemoveGuard();
|
|
|
|
|
|
|
|
void reset(css::uno::Reference<css::deployment::XPackage> const & extension) {
|
|
|
|
m_extension = extension;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ExtensionRemoveGuard::~ExtensionRemoveGuard()
|
|
|
|
{
|
|
|
|
try {
|
|
|
|
if (m_xPackageManager.is() && m_extension.is())
|
|
|
|
m_xPackageManager->removePackage(
|
|
|
|
dp_misc::getIdentifier(m_extension), ::rtl::OUString(),
|
|
|
|
css::uno::Reference<css::task::XAbortChannel>(),
|
|
|
|
css::uno::Reference<css::ucb::XCommandEnvironment>());
|
|
|
|
} catch (...) {
|
|
|
|
OSL_ASSERT(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
} //end namespace
|
|
|
|
|
|
|
|
namespace dp_manager {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//ToDo: bundled extension
|
|
|
|
ExtensionManager::ExtensionManager( Reference< uno::XComponentContext > const& xContext) :
|
2010-04-20 10:04:52 +02:00
|
|
|
::cppu::WeakComponentImplHelper1< css::deployment::XExtensionManager >(getMutex()),
|
2010-05-04 12:37:01 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-04-19 11:33:33 +02:00
|
|
|
css::uno::Reference<css::deployment::XPackageManager>
|
|
|
|
ExtensionManager::getPackageManager(::rtl::OUString const & repository)
|
|
|
|
throw (css::lang::IllegalArgumentException)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
return xPackageManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
/*
|
|
|
|
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(
|
2010-05-28 17:50:38 +02:00
|
|
|
OUString const & identifier, OUString const & fileName,
|
2010-06-01 16:20:28 +02:00
|
|
|
Reference< ucb::XCommandEnvironment> const & /*xCmdEnv*/)
|
2010-05-04 12:37:01 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
::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;
|
|
|
|
}
|
|
|
|
|
2010-05-28 17:50:38 +02:00
|
|
|
uno::Sequence<Reference<deploy::XPackage> >
|
|
|
|
ExtensionManager::getExtensionsWithSameIdentifier(
|
|
|
|
OUString const & identifier,
|
|
|
|
OUString const & fileName,
|
|
|
|
Reference< ucb::XCommandEnvironment> const & xCmdEnv )
|
|
|
|
throw (
|
|
|
|
deploy::DeploymentException,
|
|
|
|
ucb::CommandFailedException,
|
|
|
|
lang::IllegalArgumentException,
|
|
|
|
uno::RuntimeException)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
::std::list<Reference<deploy::XPackage> > listExtensions =
|
|
|
|
getExtensionsWithSameId(
|
|
|
|
identifier, fileName, xCmdEnv);
|
|
|
|
sal_Bool bHasExtension = false;
|
|
|
|
|
|
|
|
//throw an IllegalArgumentException if there is no extension at all.
|
|
|
|
typedef ::std::list<Reference<deploy::XPackage> >::const_iterator CIT;
|
|
|
|
for (CIT i = listExtensions.begin(); i != listExtensions.end(); i++)
|
|
|
|
bHasExtension |= i->is();
|
|
|
|
if (!bHasExtension)
|
|
|
|
throw lang::IllegalArgumentException(
|
|
|
|
OUSTR("Could not find extension: ") + identifier + OUSTR(", ") + fileName,
|
|
|
|
static_cast<cppu::OWeakObject*>(this), -1);
|
|
|
|
|
|
|
|
return comphelper::containerToSequence<
|
|
|
|
Reference<deploy::XPackage>,
|
|
|
|
::std::list<Reference<deploy::XPackage> >
|
|
|
|
> (listExtensions);
|
|
|
|
}
|
|
|
|
catch (deploy::DeploymentException & )
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
catch ( ucb::CommandFailedException & )
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
catch (lang::IllegalArgumentException &)
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
uno::Any exc = ::cppu::getCaughtException();
|
|
|
|
throw deploy::DeploymentException(
|
|
|
|
OUSTR("Extension Manager: exception during getExtensionsWithSameIdentifier"),
|
|
|
|
static_cast<OWeakObject*>(this), exc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
|
|
|
|
|
2010-04-21 16:04:34 +02:00
|
|
|
bool ExtensionManager::isUserDisabled(
|
|
|
|
OUString const & identifier, OUString const & fileName)
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-05-28 17:50:38 +02:00
|
|
|
::std::list<Reference<deploy::XPackage> > listExtensions;
|
|
|
|
|
|
|
|
try {
|
|
|
|
listExtensions = getExtensionsWithSameId(identifier, fileName);
|
|
|
|
} catch (lang::IllegalArgumentException & ) {
|
|
|
|
}
|
2010-04-21 16:04:34 +02:00
|
|
|
OSL_ASSERT(listExtensions.size() == 3);
|
|
|
|
|
|
|
|
return isUserDisabled( ::comphelper::containerToSequence<
|
|
|
|
Reference<deploy::XPackage>,
|
|
|
|
::std::list<Reference<deploy::XPackage> >
|
|
|
|
> (listExtensions));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ExtensionManager::isUserDisabled(
|
|
|
|
uno::Sequence<Reference<deploy::XPackage> > const & seqExtSameId)
|
|
|
|
{
|
|
|
|
OSL_ASSERT(seqExtSameId.getLength() == 3);
|
|
|
|
Reference<deploy::XPackage> const & userExtension = seqExtSameId[0];
|
|
|
|
if (userExtension.is())
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-04-21 16:04:34 +02:00
|
|
|
beans::Optional<beans::Ambiguous<sal_Bool> > reg =
|
|
|
|
userExtension->isRegistered(Reference<task::XAbortChannel>(),
|
|
|
|
Reference<ucb::XCommandEnvironment>());
|
|
|
|
//If the value is ambiguous is than we assume that the extension
|
|
|
|
//is enabled, but something went wrong during enabling. We do not
|
|
|
|
//automatically disable user extensions.
|
|
|
|
if (reg.IsPresent &&
|
|
|
|
! reg.Value.IsAmbiguous && ! reg.Value.Value)
|
|
|
|
return true;
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
2010-04-21 16:04:34 +02:00
|
|
|
return false;
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
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,
|
2010-04-21 16:04:34 +02:00
|
|
|
bool bUserDisabled,
|
|
|
|
bool bStartup,
|
2010-05-04 12:37:01 +02:00
|
|
|
Reference<task::XAbortChannel> const & xAbortChannel,
|
|
|
|
Reference<ucb::XCommandEnvironment> const & xCmdEnv )
|
|
|
|
{
|
2010-05-28 17:50:38 +02:00
|
|
|
::std::list<Reference<deploy::XPackage> > listExtensions;
|
|
|
|
try {
|
|
|
|
listExtensions = getExtensionsWithSameId(identifier, fileName);
|
|
|
|
} catch (lang::IllegalArgumentException &) {
|
|
|
|
}
|
2010-05-04 12:37:01 +02:00
|
|
|
OSL_ASSERT(listExtensions.size() == 3);
|
2010-04-19 11:33:33 +02:00
|
|
|
|
|
|
|
activateExtension(
|
|
|
|
::comphelper::containerToSequence<
|
|
|
|
Reference<deploy::XPackage>,
|
|
|
|
::std::list<Reference<deploy::XPackage> >
|
|
|
|
> (listExtensions),
|
2010-04-21 16:04:34 +02:00
|
|
|
bUserDisabled, bStartup, xAbortChannel, xCmdEnv);
|
2010-05-10 12:00:49 +02:00
|
|
|
|
|
|
|
fireModified();
|
2010-04-19 11:33:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ExtensionManager::activateExtension(
|
|
|
|
uno::Sequence<Reference<deploy::XPackage> > const & seqExt,
|
2010-04-21 16:04:34 +02:00
|
|
|
bool bUserDisabled,
|
|
|
|
bool bStartup,
|
2010-04-19 11:33:33 +02:00
|
|
|
Reference<task::XAbortChannel> const & xAbortChannel,
|
|
|
|
Reference<ucb::XCommandEnvironment> const & xCmdEnv )
|
|
|
|
{
|
2010-05-04 12:37:01 +02:00
|
|
|
bool bActive = false;
|
2010-04-19 11:33:33 +02:00
|
|
|
sal_Int32 len = seqExt.getLength();
|
|
|
|
for (sal_Int32 i = 0; i < len; i++)
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-04-19 11:33:33 +02:00
|
|
|
Reference<deploy::XPackage> const & aExt = seqExt[i];
|
|
|
|
if (aExt.is())
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
|
|
|
//get the registration value of the current iteration
|
|
|
|
beans::Optional<beans::Ambiguous<sal_Bool> > optReg =
|
2010-04-19 11:33:33 +02:00
|
|
|
aExt->isRegistered(xAbortChannel, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
//If nothing can be registered then break
|
|
|
|
if (!optReg.IsPresent)
|
|
|
|
break;
|
|
|
|
|
2010-04-21 16:04:34 +02:00
|
|
|
//Check if this is a disabled user extension,
|
|
|
|
if (i == 0 && bUserDisabled)
|
|
|
|
{
|
|
|
|
aExt->revokePackage(xAbortChannel, xCmdEnv);
|
|
|
|
continue;
|
|
|
|
}
|
2010-04-19 11:33:33 +02:00
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
//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)
|
|
|
|
{
|
2010-04-19 11:33:33 +02:00
|
|
|
aExt->revokePackage(xAbortChannel, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
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.
|
2010-04-21 16:04:34 +02:00
|
|
|
aExt->registerPackage(bStartup, xAbortChannel, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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(
|
2010-04-19 11:33:33 +02:00
|
|
|
xOldExtension->getURL(), uno::Sequence<beans::NamedValue>(),
|
|
|
|
OUString(), Reference<task::XAbortChannel>(), tmpCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
|
|
|
|
OSL_ENSURE(xBackup.is(), "Failed to backup extension");
|
|
|
|
}
|
|
|
|
return xBackup;
|
|
|
|
}
|
|
|
|
|
2010-05-17 10:40:52 +02:00
|
|
|
//The supported package types are actually determined by the registry. However
|
|
|
|
//creating a registry
|
|
|
|
//(desktop/source/deployment/registry/dp_registry.cxx:PackageRegistryImpl) will
|
|
|
|
//create all the backends, so that the registry can obtain from them the package
|
|
|
|
//types. Creating the registry will also set up the registry folder containing
|
|
|
|
//all the subfolders for the respective backends.
|
|
|
|
//Because all repositories support the same backends, we can just delegate this
|
|
|
|
//call to one of the repositories.
|
2010-05-04 12:37:01 +02:00
|
|
|
uno::Sequence< Reference<deploy::XPackageTypeInfo> >
|
2010-05-17 10:40:52 +02:00
|
|
|
ExtensionManager::getSupportedPackageTypes()
|
2010-05-04 12:37:01 +02:00
|
|
|
throw (uno::RuntimeException)
|
|
|
|
{
|
2010-05-17 10:40:52 +02:00
|
|
|
return m_userRepository->getSupportedPackageTypes();
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
|
2010-10-07 17:20:55 +02:00
|
|
|
bool ExtensionManager::doChecksForAddExtension(
|
|
|
|
Reference<deploy::XPackageManager> const & xPackageMgr,
|
|
|
|
uno::Sequence<beans::NamedValue> const & properties,
|
|
|
|
css::uno::Reference<css::deployment::XPackage> const & xTmpExtension,
|
|
|
|
Reference<task::XAbortChannel> const & xAbortChannel,
|
|
|
|
Reference<ucb::XCommandEnvironment> const & xCmdEnv,
|
|
|
|
Reference<deploy::XPackage> & out_existingExtension )
|
|
|
|
throw (deploy::DeploymentException,
|
|
|
|
ucb::CommandFailedException,
|
|
|
|
ucb::CommandAbortedException,
|
|
|
|
lang::IllegalArgumentException,
|
|
|
|
uno::RuntimeException)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Reference<deploy::XPackage> xOldExtension;
|
|
|
|
const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
|
|
|
|
const OUString sFileName = xTmpExtension->getName();
|
|
|
|
const OUString sDisplayName = xTmpExtension->getDisplayName();
|
|
|
|
const OUString sVersion = xTmpExtension->getVersion();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
xOldExtension = xPackageMgr->getDeployedPackage(
|
|
|
|
sIdentifier, sFileName, xCmdEnv);
|
|
|
|
out_existingExtension = xOldExtension;
|
|
|
|
}
|
|
|
|
catch (lang::IllegalArgumentException &)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
bool bCanInstall = false;
|
|
|
|
|
|
|
|
//This part is not guarded against other threads removing, adding, disabling ...
|
|
|
|
//etc. the same extension.
|
|
|
|
//checkInstall is safe because it notifies the user if the extension is not yet
|
|
|
|
//installed in the same repository. Because addExtension has its own guard
|
|
|
|
//(m_addMutex), another thread cannot add the extension in the meantime.
|
|
|
|
//checkUpdate is called if the same extension exists in the same
|
|
|
|
//repository. The user is asked if they want to replace it. Another
|
|
|
|
//thread
|
|
|
|
//could already remove the extension. So asking the user was not
|
|
|
|
//necessary. No harm is done. The other thread may also ask the user
|
|
|
|
//if he wants to remove the extension. This depends on the
|
|
|
|
//XCommandEnvironment which it passes to removeExtension.
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
//Prevent showing the license if requested.
|
|
|
|
Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv);
|
|
|
|
ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>());
|
|
|
|
|
|
|
|
dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL()));
|
|
|
|
const ::boost::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes =
|
|
|
|
info.getSimpleLicenseAttributes();
|
|
|
|
|
|
|
|
if (licenseAttributes && licenseAttributes->suppressIfRequired
|
|
|
|
&& props.isSuppressedLicense())
|
|
|
|
_xCmdEnv = Reference<ucb::XCommandEnvironment>(
|
|
|
|
new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler()));
|
|
|
|
|
|
|
|
bCanInstall = xTmpExtension->checkPrerequisites(
|
|
|
|
xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0 ? true : false;
|
|
|
|
|
|
|
|
return bCanInstall;
|
|
|
|
}
|
|
|
|
catch (deploy::DeploymentException& ) {
|
|
|
|
throw;
|
|
|
|
} catch (ucb::CommandFailedException & ) {
|
|
|
|
throw;
|
|
|
|
} catch (ucb::CommandAbortedException & ) {
|
|
|
|
throw;
|
|
|
|
} catch (lang::IllegalArgumentException &) {
|
|
|
|
throw;
|
|
|
|
} catch (uno::RuntimeException &) {
|
|
|
|
throw;
|
|
|
|
} catch (uno::Exception &) {
|
|
|
|
uno::Any excOccurred = ::cppu::getCaughtException();
|
|
|
|
deploy::DeploymentException exc(
|
|
|
|
OUSTR("Extension Manager: exception in doChecksForAddExtension"),
|
|
|
|
static_cast<OWeakObject*>(this), excOccurred);
|
|
|
|
throw exc;
|
|
|
|
} catch (...) {
|
|
|
|
throw uno::RuntimeException(
|
|
|
|
OUSTR("Extension Manager: unexpected exception in doChecksForAddExtension"),
|
|
|
|
static_cast<OWeakObject*>(this));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
// Only add to shared and user repository
|
|
|
|
Reference<deploy::XPackage> ExtensionManager::addExtension(
|
2010-04-19 11:33:33 +02:00
|
|
|
OUString const & url, uno::Sequence<beans::NamedValue> const & properties,
|
|
|
|
OUString const & repository,
|
2010-05-04 12:37:01 +02:00
|
|
|
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);
|
2010-10-07 17:20:55 +02:00
|
|
|
//We must make sure that the xTmpExtension is not create twice, because this
|
|
|
|
//would remove the first one.
|
|
|
|
::osl::MutexGuard addGuard(m_addMutex);
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
Reference<deploy::XPackage> xTmpExtension =
|
|
|
|
getTempExtension(url, xAbortChannel, xCmdEnv);
|
2010-10-07 17:20:55 +02:00
|
|
|
//Make sure the extension is removed from the tmp repository in case
|
|
|
|
//of an exception
|
|
|
|
ExtensionRemoveGuard tmpExtensionRemoveGuard(xTmpExtension, m_tmpRepository);
|
2010-05-04 12:37:01 +02:00
|
|
|
const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
|
|
|
|
const OUString sFileName = xTmpExtension->getName();
|
|
|
|
Reference<deploy::XPackage> xOldExtension;
|
|
|
|
Reference<deploy::XPackage> xExtensionBackup;
|
|
|
|
|
|
|
|
uno::Any excOccurred2;
|
2010-04-21 16:04:34 +02:00
|
|
|
bool bUserDisabled = false;
|
2010-10-07 17:20:55 +02:00
|
|
|
bool bCanInstall = doChecksForAddExtension(
|
|
|
|
xPackageManager,
|
|
|
|
properties,
|
|
|
|
xTmpExtension,
|
|
|
|
xAbortChannel,
|
|
|
|
xCmdEnv,
|
|
|
|
xOldExtension );
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-10-07 17:20:55 +02:00
|
|
|
// In this garded section (getMutex) we must not use the argument xCmdEnv
|
|
|
|
// because it may bring up dialogs (XInteractionHandler::handle) this
|
|
|
|
//may potententially deadlock. See issue
|
|
|
|
//http://qa.openoffice.org/issues/show_bug.cgi?id=114933
|
|
|
|
//By not providing xCmdEnv the underlying APIs will throw an exception if
|
|
|
|
//the XInteractionRequest cannot be handled
|
|
|
|
::osl::MutexGuard guard(getMutex());
|
|
|
|
|
|
|
|
if (bCanInstall)
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-10-07 17:20:55 +02:00
|
|
|
try
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-10-07 17:20:55 +02:00
|
|
|
bUserDisabled = isUserDisabled(sIdentifier, sFileName);
|
|
|
|
if (xOldExtension.is())
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
xOldExtension->revokePackage(
|
|
|
|
xAbortChannel, Reference<ucb::XCommandEnvironment>());
|
|
|
|
//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
|
|
|
|
//importing the old extension in the tmp repository will remove
|
|
|
|
//the xTmpExtension
|
|
|
|
//no command environment supplied, only this class shall interact
|
|
|
|
//with the user!
|
|
|
|
xExtensionBackup = m_tmpRepository->importExtension(
|
|
|
|
xOldExtension, Reference<task::XAbortChannel>(),
|
|
|
|
Reference<ucb::XCommandEnvironment>());
|
|
|
|
tmpExtensionRemoveGuard.reset(xExtensionBackup);
|
|
|
|
xTmpExtension = xExtensionBackup;
|
|
|
|
OSL_ASSERT(xTmpExtension.is());
|
|
|
|
}
|
|
|
|
catch (lang::DisposedException &)
|
|
|
|
{
|
|
|
|
//Another thread might have removed the extension meanwhile
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//check again dependencies but prevent user interaction,
|
|
|
|
//We can disregard the license, because the user must have already
|
|
|
|
//accepted it, whe we called checkPrerequisites the first time
|
|
|
|
SilentCheckPrerequisitesCommandEnv * pSilentCommandEnv =
|
|
|
|
new SilentCheckPrerequisitesCommandEnv();
|
|
|
|
Reference<ucb::XCommandEnvironment> silentCommandEnv(pSilentCommandEnv);
|
|
|
|
|
|
|
|
sal_Int32 failedPrereq = xTmpExtension->checkPrerequisites(
|
|
|
|
xAbortChannel, silentCommandEnv, true);
|
|
|
|
if (failedPrereq == 0)
|
|
|
|
{
|
|
|
|
xNewExtension = xPackageManager->addPackage(
|
|
|
|
url, properties, OUString(), xAbortChannel,
|
|
|
|
Reference<ucb::XCommandEnvironment>());
|
|
|
|
//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.
|
|
|
|
bool bUserDisabled2 = bUserDisabled;
|
|
|
|
if (repository.equals(OUSTR("user")))
|
|
|
|
bUserDisabled2 = false;
|
|
|
|
|
|
|
|
activateExtension(
|
|
|
|
dp_misc::getIdentifier(xNewExtension),
|
|
|
|
xNewExtension->getName(), bUserDisabled2, false, xAbortChannel,
|
|
|
|
Reference<ucb::XCommandEnvironment>());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pSilentCommandEnv->m_Exception.hasValue())
|
|
|
|
::cppu::throwException(pSilentCommandEnv->m_Exception);
|
|
|
|
else if ( pSilentCommandEnv->m_UnknownException.hasValue())
|
|
|
|
::cppu::throwException(pSilentCommandEnv->m_UnknownException);
|
|
|
|
else
|
|
|
|
throw deploy::DeploymentException (
|
|
|
|
OUSTR("Extension Manager: exception during addExtension, ckeckPrerequisites failed"),
|
|
|
|
static_cast<OWeakObject*>(this), uno::Any());
|
|
|
|
}
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
2010-10-07 17:20:55 +02:00
|
|
|
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;
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-07 17:20:55 +02:00
|
|
|
if (excOccurred2.hasValue())
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-10-07 17:20:55 +02:00
|
|
|
//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
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
|
|
|
Reference<ucb::XCommandEnvironment> tmpCmdEnv(
|
2010-10-07 17:20:55 +02:00
|
|
|
new TmpRepositoryCommandEnv());
|
|
|
|
if (xExtensionBackup.is())
|
|
|
|
{
|
|
|
|
Reference<deploy::XPackage> xRestored =
|
|
|
|
xPackageManager->importExtension(
|
|
|
|
xExtensionBackup, Reference<task::XAbortChannel>(),
|
|
|
|
tmpCmdEnv);
|
|
|
|
}
|
|
|
|
activateExtension(
|
|
|
|
sIdentifier, sFileName, bUserDisabled, false,
|
|
|
|
Reference<task::XAbortChannel>(), tmpCmdEnv);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
2010-10-07 17:20:55 +02:00
|
|
|
::cppu::throwException(excOccurred2);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
2010-10-07 17:20:55 +02:00
|
|
|
} // leaving the garded section (getMutex())
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
fireModified();
|
|
|
|
|
|
|
|
}catch (deploy::DeploymentException& ) {
|
|
|
|
throw;
|
2010-05-04 12:37:01 +02:00
|
|
|
} catch (ucb::CommandFailedException & ) {
|
2010-10-07 17:20:55 +02:00
|
|
|
throw;
|
2010-05-04 12:37:01 +02:00
|
|
|
} catch (ucb::CommandAbortedException & ) {
|
2010-10-07 17:20:55 +02:00
|
|
|
throw;
|
2010-05-04 12:37:01 +02:00
|
|
|
} catch (lang::IllegalArgumentException &) {
|
2010-10-07 17:20:55 +02:00
|
|
|
throw;
|
2010-05-04 12:37:01 +02:00
|
|
|
} catch (uno::RuntimeException &) {
|
2010-10-07 17:20:55 +02:00
|
|
|
throw;
|
|
|
|
} catch (uno::Exception &) {
|
|
|
|
uno::Any excOccurred = ::cppu::getCaughtException();
|
2010-05-04 12:37:01 +02:00
|
|
|
deploy::DeploymentException exc(
|
2010-10-07 17:20:55 +02:00
|
|
|
OUSTR("Extension Manager: exception in doChecksForAddExtension"),
|
|
|
|
static_cast<OWeakObject*>(this), excOccurred);
|
|
|
|
throw exc;
|
|
|
|
} catch (...) {
|
|
|
|
throw uno::RuntimeException(
|
|
|
|
OUSTR("Extension Manager: unexpected exception in doChecksForAddExtension"),
|
|
|
|
static_cast<OWeakObject*>(this));
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2010-04-21 16:04:34 +02:00
|
|
|
bool bUserDisabled = false;
|
|
|
|
::osl::MutexGuard guard(getMutex());
|
2010-05-04 12:37:01 +02:00
|
|
|
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);
|
|
|
|
|
2010-04-21 16:04:34 +02:00
|
|
|
bUserDisabled = isUserDisabled(identifier, fileName);
|
2010-05-04 12:37:01 +02:00
|
|
|
//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);
|
2010-04-21 16:04:34 +02:00
|
|
|
activateExtension(identifier, fileName, bUserDisabled, false,
|
|
|
|
xAbortChannel, xCmdEnv);
|
2010-04-20 10:04:52 +02:00
|
|
|
fireModified();
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
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(
|
2010-04-21 16:04:34 +02:00
|
|
|
identifier, fileName, bUserDisabled, false,
|
|
|
|
Reference<task::XAbortChannel>(),
|
2010-05-04 12:37:01 +02:00
|
|
|
tmpCmdEnv);
|
|
|
|
|
|
|
|
m_tmpRepository->removePackage(
|
|
|
|
dp_misc::getIdentifier(xExtensionBackup),
|
|
|
|
xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
|
2010-04-20 10:04:52 +02:00
|
|
|
fireModified();
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2010-04-21 16:04:34 +02:00
|
|
|
::osl::MutexGuard guard(getMutex());
|
|
|
|
bool bUserDisabled = false;
|
|
|
|
uno::Any excOccurred;
|
2010-05-04 12:37:01 +02:00
|
|
|
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);
|
|
|
|
|
2010-04-21 16:04:34 +02:00
|
|
|
bUserDisabled = isUserDisabled(dp_misc::getIdentifier(extension),
|
|
|
|
extension->getName());
|
2010-05-04 12:37:01 +02:00
|
|
|
|
|
|
|
activateExtension(dp_misc::getIdentifier(extension),
|
2010-04-21 16:04:34 +02:00
|
|
|
extension->getName(), false, false,
|
2010-04-19 11:33:33 +02:00
|
|
|
xAbortChannel, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
|
|
|
activateExtension(dp_misc::getIdentifier(extension),
|
2010-04-21 16:04:34 +02:00
|
|
|
extension->getName(), bUserDisabled, false,
|
2010-04-19 11:33:33 +02:00
|
|
|
xAbortChannel, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
::cppu::throwException(excOccurred);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-19 11:33:33 +02:00
|
|
|
/**
|
|
|
|
*/
|
2010-06-10 17:19:42 +02:00
|
|
|
sal_Int32 ExtensionManager::checkPrerequisitesAndEnable(
|
2010-04-19 11:33:33 +02:00
|
|
|
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 0;
|
2010-04-20 10:04:52 +02:00
|
|
|
::osl::MutexGuard guard(getMutex());
|
2010-04-19 11:33:33 +02:00
|
|
|
sal_Int32 ret = 0;
|
|
|
|
Reference<deploy::XPackageManager> mgr =
|
|
|
|
getPackageManager(extension->getRepositoryName());
|
|
|
|
ret = mgr->checkPrerequisites(extension, xAbortChannel, xCmdEnv);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
//There are some unfulfilled prerequisites, try to revoke
|
|
|
|
extension->revokePackage(xAbortChannel, xCmdEnv);
|
|
|
|
}
|
2010-04-21 16:04:34 +02:00
|
|
|
const OUString id(dp_misc::getIdentifier(extension));
|
|
|
|
activateExtension(id, extension->getName(),
|
|
|
|
isUserDisabled(id, extension->getName()), false,
|
|
|
|
xAbortChannel, xCmdEnv);
|
2010-04-19 11:33:33 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
catch (deploy::DeploymentException& ) {
|
|
|
|
throw;
|
|
|
|
} catch (ucb::CommandFailedException & ) {
|
|
|
|
throw;
|
|
|
|
} catch (ucb::CommandAbortedException & ) {
|
|
|
|
throw;
|
|
|
|
} catch (lang::IllegalArgumentException &) {
|
|
|
|
throw;
|
|
|
|
} catch (uno::RuntimeException &) {
|
|
|
|
throw;
|
|
|
|
} catch (...) {
|
|
|
|
uno::Any excOccurred = ::cppu::getCaughtException();
|
|
|
|
deploy::DeploymentException exc(
|
|
|
|
OUSTR("Extension Manager: exception during disableExtension"),
|
|
|
|
static_cast<OWeakObject*>(this), excOccurred);
|
|
|
|
throw exc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
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)
|
|
|
|
{
|
2010-04-21 16:04:34 +02:00
|
|
|
::osl::MutexGuard guard(getMutex());
|
2010-05-04 12:37:01 +02:00
|
|
|
uno::Any excOccurred;
|
2010-04-21 16:04:34 +02:00
|
|
|
bool bUserDisabled = false;
|
2010-05-04 12:37:01 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
if (!extension.is())
|
|
|
|
return;
|
2010-04-21 16:04:34 +02:00
|
|
|
const OUString repository( extension->getRepositoryName());
|
2010-05-04 12:37:01 +02:00
|
|
|
if (!repository.equals(OUSTR("user")))
|
|
|
|
throw lang::IllegalArgumentException(
|
|
|
|
OUSTR("No valid repository name provided."),
|
|
|
|
static_cast<cppu::OWeakObject*>(this), 0);
|
|
|
|
|
2010-04-21 16:04:34 +02:00
|
|
|
const OUString id(dp_misc::getIdentifier(extension));
|
|
|
|
bUserDisabled = isUserDisabled(id, extension->getName());
|
2010-05-04 12:37:01 +02:00
|
|
|
|
2010-04-21 16:04:34 +02:00
|
|
|
activateExtension(id, extension->getName(), true, false,
|
2010-04-19 11:33:33 +02:00
|
|
|
xAbortChannel, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
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),
|
2010-04-21 16:04:34 +02:00
|
|
|
extension->getName(), bUserDisabled, false,
|
2010-04-19 11:33:33 +02:00
|
|
|
xAbortChannel, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2010-04-19 11:33:33 +02:00
|
|
|
return getPackageManager(repository)->getDeployedPackages(
|
|
|
|
xAbort, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2010-04-19 11:33:33 +02:00
|
|
|
return getPackageManager(repository)->getDeployedPackage(
|
|
|
|
identifier, filename, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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;
|
2010-03-19 15:12:00 +01:00
|
|
|
uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > seqSeq(vecExtensions.size());
|
2010-05-04 12:37:01 +02:00
|
|
|
for (;citVecVec != vecExtensions.end(); citVecVec++, j++)
|
|
|
|
{
|
|
|
|
seqSeq[j] = comphelper::containerToSequence(*citVecVec);
|
|
|
|
}
|
2010-03-19 15:12:00 +01:00
|
|
|
return seqSeq;
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
} 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);
|
2010-03-19 15:12:00 +01:00
|
|
|
}
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
|
2010-05-21 15:13:26 +02:00
|
|
|
//only to be called from unopkg!!!
|
2010-05-04 12:37:01 +02:00
|
|
|
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
|
|
|
|
{
|
2010-04-19 11:33:33 +02:00
|
|
|
Reference<deploy::XPackageManager>
|
|
|
|
xPackageManager = getPackageManager(repository);
|
2010-05-04 12:37:01 +02:00
|
|
|
|
2010-04-20 10:04:52 +02:00
|
|
|
::osl::MutexGuard guard(getMutex());
|
2010-05-04 12:37:01 +02:00
|
|
|
xPackageManager->reinstallDeployedPackages(xAbortChannel, xCmdEnv);
|
2010-05-21 15:13:26 +02:00
|
|
|
//We must sync here, otherwise we will get exceptions when extensions
|
|
|
|
//are removed.
|
|
|
|
dp_misc::syncRepositories(xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
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());
|
2010-04-21 16:04:34 +02:00
|
|
|
activateExtension(id, fileName, false, false, xAbortChannel, xCmdEnv );
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-17 10:40:52 +02:00
|
|
|
sal_Bool ExtensionManager::synchronize(
|
2010-05-04 12:37:01 +02:00
|
|
|
Reference<task::XAbortChannel> const & xAbortChannel,
|
|
|
|
Reference<ucb::XCommandEnvironment> const & xCmdEnv )
|
|
|
|
throw (deploy::DeploymentException,
|
|
|
|
ucb::CommandFailedException,
|
|
|
|
ucb::CommandAbortedException,
|
|
|
|
lang::IllegalArgumentException,
|
|
|
|
uno::RuntimeException)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2010-05-17 10:40:52 +02:00
|
|
|
sal_Bool bModified = sal_False;
|
2010-05-04 12:37:01 +02:00
|
|
|
|
2010-04-20 10:04:52 +02:00
|
|
|
::osl::MutexGuard guard(getMutex());
|
2010-05-21 09:42:27 +02:00
|
|
|
String sSynchronizingShared(StrSyncRepository::get());
|
|
|
|
sSynchronizingShared.SearchAndReplaceAllAscii( "%NAME", OUSTR("shared"));
|
|
|
|
dp_misc::ProgressLevel progressShared(xCmdEnv, sSynchronizingShared);
|
|
|
|
bModified = m_sharedRepository->synchronize(xAbortChannel, xCmdEnv);
|
|
|
|
progressShared.update(OUSTR("\n\n"));
|
|
|
|
|
|
|
|
String sSynchronizingBundled(StrSyncRepository::get());
|
|
|
|
sSynchronizingBundled.SearchAndReplaceAllAscii( "%NAME", OUSTR("bundled"));
|
|
|
|
dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled);
|
|
|
|
bModified |= m_bundledRepository->synchronize(xAbortChannel, xCmdEnv);
|
|
|
|
progressBundled.update(OUSTR("\n\n"));
|
2010-04-19 11:33:33 +02:00
|
|
|
|
2010-07-28 16:27:07 +02:00
|
|
|
//Always determine the active extension. This is necessary for the
|
|
|
|
//first-start optimization. The setup creates the registration data for the
|
|
|
|
//bundled extensions (brand_layer/share/prereg/bundled), which is copied to the user
|
|
|
|
//installation (user_installation/extension/bundled) when a user starts OOo
|
|
|
|
//for the first time after running setup. All bundled extensions are registered
|
|
|
|
//at that moment. However, extensions with the same identifier can be in the
|
|
|
|
//shared or user repository, in which case the respective bundled extensions must
|
|
|
|
//be revoked.
|
2010-04-19 11:33:33 +02:00
|
|
|
try
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-04-19 11:33:33 +02:00
|
|
|
const uno::Sequence<uno::Sequence<Reference<deploy::XPackage> > >
|
|
|
|
seqSeqExt = getAllExtensions(xAbortChannel, xCmdEnv);
|
|
|
|
for (sal_Int32 i = 0; i < seqSeqExt.getLength(); i++)
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-04-19 11:33:33 +02:00
|
|
|
uno::Sequence<Reference<deploy::XPackage> > const & seqExt =
|
|
|
|
seqSeqExt[i];
|
2010-04-21 16:04:34 +02:00
|
|
|
activateExtension(seqExt, isUserDisabled(seqExt), true,
|
|
|
|
xAbortChannel, xCmdEnv);
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
|
|
|
}
|
2010-04-19 11:33:33 +02:00
|
|
|
catch (...)
|
2010-05-04 12:37:01 +02:00
|
|
|
{
|
2010-04-19 11:33:33 +02:00
|
|
|
//We catch the exception, so we can write the lastmodified file
|
|
|
|
//so we will no repeat this everytime OOo starts.
|
|
|
|
OSL_ENSURE(0, "Extensions Manager: synchronize");
|
2010-05-04 12:37:01 +02:00
|
|
|
}
|
2010-05-21 15:13:26 +02:00
|
|
|
OUString lastSyncBundled(RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"$BUNDLED_EXTENSIONS_USER/lastsynchronized"));
|
|
|
|
writeLastModified(lastSyncBundled, xCmdEnv);
|
|
|
|
OUString lastSyncShared(RTL_CONSTASCII_USTRINGPARAM(
|
|
|
|
"$SHARED_EXTENSIONS_USER/lastsynchronized"));
|
|
|
|
writeLastModified(lastSyncShared, xCmdEnv);
|
2010-05-17 10:40:52 +02:00
|
|
|
return bModified;
|
2010-05-04 12:37:01 +02:00
|
|
|
} 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(
|
2010-06-10 14:04:48 +02:00
|
|
|
OUSTR("Extension Manager: exception in synchronize"),
|
2010-05-04 12:37:01 +02:00
|
|
|
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(
|
2010-04-19 11:33:33 +02:00
|
|
|
url, uno::Sequence<beans::NamedValue>(),OUString(), xAbortChannel, tmpCmdEnvA);
|
2010-05-04 12:37:01 +02:00
|
|
|
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;
|
|
|
|
}
|
2010-04-19 11:33:33 +02:00
|
|
|
|
|
|
|
uno::Sequence<Reference<deploy::XPackage> > SAL_CALL
|
|
|
|
ExtensionManager::getExtensionsWithUnacceptedLicenses(
|
|
|
|
OUString const & repository,
|
|
|
|
Reference<ucb::XCommandEnvironment> const & xCmdEnv)
|
|
|
|
throw (deploy::DeploymentException,
|
|
|
|
uno::RuntimeException)
|
|
|
|
{
|
|
|
|
Reference<deploy::XPackageManager>
|
|
|
|
xPackageManager = getPackageManager(repository);
|
2010-04-20 10:04:52 +02:00
|
|
|
::osl::MutexGuard guard(getMutex());
|
2010-04-19 11:33:33 +02:00
|
|
|
return xPackageManager->getExtensionsWithUnacceptedLicenses(xCmdEnv);
|
|
|
|
}
|
|
|
|
|
2010-04-23 11:43:48 +02:00
|
|
|
sal_Bool ExtensionManager::isReadOnlyRepository(::rtl::OUString const & repository)
|
2010-05-10 11:06:01 +02:00
|
|
|
throw (uno::RuntimeException)
|
2010-04-23 11:43:48 +02:00
|
|
|
{
|
|
|
|
return getPackageManager(repository)->isReadOnly();
|
|
|
|
}
|
2010-05-04 12:37:01 +02:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-20 10:04:52 +02:00
|
|
|
// XModifyBroadcaster
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void ExtensionManager::addModifyListener(
|
|
|
|
Reference<util::XModifyListener> const & xListener )
|
|
|
|
throw (uno::RuntimeException)
|
|
|
|
{
|
|
|
|
check();
|
|
|
|
rBHelper.addListener( ::getCppuType( &xListener ), xListener );
|
|
|
|
}
|
|
|
|
|
|
|
|
//______________________________________________________________________________
|
|
|
|
void ExtensionManager::removeModifyListener(
|
|
|
|
Reference<util::XModifyListener> const & xListener )
|
|
|
|
throw (uno::RuntimeException)
|
|
|
|
{
|
|
|
|
check();
|
|
|
|
rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExtensionManager::check()
|
|
|
|
{
|
|
|
|
::osl::MutexGuard guard( getMutex() );
|
|
|
|
if (rBHelper.bInDispose || rBHelper.bDisposed) {
|
|
|
|
throw lang::DisposedException(
|
|
|
|
OUSTR("ExtensionManager instance has already been disposed!"),
|
|
|
|
static_cast<OWeakObject *>(this) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ExtensionManager::fireModified()
|
|
|
|
{
|
|
|
|
::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer(
|
|
|
|
util::XModifyListener::static_type() );
|
|
|
|
if (pContainer != 0) {
|
|
|
|
pContainer->forEach<util::XModifyListener>(
|
|
|
|
boost::bind(&util::XModifyListener::modified, _1,
|
|
|
|
lang::EventObject(static_cast<OWeakObject *>(this))) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-04 12:37:01 +02:00
|
|
|
} // namespace dp_manager
|
|
|
|
|
|
|
|
|