#i10000# changes from OOO330 m11
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include "sal/config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <list>
|
||||
|
||||
#include "com/sun/star/beans/Optional.hpp"
|
||||
@@ -43,8 +44,11 @@
|
||||
#include "com/sun/star/uno/RuntimeException.hpp"
|
||||
#include "com/sun/star/uno/XComponentContext.hpp"
|
||||
#include "com/sun/star/uno/XInterface.hpp"
|
||||
#include "osl/conditn.hxx"
|
||||
#include "osl/diagnose.h"
|
||||
#include "osl/file.hxx"
|
||||
#include "osl/mutex.hxx"
|
||||
#include "osl/thread.hxx"
|
||||
#include "rtl/bootstrap.hxx"
|
||||
#include "rtl/logfile.h"
|
||||
#include "rtl/ref.hxx"
|
||||
@@ -53,10 +57,12 @@
|
||||
#include "rtl/ustring.h"
|
||||
#include "rtl/ustring.hxx"
|
||||
#include "sal/types.h"
|
||||
#include "salhelper/simplereferenceobject.hxx"
|
||||
|
||||
#include "additions.hxx"
|
||||
#include "components.hxx"
|
||||
#include "data.hxx"
|
||||
#include "lock.hxx"
|
||||
#include "modifications.hxx"
|
||||
#include "node.hxx"
|
||||
#include "nodemap.hxx"
|
||||
@@ -148,6 +154,66 @@ static Components * singleton = 0;
|
||||
|
||||
}
|
||||
|
||||
class Components::WriteThread:
|
||||
public osl::Thread, public salhelper::SimpleReferenceObject
|
||||
{
|
||||
public:
|
||||
static void * operator new(std::size_t size)
|
||||
{ return Thread::operator new(size); }
|
||||
|
||||
static void operator delete(void * pointer)
|
||||
{ Thread::operator delete(pointer); }
|
||||
|
||||
WriteThread(
|
||||
rtl::Reference< WriteThread > * reference, Components & components,
|
||||
rtl::OUString const & url, Data const & data);
|
||||
|
||||
void flush() { delay_.set(); }
|
||||
|
||||
private:
|
||||
virtual ~WriteThread() {}
|
||||
|
||||
virtual void SAL_CALL run();
|
||||
|
||||
virtual void SAL_CALL onTerminated() { release(); }
|
||||
|
||||
rtl::Reference< WriteThread > * reference_;
|
||||
Components & components_;
|
||||
rtl::OUString url_;
|
||||
Data const & data_;
|
||||
osl::Condition delay_;
|
||||
};
|
||||
|
||||
Components::WriteThread::WriteThread(
|
||||
rtl::Reference< WriteThread > * reference, Components & components,
|
||||
rtl::OUString const & url, Data const & data):
|
||||
reference_(reference), components_(components), url_(url), data_(data)
|
||||
{
|
||||
OSL_ASSERT(reference != 0);
|
||||
acquire();
|
||||
}
|
||||
|
||||
void Components::WriteThread::run() {
|
||||
TimeValue t = { 1, 0 }; // 1 sec
|
||||
delay_.wait(&t); // must not throw; result_error is harmless and ignored
|
||||
osl::MutexGuard g(lock); // must not throw
|
||||
try {
|
||||
try {
|
||||
writeModFile(components_, url_, data_);
|
||||
} catch (css::uno::RuntimeException & e) {
|
||||
// Silently ignore write errors, instead of aborting:
|
||||
OSL_TRACE(
|
||||
"configmgr error writing modifications: %s",
|
||||
rtl::OUStringToOString(
|
||||
e.Message, RTL_TEXTENCODING_UTF8).getStr());
|
||||
}
|
||||
} catch (...) {
|
||||
reference_->clear();
|
||||
throw;
|
||||
}
|
||||
reference_->clear();
|
||||
}
|
||||
|
||||
void Components::initSingleton(
|
||||
css::uno::Reference< css::uno::XComponentContext > const & context)
|
||||
{
|
||||
@@ -238,7 +304,23 @@ void Components::addModification(Path const & path) {
|
||||
}
|
||||
|
||||
void Components::writeModifications() {
|
||||
writeModFile(*this, getModificationFileUrl(), data_);
|
||||
if (!writeThread_.is()) {
|
||||
writeThread_ = new WriteThread(
|
||||
&writeThread_, *this, getModificationFileUrl(), data_);
|
||||
writeThread_->create();
|
||||
}
|
||||
}
|
||||
|
||||
void Components::flushModifications() {
|
||||
rtl::Reference< WriteThread > thread;
|
||||
{
|
||||
osl::MutexGuard g(lock);
|
||||
thread = writeThread_;
|
||||
}
|
||||
if (thread.is()) {
|
||||
thread->flush();
|
||||
thread->join();
|
||||
}
|
||||
}
|
||||
|
||||
void Components::insertExtensionXcsFile(
|
||||
|
@@ -94,6 +94,11 @@ public:
|
||||
|
||||
void writeModifications();
|
||||
|
||||
void flushModifications();
|
||||
// must be called with configmgr::lock unaquired; must be called before
|
||||
// shutdown if writeModifications has ever been called (probably
|
||||
// indirectly, via removeExtensionXcuFile)
|
||||
|
||||
void insertExtensionXcsFile(bool shared, rtl::OUString const & fileUri);
|
||||
|
||||
void insertExtensionXcuFile(
|
||||
@@ -160,11 +165,14 @@ private:
|
||||
com::sun::star::beans::XPropertySet > >
|
||||
ExternalServices;
|
||||
|
||||
class WriteThread;
|
||||
|
||||
com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
|
||||
context_;
|
||||
Data data_;
|
||||
WeakRootSet roots_;
|
||||
ExternalServices externalServices_;
|
||||
rtl::Reference< WriteThread > writeThread_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -114,6 +114,8 @@ public:
|
||||
private:
|
||||
virtual ~Service() {}
|
||||
|
||||
virtual void SAL_CALL disposing() { flushModifications(); }
|
||||
|
||||
virtual rtl::OUString SAL_CALL getImplementationName()
|
||||
throw (css::uno::RuntimeException)
|
||||
{ return configuration_provider::getImplementationName(); }
|
||||
@@ -166,6 +168,8 @@ private:
|
||||
virtual css::lang::Locale SAL_CALL getLocale()
|
||||
throw (css::uno::RuntimeException);
|
||||
|
||||
void flushModifications() const;
|
||||
|
||||
css::uno::Reference< css::uno::XComponentContext > context_;
|
||||
rtl::OUString locale_;
|
||||
};
|
||||
@@ -326,7 +330,7 @@ void Service::removeRefreshListener(
|
||||
}
|
||||
|
||||
void Service::flush() throw (css::uno::RuntimeException) {
|
||||
//TODO
|
||||
flushModifications();
|
||||
cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
|
||||
cppu::UnoType< css::util::XFlushListener >::get());
|
||||
if (cont != 0) {
|
||||
@@ -380,6 +384,16 @@ css::lang::Locale Service::getLocale() throw (css::uno::RuntimeException) {
|
||||
return loc;
|
||||
}
|
||||
|
||||
void Service::flushModifications() const {
|
||||
Components * components;
|
||||
{
|
||||
osl::MutexGuard guard(lock);
|
||||
Components::initSingleton(context_);
|
||||
components = &Components::getSingleton();
|
||||
}
|
||||
components->flushModifications();
|
||||
}
|
||||
|
||||
class Factory:
|
||||
public cppu::WeakImplHelper1< css::lang::XSingleComponentFactory >,
|
||||
private boost::noncopyable
|
||||
|
@@ -155,6 +155,7 @@ class Desktop : public Application
|
||||
|
||||
sal_Bool InitializeInstallation( const rtl::OUString& rAppFilename );
|
||||
sal_Bool InitializeConfiguration();
|
||||
void FlushConfiguration();
|
||||
sal_Bool InitializeQuickstartMode( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rSMgr );
|
||||
|
||||
void HandleBootstrapPathErrors( ::utl::Bootstrap::Status, const ::rtl::OUString& aMsg );
|
||||
|
@@ -754,6 +754,7 @@ void Desktop::DeInit()
|
||||
// instead of removing of the configManager just let it commit all the changes
|
||||
RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
|
||||
utl::ConfigManager::GetConfigManager()->StoreConfigItems();
|
||||
FlushConfiguration();
|
||||
RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
|
||||
|
||||
// close splashscreen if it's still open
|
||||
@@ -784,6 +785,7 @@ BOOL Desktop::QueryExit()
|
||||
{
|
||||
RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
|
||||
utl::ConfigManager::GetConfigManager()->StoreConfigItems();
|
||||
FlushConfiguration();
|
||||
RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
|
||||
}
|
||||
catch ( RuntimeException& )
|
||||
@@ -1436,18 +1438,7 @@ USHORT Desktop::Exception(USHORT nError)
|
||||
if ( bAllowRecoveryAndSessionManagement )
|
||||
bRestart = SaveTasks();
|
||||
|
||||
// because there is no method to flush the condiguration data, we must dispose the ConfigManager
|
||||
Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY );
|
||||
if (xCFGFlush.is())
|
||||
{
|
||||
xCFGFlush->flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY );
|
||||
if (xCFGDispose.is())
|
||||
xCFGDispose->dispose();
|
||||
}
|
||||
FlushConfiguration();
|
||||
|
||||
switch( nError & EXC_MAJORTYPE )
|
||||
{
|
||||
@@ -1976,6 +1967,7 @@ void Desktop::Main()
|
||||
|
||||
// remove temp directory
|
||||
RemoveTemporaryDirectory();
|
||||
FlushConfiguration();
|
||||
// The acceptors in the AcceptorMap must be released (in DeregisterServices)
|
||||
// with the solar mutex unlocked, to avoid deadlock:
|
||||
nAcquireCount = Application::ReleaseSolarMutex();
|
||||
@@ -2073,6 +2065,22 @@ sal_Bool Desktop::InitializeConfiguration()
|
||||
return bOk;
|
||||
}
|
||||
|
||||
void Desktop::FlushConfiguration()
|
||||
{
|
||||
Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY );
|
||||
if (xCFGFlush.is())
|
||||
{
|
||||
xCFGFlush->flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
// because there is no method to flush the condiguration data, we must dispose the ConfigManager
|
||||
Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY );
|
||||
if (xCFGDispose.is())
|
||||
xCFGDispose->dispose();
|
||||
}
|
||||
}
|
||||
|
||||
sal_Bool Desktop::InitializeQuickstartMode( Reference< XMultiServiceFactory >& rSMgr )
|
||||
{
|
||||
try
|
||||
|
@@ -31,6 +31,8 @@
|
||||
#include "com/sun/star/deployment/VersionException.hpp"
|
||||
#include "com/sun/star/deployment/LicenseException.hpp"
|
||||
#include "com/sun/star/deployment/InstallException.hpp"
|
||||
#include "com/sun/star/deployment/DependencyException.hpp"
|
||||
#include "com/sun/star/deployment/PlatformException.hpp"
|
||||
#include "com/sun/star/task/XInteractionApprove.hpp"
|
||||
#include "com/sun/star/task/XInteractionAbort.hpp"
|
||||
#include "com/sun/star/task/XInteractionHandler.hpp"
|
||||
@@ -250,7 +252,43 @@ void NoLicenseCommandEnv::handle(
|
||||
handle_(approve, abort, xRequest);
|
||||
}
|
||||
|
||||
// SilentCheckPrerequisitesCommandEnv::SilentCheckPrerequisitesCommandEnv(
|
||||
// css::uno::Reference< css::task::XInteractionHandler> const & handler):
|
||||
// BaseCommandEnv(handler)
|
||||
// {
|
||||
// }
|
||||
SilentCheckPrerequisitesCommandEnv::SilentCheckPrerequisitesCommandEnv()
|
||||
{
|
||||
}
|
||||
|
||||
void SilentCheckPrerequisitesCommandEnv::handle(
|
||||
Reference< task::XInteractionRequest> const & xRequest )
|
||||
throw (uno::RuntimeException)
|
||||
{
|
||||
uno::Any request( xRequest->getRequest() );
|
||||
OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION );
|
||||
|
||||
deployment::LicenseException licExc;
|
||||
deployment::PlatformException platformExc;
|
||||
deployment::DependencyException depExc;
|
||||
bool approve = false;
|
||||
bool abort = false;
|
||||
|
||||
if (request >>= licExc)
|
||||
{
|
||||
approve = true;
|
||||
handle_(approve, abort, xRequest);
|
||||
}
|
||||
else if ((request >>= platformExc)
|
||||
|| (request >>= depExc))
|
||||
{
|
||||
m_Exception = request;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_UnknownException = request;
|
||||
}
|
||||
}
|
||||
// NoExceptionCommandEnv::NoExceptionCommandEnv(
|
||||
// css::uno::Reference< css::task::XInteractionHandler> const & handler,
|
||||
// css::uno::Type const & type):
|
||||
|
@@ -135,6 +135,29 @@ public:
|
||||
|
||||
};
|
||||
|
||||
/* For use in XExtensionManager::addExtension in the call to
|
||||
XPackage::checkPrerequisites
|
||||
It prevents all user interactions. The license is always accepted.
|
||||
It remembers if there was a platform or a dependency exception in
|
||||
the member m_bException. if there was any other exception then m_bUnknownException
|
||||
is set.
|
||||
|
||||
*/
|
||||
class SilentCheckPrerequisitesCommandEnv : public BaseCommandEnv
|
||||
{
|
||||
public:
|
||||
SilentCheckPrerequisitesCommandEnv();
|
||||
// XInteractionHandler
|
||||
virtual void SAL_CALL handle(
|
||||
css::uno::Reference<css::task::XInteractionRequest > const & xRequest )
|
||||
throw (css::uno::RuntimeException);
|
||||
|
||||
// Set to true if a PlatformException or a DependencyException were handled.
|
||||
css::uno::Any m_Exception;
|
||||
// Set to true if an unknown exception was handled.
|
||||
css::uno::Any m_UnknownException;
|
||||
};
|
||||
|
||||
// class NoExceptionCommandEnv : public BaseCommandEnv
|
||||
// {
|
||||
// css::uno::Type m_type;
|
||||
|
@@ -139,6 +139,37 @@ void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const
|
||||
OUSTR("Failed to update") + url, 0, exc);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
} //end namespace
|
||||
|
||||
namespace dp_manager {
|
||||
@@ -500,6 +531,107 @@ ExtensionManager::getSupportedPackageTypes()
|
||||
{
|
||||
return m_userRepository->getSupportedPackageTypes();
|
||||
}
|
||||
//Do some necessary checks and user interaction. This function does not
|
||||
//aquire the extension manager mutex and that mutex must not be aquired
|
||||
//when this function is called. doChecksForAddExtension does synchronous
|
||||
//user interactions which may require aquiring the solar mutex.
|
||||
//Returns true if the extension can be installed.
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// Only add to shared and user repository
|
||||
Reference<deploy::XPackage> ExtensionManager::addExtension(
|
||||
@@ -524,165 +656,183 @@ Reference<deploy::XPackage> ExtensionManager::addExtension(
|
||||
throw lang::IllegalArgumentException(
|
||||
OUSTR("No valid repository name provided."),
|
||||
static_cast<cppu::OWeakObject*>(this), 0);
|
||||
::osl::MutexGuard guard(getMutex());
|
||||
//We must make sure that the xTmpExtension is not create twice, because this
|
||||
//would remove the first one.
|
||||
::osl::MutexGuard addGuard(m_addMutex);
|
||||
|
||||
Reference<deploy::XPackage> xTmpExtension =
|
||||
getTempExtension(url, xAbortChannel, xCmdEnv);
|
||||
//Make sure the extension is removed from the tmp repository in case
|
||||
//of an exception
|
||||
ExtensionRemoveGuard tmpExtensionRemoveGuard(xTmpExtension, m_tmpRepository);
|
||||
const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
|
||||
const OUString sFileName = xTmpExtension->getName();
|
||||
const OUString sDisplayName = xTmpExtension->getDisplayName();
|
||||
const OUString sVersion = xTmpExtension->getVersion();
|
||||
dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL()));
|
||||
const ::boost::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes =
|
||||
info.getSimpleLicenseAttributes();
|
||||
Reference<deploy::XPackage> xOldExtension;
|
||||
Reference<deploy::XPackage> xExtensionBackup;
|
||||
|
||||
uno::Any excOccurred1;
|
||||
uno::Any excOccurred2;
|
||||
bool bUserDisabled = false;
|
||||
try
|
||||
{
|
||||
bUserDisabled = isUserDisabled(sIdentifier, sFileName);
|
||||
try
|
||||
{
|
||||
xOldExtension = xPackageManager->getDeployedPackage(
|
||||
sIdentifier, sFileName, xCmdEnv);
|
||||
}
|
||||
catch (lang::IllegalArgumentException &)
|
||||
{
|
||||
}
|
||||
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);
|
||||
}
|
||||
//Prevent showing the license if requested.
|
||||
Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv);
|
||||
ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>());
|
||||
if (licenseAttributes && licenseAttributes->suppressIfRequired
|
||||
&& props.isSuppressedLicense())
|
||||
_xCmdEnv = Reference<ucb::XCommandEnvironment>(
|
||||
new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler()));
|
||||
bool bCanInstall = doChecksForAddExtension(
|
||||
xPackageManager,
|
||||
properties,
|
||||
xTmpExtension,
|
||||
xAbortChannel,
|
||||
xCmdEnv,
|
||||
xOldExtension );
|
||||
|
||||
bCanInstall = xTmpExtension->checkPrerequisites(
|
||||
xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0 ? true : false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if (xOldExtension.is())
|
||||
try
|
||||
{
|
||||
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, properties, OUString(), xAbortChannel, xCmdEnv);
|
||||
//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, xCmdEnv);
|
||||
fireModified();
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 will later be used to check the dependencies
|
||||
//again. However, only xExtensionBackup will be later removed
|
||||
//from the tmp repository
|
||||
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);
|
||||
|
||||
if (excOccurred2.hasValue())
|
||||
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());
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
if (xExtensionBackup.is())
|
||||
{
|
||||
Reference<deploy::XPackage> xRestored =
|
||||
xPackageManager->importExtension(
|
||||
xExtensionBackup, Reference<task::XAbortChannel>(),
|
||||
Reference<ucb::XCommandEnvironment>());
|
||||
}
|
||||
activateExtension(
|
||||
sIdentifier, sFileName, bUserDisabled, false,
|
||||
Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
::cppu::throwException(excOccurred2);
|
||||
}
|
||||
} // leaving the garded section (getMutex())
|
||||
|
||||
try
|
||||
{
|
||||
//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, false,
|
||||
Reference<task::XAbortChannel>(), tmpCmdEnv);
|
||||
if (xTmpExtension.is() || xExtensionBackup.is())
|
||||
m_tmpRepository->removePackage(
|
||||
sIdentifier, OUString(), xAbortChannel, xCmdEnv);
|
||||
fireModified();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
::cppu::throwException(excOccurred2);
|
||||
}
|
||||
if (xTmpExtension.is() || xExtensionBackup.is())
|
||||
m_tmpRepository->removePackage(
|
||||
sIdentifier,OUString(), xAbortChannel, xCmdEnv);
|
||||
fireModified();
|
||||
|
||||
if (excOccurred1.hasValue())
|
||||
::cppu::throwException(excOccurred1);
|
||||
}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));
|
||||
}
|
||||
|
||||
return xNewExtension;
|
||||
}
|
||||
|
@@ -235,6 +235,8 @@ private:
|
||||
css::uno::Reference<css::deployment::XPackageManager> m_bundledRepository;
|
||||
css::uno::Reference<css::deployment::XPackageManager> m_tmpRepository;
|
||||
|
||||
//only to be used within addExtension
|
||||
::osl::Mutex m_addMutex;
|
||||
/* 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"
|
||||
@@ -296,6 +298,21 @@ private:
|
||||
css::uno::Reference<css::deployment::XPackageManager>
|
||||
getPackageManager(::rtl::OUString const & repository)
|
||||
throw (css::lang::IllegalArgumentException);
|
||||
|
||||
bool doChecksForAddExtension(
|
||||
css::uno::Reference<css::deployment::XPackageManager> const & xPackageMgr,
|
||||
css::uno::Sequence<css::beans::NamedValue> const & properties,
|
||||
css::uno::Reference<css::deployment::XPackage> const & xTmpExtension,
|
||||
css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel,
|
||||
css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv,
|
||||
css::uno::Reference<css::deployment::XPackage> & out_existingExtension )
|
||||
throw (css::deployment::DeploymentException,
|
||||
css::ucb::CommandFailedException,
|
||||
css::ucb::CommandAbortedException,
|
||||
css::lang::IllegalArgumentException,
|
||||
css::uno::RuntimeException);
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user