#i10000# changes from OOO330 m11

This commit is contained in:
Vladimir Glazunov
2010-10-18 13:21:01 +02:00
9 changed files with 497 additions and 156 deletions

View File

@@ -29,6 +29,7 @@
#include "sal/config.h" #include "sal/config.h"
#include <algorithm> #include <algorithm>
#include <cstddef>
#include <list> #include <list>
#include "com/sun/star/beans/Optional.hpp" #include "com/sun/star/beans/Optional.hpp"
@@ -43,8 +44,11 @@
#include "com/sun/star/uno/RuntimeException.hpp" #include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/XComponentContext.hpp" #include "com/sun/star/uno/XComponentContext.hpp"
#include "com/sun/star/uno/XInterface.hpp" #include "com/sun/star/uno/XInterface.hpp"
#include "osl/conditn.hxx"
#include "osl/diagnose.h" #include "osl/diagnose.h"
#include "osl/file.hxx" #include "osl/file.hxx"
#include "osl/mutex.hxx"
#include "osl/thread.hxx"
#include "rtl/bootstrap.hxx" #include "rtl/bootstrap.hxx"
#include "rtl/logfile.h" #include "rtl/logfile.h"
#include "rtl/ref.hxx" #include "rtl/ref.hxx"
@@ -53,10 +57,12 @@
#include "rtl/ustring.h" #include "rtl/ustring.h"
#include "rtl/ustring.hxx" #include "rtl/ustring.hxx"
#include "sal/types.h" #include "sal/types.h"
#include "salhelper/simplereferenceobject.hxx"
#include "additions.hxx" #include "additions.hxx"
#include "components.hxx" #include "components.hxx"
#include "data.hxx" #include "data.hxx"
#include "lock.hxx"
#include "modifications.hxx" #include "modifications.hxx"
#include "node.hxx" #include "node.hxx"
#include "nodemap.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( void Components::initSingleton(
css::uno::Reference< css::uno::XComponentContext > const & context) css::uno::Reference< css::uno::XComponentContext > const & context)
{ {
@@ -238,7 +304,23 @@ void Components::addModification(Path const & path) {
} }
void Components::writeModifications() { 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( void Components::insertExtensionXcsFile(

View File

@@ -94,6 +94,11 @@ public:
void writeModifications(); 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 insertExtensionXcsFile(bool shared, rtl::OUString const & fileUri);
void insertExtensionXcuFile( void insertExtensionXcuFile(
@@ -160,11 +165,14 @@ private:
com::sun::star::beans::XPropertySet > > com::sun::star::beans::XPropertySet > >
ExternalServices; ExternalServices;
class WriteThread;
com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
context_; context_;
Data data_; Data data_;
WeakRootSet roots_; WeakRootSet roots_;
ExternalServices externalServices_; ExternalServices externalServices_;
rtl::Reference< WriteThread > writeThread_;
}; };
} }

View File

@@ -114,6 +114,8 @@ public:
private: private:
virtual ~Service() {} virtual ~Service() {}
virtual void SAL_CALL disposing() { flushModifications(); }
virtual rtl::OUString SAL_CALL getImplementationName() virtual rtl::OUString SAL_CALL getImplementationName()
throw (css::uno::RuntimeException) throw (css::uno::RuntimeException)
{ return configuration_provider::getImplementationName(); } { return configuration_provider::getImplementationName(); }
@@ -166,6 +168,8 @@ private:
virtual css::lang::Locale SAL_CALL getLocale() virtual css::lang::Locale SAL_CALL getLocale()
throw (css::uno::RuntimeException); throw (css::uno::RuntimeException);
void flushModifications() const;
css::uno::Reference< css::uno::XComponentContext > context_; css::uno::Reference< css::uno::XComponentContext > context_;
rtl::OUString locale_; rtl::OUString locale_;
}; };
@@ -326,7 +330,7 @@ void Service::removeRefreshListener(
} }
void Service::flush() throw (css::uno::RuntimeException) { void Service::flush() throw (css::uno::RuntimeException) {
//TODO flushModifications();
cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer( cppu::OInterfaceContainerHelper * cont = rBHelper.getContainer(
cppu::UnoType< css::util::XFlushListener >::get()); cppu::UnoType< css::util::XFlushListener >::get());
if (cont != 0) { if (cont != 0) {
@@ -380,6 +384,16 @@ css::lang::Locale Service::getLocale() throw (css::uno::RuntimeException) {
return loc; return loc;
} }
void Service::flushModifications() const {
Components * components;
{
osl::MutexGuard guard(lock);
Components::initSingleton(context_);
components = &Components::getSingleton();
}
components->flushModifications();
}
class Factory: class Factory:
public cppu::WeakImplHelper1< css::lang::XSingleComponentFactory >, public cppu::WeakImplHelper1< css::lang::XSingleComponentFactory >,
private boost::noncopyable private boost::noncopyable

View File

@@ -155,6 +155,7 @@ class Desktop : public Application
sal_Bool InitializeInstallation( const rtl::OUString& rAppFilename ); sal_Bool InitializeInstallation( const rtl::OUString& rAppFilename );
sal_Bool InitializeConfiguration(); sal_Bool InitializeConfiguration();
void FlushConfiguration();
sal_Bool InitializeQuickstartMode( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rSMgr ); sal_Bool InitializeQuickstartMode( com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& rSMgr );
void HandleBootstrapPathErrors( ::utl::Bootstrap::Status, const ::rtl::OUString& aMsg ); void HandleBootstrapPathErrors( ::utl::Bootstrap::Status, const ::rtl::OUString& aMsg );

View File

@@ -754,6 +754,7 @@ void Desktop::DeInit()
// instead of removing of the configManager just let it commit all the changes // instead of removing of the configManager just let it commit all the changes
RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
utl::ConfigManager::GetConfigManager()->StoreConfigItems(); utl::ConfigManager::GetConfigManager()->StoreConfigItems();
FlushConfiguration();
RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
// close splashscreen if it's still open // close splashscreen if it's still open
@@ -784,6 +785,7 @@ BOOL Desktop::QueryExit()
{ {
RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
utl::ConfigManager::GetConfigManager()->StoreConfigItems(); utl::ConfigManager::GetConfigManager()->StoreConfigItems();
FlushConfiguration();
RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" ); RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
} }
catch ( RuntimeException& ) catch ( RuntimeException& )
@@ -1436,18 +1438,7 @@ USHORT Desktop::Exception(USHORT nError)
if ( bAllowRecoveryAndSessionManagement ) if ( bAllowRecoveryAndSessionManagement )
bRestart = SaveTasks(); bRestart = SaveTasks();
// because there is no method to flush the condiguration data, we must dispose the ConfigManager FlushConfiguration();
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();
}
switch( nError & EXC_MAJORTYPE ) switch( nError & EXC_MAJORTYPE )
{ {
@@ -1976,6 +1967,7 @@ void Desktop::Main()
// remove temp directory // remove temp directory
RemoveTemporaryDirectory(); RemoveTemporaryDirectory();
FlushConfiguration();
// The acceptors in the AcceptorMap must be released (in DeregisterServices) // The acceptors in the AcceptorMap must be released (in DeregisterServices)
// with the solar mutex unlocked, to avoid deadlock: // with the solar mutex unlocked, to avoid deadlock:
nAcquireCount = Application::ReleaseSolarMutex(); nAcquireCount = Application::ReleaseSolarMutex();
@@ -2073,6 +2065,22 @@ sal_Bool Desktop::InitializeConfiguration()
return bOk; 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 ) sal_Bool Desktop::InitializeQuickstartMode( Reference< XMultiServiceFactory >& rSMgr )
{ {
try try

View File

@@ -31,6 +31,8 @@
#include "com/sun/star/deployment/VersionException.hpp" #include "com/sun/star/deployment/VersionException.hpp"
#include "com/sun/star/deployment/LicenseException.hpp" #include "com/sun/star/deployment/LicenseException.hpp"
#include "com/sun/star/deployment/InstallException.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/XInteractionApprove.hpp"
#include "com/sun/star/task/XInteractionAbort.hpp" #include "com/sun/star/task/XInteractionAbort.hpp"
#include "com/sun/star/task/XInteractionHandler.hpp" #include "com/sun/star/task/XInteractionHandler.hpp"
@@ -250,7 +252,43 @@ void NoLicenseCommandEnv::handle(
handle_(approve, abort, xRequest); 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( // NoExceptionCommandEnv::NoExceptionCommandEnv(
// css::uno::Reference< css::task::XInteractionHandler> const & handler, // css::uno::Reference< css::task::XInteractionHandler> const & handler,
// css::uno::Type const & type): // css::uno::Type const & type):

View File

@@ -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 // class NoExceptionCommandEnv : public BaseCommandEnv
// { // {
// css::uno::Type m_type; // css::uno::Type m_type;

View File

@@ -139,6 +139,37 @@ void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const
OUSTR("Failed to update") + url, 0, exc); 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 } //end namespace
namespace dp_manager { namespace dp_manager {
@@ -500,6 +531,107 @@ ExtensionManager::getSupportedPackageTypes()
{ {
return m_userRepository->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 // Only add to shared and user repository
Reference<deploy::XPackage> ExtensionManager::addExtension( Reference<deploy::XPackage> ExtensionManager::addExtension(
@@ -524,165 +656,183 @@ Reference<deploy::XPackage> ExtensionManager::addExtension(
throw lang::IllegalArgumentException( throw lang::IllegalArgumentException(
OUSTR("No valid repository name provided."), OUSTR("No valid repository name provided."),
static_cast<cppu::OWeakObject*>(this), 0); 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 = Reference<deploy::XPackage> xTmpExtension =
getTempExtension(url, xAbortChannel, xCmdEnv); 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 sIdentifier = dp_misc::getIdentifier(xTmpExtension);
const OUString sFileName = xTmpExtension->getName(); 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> xOldExtension;
Reference<deploy::XPackage> xExtensionBackup; Reference<deploy::XPackage> xExtensionBackup;
uno::Any excOccurred1;
uno::Any excOccurred2; uno::Any excOccurred2;
bool bUserDisabled = false; bool bUserDisabled = false;
try bool bCanInstall = doChecksForAddExtension(
{ xPackageManager,
bUserDisabled = isUserDisabled(sIdentifier, sFileName); properties,
try xTmpExtension,
{ xAbortChannel,
xOldExtension = xPackageManager->getDeployedPackage( xCmdEnv,
sIdentifier, sFileName, xCmdEnv); xOldExtension );
}
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()));
bCanInstall = xTmpExtension->checkPrerequisites( {
xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0 ? true : false; // In this garded section (getMutex) we must not use the argument xCmdEnv
} // because it may bring up dialogs (XInteractionHandler::handle) this
catch (deploy::DeploymentException& ) { //may potententially deadlock. See issue
excOccurred1 = ::cppu::getCaughtException(); //http://qa.openoffice.org/issues/show_bug.cgi?id=114933
} catch (ucb::CommandFailedException & ) { //By not providing xCmdEnv the underlying APIs will throw an exception if
excOccurred1 = ::cppu::getCaughtException(); //the XInteractionRequest cannot be handled
} catch (ucb::CommandAbortedException & ) { ::osl::MutexGuard guard(getMutex());
excOccurred1 = ::cppu::getCaughtException();
} catch (lang::IllegalArgumentException &) {
excOccurred1 = ::cppu::getCaughtException();
} catch (uno::RuntimeException &) {
excOccurred1 = ::cppu::getCaughtException();
} catch (...) {
excOccurred1 = ::cppu::getCaughtException();
deploy::DeploymentException exc(
OUSTR("Extension Manager: exception during addExtension, url: ")
+ url, static_cast<OWeakObject*>(this), excOccurred1);
excOccurred1 <<= exc;
}
if (bCanInstall) if (bCanInstall)
{ {
if (xOldExtension.is()) try
{ {
xOldExtension->revokePackage(xAbortChannel, xCmdEnv); bUserDisabled = isUserDisabled(sIdentifier, sFileName);
//save the old user extension in case the user aborts if (xOldExtension.is())
//store the extension in the tmp repository, this will overwrite {
//xTmpPackage (same identifier). Do not let the user abort or try
//interact {
Reference<ucb::XCommandEnvironment> tmpCmdEnv( xOldExtension->revokePackage(
new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); xAbortChannel, Reference<ucb::XCommandEnvironment>());
//importing the old extension in the tmp repository will remove //save the old user extension in case the user aborts
//the xTmpExtension //store the extension in the tmp repository, this will overwrite
xTmpExtension = 0; //xTmpPackage (same identifier). Do not let the user abort or
xExtensionBackup = m_tmpRepository->importExtension( //interact
xOldExtension, Reference<task::XAbortChannel>(), //importing the old extension in the tmp repository will remove
tmpCmdEnv); //the xTmpExtension
} //no command environment supplied, only this class shall interact
xNewExtension = xPackageManager->addPackage( //with the user!
url, properties, OUString(), xAbortChannel, xCmdEnv); xExtensionBackup = m_tmpRepository->importExtension(
//If we add a user extension and there is already one which was xOldExtension, Reference<task::XAbortChannel>(),
//disabled by a user, then the newly installed one is enabled. If we Reference<ucb::XCommandEnvironment>());
//add to another repository then the user extension remains tmpExtensionRemoveGuard.reset(xExtensionBackup);
//disabled. //xTmpExtension will later be used to check the dependencies
bool bUserDisabled2 = bUserDisabled; //again. However, only xExtensionBackup will be later removed
if (repository.equals(OUSTR("user"))) //from the tmp repository
bUserDisabled2 = false; xTmpExtension = xExtensionBackup;
activateExtension( OSL_ASSERT(xTmpExtension.is());
dp_misc::getIdentifier(xNewExtension), }
xNewExtension->getName(), bUserDisabled2, false, xAbortChannel, xCmdEnv); catch (lang::DisposedException &)
fireModified(); {
} //Another thread might have removed the extension meanwhile
} }
catch (deploy::DeploymentException& ) { }
excOccurred2 = ::cppu::getCaughtException(); //check again dependencies but prevent user interaction,
} catch (ucb::CommandFailedException & ) { //We can disregard the license, because the user must have already
excOccurred2 = ::cppu::getCaughtException(); //accepted it, whe we called checkPrerequisites the first time
} catch (ucb::CommandAbortedException & ) { SilentCheckPrerequisitesCommandEnv * pSilentCommandEnv =
excOccurred2 = ::cppu::getCaughtException(); new SilentCheckPrerequisitesCommandEnv();
} catch (lang::IllegalArgumentException &) { Reference<ucb::XCommandEnvironment> silentCommandEnv(pSilentCommandEnv);
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()) 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 fireModified();
//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);
if (excOccurred1.hasValue()) }catch (deploy::DeploymentException& ) {
::cppu::throwException(excOccurred1); 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; return xNewExtension;
} }

View File

@@ -235,6 +235,8 @@ private:
css::uno::Reference<css::deployment::XPackageManager> m_bundledRepository; css::uno::Reference<css::deployment::XPackageManager> m_bundledRepository;
css::uno::Reference<css::deployment::XPackageManager> m_tmpRepository; 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 /* contains the names of all repositories (except tmp) in order of there
priority. That is, the first element is "user" follod by "shared" and priority. That is, the first element is "user" follod by "shared" and
then "bundled" then "bundled"
@@ -296,6 +298,21 @@ private:
css::uno::Reference<css::deployment::XPackageManager> css::uno::Reference<css::deployment::XPackageManager>
getPackageManager(::rtl::OUString const & repository) getPackageManager(::rtl::OUString const & repository)
throw (css::lang::IllegalArgumentException); 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);
}; };
} }