Kaydet (Commit) f167d090 authored tarafından Kurt Zenker's avatar Kurt Zenker

INTEGRATION: CWS extmgrui01 (1.1.2); FILE ADDED

2008/05/21 11:31:39 kz 1.1.2.13: license updated
2008/04/29 06:12:50 dv 1.1.2.12: Better progress handling
2008/04/29 06:03:34 dv 1.1.2.11: Added changes from CWS JL94
2008/03/28 07:01:27 dv 1.1.2.10: Some more dialog changed a little bit
2008/03/27 13:02:50 dv 1.1.2.9: Better handling of adding extensions via system integration
2008/03/27 08:06:18 dv 1.1.2.8: Adopted 'Already installed' request to latest version handling
2008/03/26 09:57:06 dv 1.1.2.7: fixed some merge problems with resource ids
2008/02/29 09:53:47 dv 1.1.2.6: #i83902# Changed some strings
2008/02/28 15:16:51 dv 1.1.2.5: #i83902# Added support for updating a single extension via context menu
2008/02/27 12:58:54 dv 1.1.2.4: #i83902# Better handling of external adding of extensions
2008/02/26 07:19:53 dv 1.1.2.3: #i83902# Some strings changed for new dialog
2008/02/22 08:14:15 dv 1.1.2.2: Fixes for unix compiler
2008/02/22 07:49:45 dv 1.1.2.1: #i83902# Added progress bar
üst 8ee302b0
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: dp_gui_extensioncmdqueue.cxx,v $
*
* $Revision: 1.2 $
*
* 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 "sal/config.h"
#include <cstddef>
#include "com/sun/star/beans/PropertyValue.hpp"
#include "com/sun/star/deployment/DependencyException.hpp"
#include "com/sun/star/deployment/LicenseException.hpp"
#include "com/sun/star/deployment/LicenseIndividualAgreementException.hpp"
#include "com/sun/star/deployment/VersionException.hpp"
#include "com/sun/star/deployment/InstallException.hpp"
#include "com/sun/star/deployment/PlatformException.hpp"
#include "com/sun/star/deployment/ui/LicenseDialog.hpp"
#include "com/sun/star/deployment/DeploymentException.hpp"
#include "com/sun/star/deployment/UpdateInformationProvider.hpp"
#include "com/sun/star/deployment/XPackage.hpp"
#include "com/sun/star/deployment/XPackageManager.hpp"
#include "com/sun/star/task/XAbortChannel.hpp"
#include "com/sun/star/task/XInteractionAbort.hpp"
#include "com/sun/star/task/XInteractionApprove.hpp"
#include "com/sun/star/ucb/CommandAbortedException.hpp"
#include "com/sun/star/ucb/CommandFailedException.hpp"
#include "com/sun/star/ucb/XCommandEnvironment.hpp"
#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp"
#include "com/sun/star/uno/Reference.hxx"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include "com/sun/star/uno/XInterface.hpp"
#include "com/sun/star/uno/TypeClass.hpp"
#include "osl/diagnose.h"
#include "osl/mutex.hxx"
#include "rtl/ref.hxx"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"
#include "ucbhelper/content.hxx"
#include "cppuhelper/exc_hlp.hxx"
#include "cppuhelper/implbase3.hxx"
#include "comphelper/anytostring.hxx"
#include "vcl/msgbox.hxx"
#include "toolkit/helper/vclunohelper.hxx"
#include "dp_gui.h"
#include "dp_gui_thread.hxx"
#include "dp_gui_extensioncmdqueue.hxx"
#include "dp_gui_dependencydialog.hxx"
#include "dp_gui_dialog2.hxx"
#include "dp_gui_shared.hxx"
#include "dp_gui_theextmgr.hxx"
#include "dp_gui_updatedialog.hxx"
#include "dp_gui_updateinstalldialog.hxx"
#include "dp_dependencies.hxx"
#include "dp_identifier.hxx"
#include "dp_version.hxx"
#include <queue>
#include <boost/shared_ptr.hpp>
#if 0
#include "dp_gui.hrc"
#include "dp_gui.h"
#include "dp_gui_cmdenv.h"
#include "comphelper/anytostring.hxx"
#include "com/sun/star/lang/WrappedTargetException.hpp"
#include "tools/resid.hxx"
#include "tools/rcid.h"
#include "vcl/msgbox.hxx"
#include "vcl/threadex.hxx"
#include "boost/bind.hpp"
#endif
using namespace ::com::sun::star;
using ::rtl::OUString;
namespace {
OUString getVersion( const uno::Reference< deployment::XPackage > &rPackage )
{
OUString sVersion( rPackage->getVersion());
return ( sVersion.getLength() == 0 ) ? OUString( RTL_CONSTASCII_USTRINGPARAM( "0" ) ) : sVersion;
}
}
namespace dp_gui {
//==============================================================================
//Only if the class is consructed with the DialogImpl then the ProgressDialog can be
//displayed. Otherwise this class can still be used to forward an interaction. This
//is done by the interaction handler of the "Download and Installation" dialog.
class ProgressCmdEnv
: public ::cppu::WeakImplHelper3< ucb::XCommandEnvironment,
task::XInteractionHandler,
ucb::XProgressHandler >
{
uno::Reference< task::XInteractionHandler> m_xHandler;
uno::Reference< uno::XComponentContext > m_xContext;
uno::Reference< task::XAbortChannel> m_xAbortChannel;
ExtMgrDialog *m_pDialog;
OUString m_sTitle;
bool m_bAborted;
bool m_bWarnUser;
sal_Int32 m_nCurrentProgress;
void updateProgress();
void update_( uno::Any const & Status ) throw ( uno::RuntimeException );
public:
virtual ~ProgressCmdEnv();
/** When param bAskWhenInstalling = true, then the user is asked if he
agrees to install this extension. In case this extension is already installed
then the user is also notified and asked if he wants to replace that existing
extension. In first case an interaction request with an InstallException
will be handled and in the second case a VersionException will be handled.
*/
ProgressCmdEnv( const uno::Reference< uno::XComponentContext > rContext,
ExtMgrDialog *pDialog,
const OUString &rTitle )
: m_xContext( rContext ),
m_pDialog( pDialog ),
m_sTitle( rTitle ),
m_bAborted( false ),
m_bWarnUser( false )
{}
Dialog * activeDialog() { return m_pDialog; }
void startProgress();
void stopProgress();
void progressSection( const OUString &rText,
const uno::Reference< task::XAbortChannel > &xAbortChannel = 0 );
inline bool isAborted() const { return m_bAborted; }
inline void setWarnUser( bool bNewVal ) { m_bWarnUser = bNewVal; }
// XCommandEnvironment
virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler()
throw ( uno::RuntimeException );
virtual uno::Reference< ucb::XProgressHandler > SAL_CALL getProgressHandler()
throw ( uno::RuntimeException );
// XInteractionHandler
virtual void SAL_CALL handle( uno::Reference< task::XInteractionRequest > const & xRequest )
throw ( uno::RuntimeException );
// XProgressHandler
virtual void SAL_CALL push( uno::Any const & Status )
throw ( uno::RuntimeException );
virtual void SAL_CALL update( uno::Any const & Status )
throw ( uno::RuntimeException );
virtual void SAL_CALL pop() throw ( uno::RuntimeException );
};
//------------------------------------------------------------------------------
struct ExtensionCmd
{
enum E_CMD_TYPE { ADD, ENABLE, DISABLE, REMOVE, CHECK_FOR_UPDATE, CHECK_FOR_UPDATES };
E_CMD_TYPE m_eCmdType;
bool m_bWarnUser;
OUString m_sExtensionURL;
uno::Reference< deployment::XPackageManager > m_xPackageManager;
uno::Reference< deployment::XPackage > m_xPackage;
uno::Sequence< uno::Reference< deployment::XPackageManager > > m_xPackageManagers;
ExtensionCmd( const E_CMD_TYPE eCommand,
const uno::Reference< deployment::XPackageManager > &rPackageManager,
const OUString &rExtensionURL,
const bool bWarnUser )
: m_eCmdType( eCommand ),
m_bWarnUser( bWarnUser ),
m_sExtensionURL( rExtensionURL ),
m_xPackageManager( rPackageManager ) {};
ExtensionCmd( const E_CMD_TYPE eCommand,
const uno::Reference< deployment::XPackageManager > &rPackageManager,
const uno::Reference< deployment::XPackage > &rPackage )
: m_eCmdType( eCommand ),
m_bWarnUser( false ),
m_xPackageManager( rPackageManager ),
m_xPackage( rPackage ) {};
ExtensionCmd( const E_CMD_TYPE eCommand,
const uno::Reference< deployment::XPackage > &rPackage )
: m_eCmdType( eCommand ),
m_bWarnUser( false ),
m_xPackage( rPackage ) {};
ExtensionCmd( const E_CMD_TYPE eCommand,
const uno::Sequence< uno::Reference< deployment::XPackageManager > > &rPackageManagers )
: m_eCmdType( eCommand ),
m_bWarnUser( false ),
m_xPackageManagers( rPackageManagers ) {};
};
typedef ::boost::shared_ptr< ExtensionCmd > TExtensionCmd;
//------------------------------------------------------------------------------
class ExtensionCmdQueue::Thread: public dp_gui::Thread
{
public:
Thread( ExtMgrDialog *pDialog,
TheExtensionManager *pManager,
const uno::Reference< uno::XComponentContext > & rContext );
void addExtension( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const OUString &rExtensionURL,
const bool bWarnUser );
void removeExtension( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const uno::Reference< deployment::XPackage > &rPackage );
void enableExtension( const uno::Reference< deployment::XPackage > &rPackage,
const bool bEnable );
void checkForUpdates( const uno::Sequence< uno::Reference< deployment::XPackageManager > > &rPackageManagers );
void checkForUpdate( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const uno::Reference< deployment::XPackage > &rPackage );
void stop();
bool hasTerminated();
static OUString searchAndReplaceAll( const OUString &rSource,
const OUString &rWhat,
const OUString &rWith );
private:
Thread( Thread & ); // not defined
void operator =( Thread & ); // not defined
virtual ~Thread();
virtual void execute();
virtual void SAL_CALL onTerminated();
void _addExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv,
const uno::Reference< deployment::XPackageManager > &xPackageManager,
const OUString &rPackageURL,
const bool bWarnUser );
void _removeExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv,
const uno::Reference< deployment::XPackageManager > &xPackageManager,
const uno::Reference< deployment::XPackage > &xPackage );
void _enableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv,
const uno::Reference< deployment::XPackage > &xPackage );
void _disableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv,
const uno::Reference< deployment::XPackage > &xPackage );
void _checkForUpdates( const uno::Sequence< uno::Reference< deployment::XPackageManager > > &rPackageManagers,
const uno::Reference< deployment::XPackageManager > &xPackageManager,
const uno::Reference< deployment::XPackage > &xPackage );
enum Input { NONE, START, STOP };
uno::Reference< uno::XComponentContext > m_xContext;
std::queue< TExtensionCmd > m_queue;
ExtMgrDialog *m_pDialog;
TheExtensionManager *m_pManager;
const OUString m_sEnablingPackages;
const OUString m_sDisablingPackages;
const OUString m_sAddingPackages;
const OUString m_sRemovingPackages;
osl::Condition m_wakeup;
osl::Mutex m_mutex;
Input m_eInput;
bool m_bTerminated;
bool m_bStopped;
};
//------------------------------------------------------------------------------
void ProgressCmdEnv::startProgress()
{
m_nCurrentProgress = 0;
m_pDialog->showProgress( true );
}
//------------------------------------------------------------------------------
void ProgressCmdEnv::stopProgress()
{
m_pDialog->showProgress( false );
}
//------------------------------------------------------------------------------
void ProgressCmdEnv::progressSection( const OUString &rText,
const uno::Reference< task::XAbortChannel > &xAbortChannel )
{
m_xAbortChannel = xAbortChannel;
if (! m_bAborted)
{
m_nCurrentProgress = 0;
m_pDialog->updateProgress( rText, xAbortChannel );
m_pDialog->updateProgress( 5 );
}
}
//------------------------------------------------------------------------------
void ProgressCmdEnv::updateProgress()
{
if ( ! m_bAborted )
{
long nProgress = ((m_nCurrentProgress*5) % 100) + 5;
m_pDialog->updateProgress( nProgress );
}
}
//------------------------------------------------------------------------------
ProgressCmdEnv::~ProgressCmdEnv()
{
// TODO: stop all threads and wait
}
//------------------------------------------------------------------------------
// XCommandEnvironment
//------------------------------------------------------------------------------
uno::Reference< task::XInteractionHandler > ProgressCmdEnv::getInteractionHandler()
throw ( uno::RuntimeException )
{
return this;
}
//------------------------------------------------------------------------------
uno::Reference< ucb::XProgressHandler > ProgressCmdEnv::getProgressHandler()
throw ( uno::RuntimeException )
{
return this;
}
//------------------------------------------------------------------------------
// XInteractionHandler
//------------------------------------------------------------------------------
void ProgressCmdEnv::handle( uno::Reference< task::XInteractionRequest > const & xRequest )
throw ( uno::RuntimeException )
{
uno::Any request( xRequest->getRequest() );
OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION );
#if OSL_DEBUG_LEVEL > 1
OSL_TRACE( "[dp_gui_cmdenv.cxx] incoming request:\n%s\n",
::rtl::OUStringToOString( ::comphelper::anyToString(request),
RTL_TEXTENCODING_UTF8 ).getStr() );
#endif
lang::WrappedTargetException wtExc;
deployment::DependencyException depExc;
deployment::LicenseException licExc;
deployment::LicenseIndividualAgreementException licAgreementExc;
deployment::VersionException verExc;
deployment::InstallException instExc;
deployment::PlatformException platExc;
// selections:
bool approve = false;
bool abort = false;
if (request >>= wtExc) {
// handable deployment error signalled, e.g.
// bundle item registration failed, notify cause only:
uno::Any cause;
deployment::DeploymentException dpExc;
if (wtExc.TargetException >>= dpExc)
cause = dpExc.Cause;
else {
ucb::CommandFailedException cfExc;
if (wtExc.TargetException >>= cfExc)
cause = cfExc.Reason;
else
cause = wtExc.TargetException;
}
update_( cause );
// ignore intermediate errors of legacy packages, i.e.
// former pkgchk behaviour:
const uno::Reference< deployment::XPackage > xPackage( wtExc.Context, uno::UNO_QUERY );
OSL_ASSERT( xPackage.is() );
if ( xPackage.is() )
{
const uno::Reference< deployment::XPackageTypeInfo > xPackageType( xPackage->getPackageType() );
OSL_ASSERT( xPackageType.is() );
if (xPackageType.is())
{
approve = ( xPackage->isBundle() &&
xPackageType->getMediaType().matchAsciiL(
RTL_CONSTASCII_STRINGPARAM(
"application/"
"vnd.sun.star.legacy-package-bundle") ));
}
}
abort = !approve;
}
else if (request >>= depExc)
{
std::vector< rtl::OUString > deps;
for (sal_Int32 i = 0; i < depExc.UnsatisfiedDependencies.getLength();
++i)
{
deps.push_back(
dp_misc::Dependencies::name( depExc.UnsatisfiedDependencies[i]) );
}
{
vos::OGuard guard(Application::GetSolarMutex());
short n = DependencyDialog( m_pDialog, deps ).Execute();
// Distinguish between closing the dialog and programatically
// canceling the dialog (headless VCL):
approve = n == RET_OK
|| n == RET_CANCEL && !Application::IsDialogCancelEnabled();
}
}
else if (request >>= licAgreementExc)
{
vos::OGuard aSolarGuard( Application::GetSolarMutex() );
ResId warnId(WARNINGBOX_NOSHAREDALLOWED, *DeploymentGuiResMgr::get());
WarningBox warn( m_pDialog, warnId);
String msgText = warn.GetMessText();
msgText.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() );
msgText.SearchAndReplaceAllAscii("%NAME", licAgreementExc.ExtensionName);
warn.SetMessText(msgText);
warn.Execute();
abort = true;
}
else if (request >>= licExc)
{
uno::Reference< ui::dialogs::XExecutableDialog > xDialog(
deployment::ui::LicenseDialog::create(
m_xContext, VCLUnoHelper::GetInterface( m_pDialog ), licExc.Text ) );
sal_Int16 res = xDialog->execute();
if ( res == ui::dialogs::ExecutableDialogResults::CANCEL )
abort = true;
else if ( res == ui::dialogs::ExecutableDialogResults::OK )
approve = true;
else
{
OSL_ASSERT(0);
}
}
else if (request >>= verExc)
{
sal_uInt32 id;
switch (dp_misc::comparePackageVersions( verExc.New, verExc.Deployed ))
{
case dp_misc::LESS:
id = RID_WARNINGBOX_VERSION_LESS;
break;
case dp_misc::EQUAL:
id = RID_WARNINGBOX_VERSION_EQUAL;
break;
default: // dp_misc::GREATER
id = RID_WARNINGBOX_VERSION_GREATER;
break;
}
OSL_ASSERT( verExc.New.is() && verExc.Deployed.is() );
bool bEqualNames = verExc.New->getDisplayName().equals(
verExc.Deployed->getDisplayName());
{
vos::OGuard guard(Application::GetSolarMutex());
WarningBox box( m_pDialog, ResId(id, *DeploymentGuiResMgr::get()));
String s;
if (bEqualNames)
{
s = box.GetMessText();
}
else if (id == RID_WARNINGBOX_VERSION_EQUAL)
{
//hypothetical: requires two instances of an extension with the same
//version to have different display names. Probably the developer forgot
//to change the version.
s = String(ResId(RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES, *DeploymentGuiResMgr::get()));
}
else if (id == RID_WARNINGBOX_VERSION_LESS)
{
s = String(ResId(RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES, *DeploymentGuiResMgr::get()));
}
else if (id == RID_WARNINGBOX_VERSION_GREATER)
{
s = String(ResId(RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES, *DeploymentGuiResMgr::get()));
}
s.SearchAndReplaceAllAscii( "$NAME", verExc.New->getDisplayName());
s.SearchAndReplaceAllAscii( "$OLDNAME", verExc.Deployed->getDisplayName());
s.SearchAndReplaceAllAscii( "$NEW", getVersion(verExc.New) );
s.SearchAndReplaceAllAscii( "$DEPLOYED", getVersion(verExc.Deployed) );
box.SetMessText(s);
approve = box.Execute() == RET_OK;
abort = !approve;
}
}
else if (request >>= instExc)
{
if ( ! m_bWarnUser )
{
approve = true;
}
else
{
vos::OGuard guard(Application::GetSolarMutex());
approve = m_pDialog->installExtensionWarn( instExc.New->getDisplayName() );
abort = !approve;
}
}
else if (request >>= platExc)
{
vos::OGuard guard( Application::GetSolarMutex() );
String sMsg( ResId( RID_STR_UNSUPPORTED_PLATFORM, *DeploymentGuiResMgr::get() ) );
sMsg.SearchAndReplaceAllAscii( "%Name", platExc.package->getDisplayName() );
ErrorBox box( m_pDialog, WB_OK, sMsg );
box.Execute();
approve = true;
}
if (approve == false && abort == false)
{
// forward to UUI handler:
if (! m_xHandler.is()) {
// late init:
uno::Sequence< uno::Any > handlerArgs( 1 );
handlerArgs[ 0 ] <<= beans::PropertyValue(
OUSTR("Context"), -1, uno::Any( m_sTitle ),
beans::PropertyState_DIRECT_VALUE );
m_xHandler.set( m_xContext->getServiceManager()
->createInstanceWithArgumentsAndContext(
OUSTR("com.sun.star.uui.InteractionHandler"),
handlerArgs, m_xContext ), uno::UNO_QUERY_THROW );
}
m_xHandler->handle( xRequest );
}
else
{
// select:
uno::Sequence< uno::Reference< task::XInteractionContinuation > > conts(
xRequest->getContinuations() );
uno::Reference< task::XInteractionContinuation > const * pConts = conts.getConstArray();
sal_Int32 len = conts.getLength();
for ( sal_Int32 pos = 0; pos < len; ++pos )
{
if (approve) {
uno::Reference< task::XInteractionApprove > xInteractionApprove( pConts[ pos ], uno::UNO_QUERY );
if (xInteractionApprove.is()) {
xInteractionApprove->select();
// don't query again for ongoing continuations:
approve = false;
}
}
else if (abort) {
uno::Reference< task::XInteractionAbort > xInteractionAbort( pConts[ pos ], uno::UNO_QUERY );
if (xInteractionAbort.is()) {
xInteractionAbort->select();
// don't query again for ongoing continuations:
abort = false;
}
}
}
}
}
//------------------------------------------------------------------------------
// XProgressHandler
//------------------------------------------------------------------------------
void ProgressCmdEnv::push( uno::Any const & rStatus )
throw( uno::RuntimeException )
{
update_( rStatus );
}
//------------------------------------------------------------------------------
void ProgressCmdEnv::update_( uno::Any const & rStatus )
throw( uno::RuntimeException )
{
OUString text;
if ( rStatus.hasValue() && !( rStatus >>= text) )
{
if ( rStatus.getValueTypeClass() == uno::TypeClass_EXCEPTION )
text = static_cast< uno::Exception const *>( rStatus.getValue() )->Message;
if ( text.getLength() == 0 )
text = ::comphelper::anyToString( rStatus ); // fallback
const ::vos::OGuard aGuard( Application::GetSolarMutex() );
const ::std::auto_ptr< ErrorBox > aBox( new ErrorBox( m_pDialog, WB_OK, text ) );
aBox->Execute();
}
++m_nCurrentProgress;
updateProgress();
}
//------------------------------------------------------------------------------
void ProgressCmdEnv::update( uno::Any const & rStatus )
throw( uno::RuntimeException )
{
update_( rStatus );
}
//------------------------------------------------------------------------------
void ProgressCmdEnv::pop()
throw( uno::RuntimeException )
{
update_( uno::Any() ); // no message
}
//------------------------------------------------------------------------------
ExtensionCmdQueue::Thread::Thread( ExtMgrDialog *pDialog,
TheExtensionManager *pManager,
const uno::Reference< uno::XComponentContext > & rContext ) :
m_xContext( rContext ),
m_pDialog( pDialog ),
m_pManager( pManager ),
m_sEnablingPackages( ExtMgrDialog::getResourceString( RID_STR_ENABLING_PACKAGES ) ),
m_sDisablingPackages( ExtMgrDialog::getResourceString( RID_STR_DISABLING_PACKAGES ) ),
m_sAddingPackages( ExtMgrDialog::getResourceString( RID_STR_ADDING_PACKAGES ) ),
m_sRemovingPackages( ExtMgrDialog::getResourceString( RID_STR_REMOVING_PACKAGES ) ),
m_eInput( NONE ),
m_bTerminated( false ),
m_bStopped( false )
{
OSL_ASSERT( pDialog );
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::addExtension( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const ::rtl::OUString &rExtensionURL,
const bool bWarnUser )
{
::osl::MutexGuard aGuard( m_mutex );
//If someone called stop then we do not add the extension -> game over!
if ( m_bStopped )
return;
if ( rExtensionURL.getLength() )
{
TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::ADD, rPackageManager, rExtensionURL, bWarnUser ) );
m_queue.push( pEntry );
m_eInput = START;
m_wakeup.set();
}
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::removeExtension( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const uno::Reference< deployment::XPackage > &rPackage )
{
::osl::MutexGuard aGuard( m_mutex );
//If someone called stop then we do not remove the extension -> game over!
if ( m_bStopped )
return;
if ( rPackageManager.is() && rPackage.is() )
{
TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::REMOVE, rPackageManager, rPackage ) );
m_queue.push( pEntry );
m_eInput = START;
m_wakeup.set();
}
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::enableExtension( const uno::Reference< deployment::XPackage > &rPackage,
const bool bEnable )
{
::osl::MutexGuard aGuard( m_mutex );
//If someone called stop then we do not remove the extension -> game over!
if ( m_bStopped )
return;
if ( rPackage.is() )
{
TExtensionCmd pEntry( new ExtensionCmd( bEnable ? ExtensionCmd::ENABLE :
ExtensionCmd::DISABLE,
rPackage ) );
m_queue.push( pEntry );
m_eInput = START;
m_wakeup.set();
}
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::checkForUpdates( const uno::Sequence< uno::Reference< deployment::XPackageManager > > &rPackageManagers )
{
::osl::MutexGuard aGuard( m_mutex );
//If someone called stop then we do not remove the extension -> game over!
if ( m_bStopped )
return;
TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::CHECK_FOR_UPDATES, rPackageManagers ) );
m_queue.push( pEntry );
m_eInput = START;
m_wakeup.set();
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::checkForUpdate( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const uno::Reference< deployment::XPackage > &rPackage )
{
::osl::MutexGuard aGuard( m_mutex );
//If someone called stop then we do not remove the extension -> game over!
if ( m_bStopped )
return;
if ( rPackageManager.is() && rPackage.is() )
{
TExtensionCmd pEntry( new ExtensionCmd( ExtensionCmd::CHECK_FOR_UPDATE, rPackageManager, rPackage ) );
m_queue.push( pEntry );
m_eInput = START;
m_wakeup.set();
}
}
//------------------------------------------------------------------------------
//Stopping this thread will not abort the installation of extensions.
void ExtensionCmdQueue::Thread::stop()
{
osl::MutexGuard aGuard( m_mutex );
m_bStopped = true;
m_eInput = STOP;
m_wakeup.set();
}
//------------------------------------------------------------------------------
bool ExtensionCmdQueue::Thread::hasTerminated()
{
osl::MutexGuard aGuard( m_mutex );
return m_bTerminated;
}
//------------------------------------------------------------------------------
ExtensionCmdQueue::Thread::~Thread() {}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::execute()
{
for (;;)
{
if ( m_wakeup.wait() != osl::Condition::result_ok )
{
OSL_TRACE( "dp_gui::ExtensionCmdQueue::Thread::run: ignored "
"osl::Condition::wait failure" );
}
m_wakeup.reset();
int nSize;
Input eInput;
{
osl::MutexGuard aGuard( m_mutex );
eInput = m_eInput;
m_eInput = NONE;
nSize = m_queue.size();
}
// If this thread has been woken up by anything else except start, stop
// then input is NONE and we wait again.
// We only install the extension which are currently in the queue.
// The progressbar will be set to show the progress of the current number
// of extensions. If we allowed to add extensions now then the progressbar may
// have reached the end while we still install newly added extensions.
if ( ( eInput == NONE ) || ( nSize == 0 ) )
continue;
if ( eInput == STOP )
break;
::rtl::Reference< ProgressCmdEnv > currentCmdEnv( new ProgressCmdEnv( m_xContext, m_pDialog, m_sAddingPackages ) );
// Do not lock the following part with addExtension. addExtension may be called in the main thread.
// If the message box "Do you want to install the extension (or similar)" is shown and then
// addExtension is called, which then blocks the main thread, then we deadlock.
bool bStartProgress = true;
while ( !currentCmdEnv->isAborted() && --nSize >= 0 )
{
try
{
TExtensionCmd pEntry;
{
::osl::MutexGuard queueGuard( m_mutex );
pEntry = m_queue.front();
m_queue.pop();
}
if ( bStartProgress && ( pEntry->m_eCmdType != ExtensionCmd::CHECK_FOR_UPDATE ) &&
( pEntry->m_eCmdType != ExtensionCmd::CHECK_FOR_UPDATES ) )
{
currentCmdEnv->startProgress();
bStartProgress = false;
}
switch ( pEntry->m_eCmdType ) {
case ExtensionCmd::ADD :
_addExtension( currentCmdEnv, pEntry->m_xPackageManager, pEntry->m_sExtensionURL, pEntry->m_bWarnUser );
break;
case ExtensionCmd::REMOVE :
_removeExtension( currentCmdEnv, pEntry->m_xPackageManager, pEntry->m_xPackage );
break;
case ExtensionCmd::ENABLE :
_enableExtension( currentCmdEnv, pEntry->m_xPackage );
break;
case ExtensionCmd::DISABLE :
_disableExtension( currentCmdEnv, pEntry->m_xPackage );
break;
case ExtensionCmd::CHECK_FOR_UPDATE :
case ExtensionCmd::CHECK_FOR_UPDATES :
_checkForUpdates( pEntry->m_xPackageManagers, pEntry->m_xPackageManager, pEntry->m_xPackage );
break;
}
}
//catch ( deployment::DeploymentException &)
//{
//}
//catch ( lang::IllegalArgumentException &)
//{
//}
catch ( ucb::CommandAbortedException & )
{
//This exception is thrown when the user clicks cancel on the progressbar.
//Then we cancel the installation of all extensions and remove them from
//the queue.
{
::osl::MutexGuard queueGuard2(m_mutex);
while ( --nSize >= 0 )
m_queue.pop();
}
break;
}
catch ( ucb::CommandFailedException & )
{
//This exception is thrown when a user clicked cancel in the messagebox which was
//startet by the interaction handler. For example the user will be asked if he/she
//really wants to install the extension.
//These interaction are run for exectly one extension at a time. Therefore we continue
//with installing the remaining extensions.
continue;
}
catch ( uno::Exception & )
{
//Todo display the user an error
//see also DialogImpl::SyncPushButton::Click()
uno::Any exc( ::cppu::getCaughtException() );
OUString msg;
deployment::DeploymentException dpExc;
if ((exc >>= dpExc) &&
dpExc.Cause.getValueTypeClass() == uno::TypeClass_EXCEPTION)
{
// notify error cause only:
msg = reinterpret_cast< uno::Exception const * >( dpExc.Cause.getValue() )->Message;
}
if (msg.getLength() == 0) // fallback for debugging purposes
msg = ::comphelper::anyToString(exc);
const ::vos::OGuard guard( Application::GetSolarMutex() );
::std::auto_ptr<ErrorBox> box(
new ErrorBox( currentCmdEnv->activeDialog(), WB_OK, msg ) );
box->SetText( m_pDialog->GetText() );
box->Execute();
//Continue with installation of the remaining extensions
}
}
if ( !bStartProgress )
currentCmdEnv->stopProgress();
}
//end for
//enable all buttons
// m_pDialog->m_bAddingExtensions = false;
// m_pDialog->updateButtonStates();
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::_addExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv,
const uno::Reference< deployment::XPackageManager > &xPackageManager,
const OUString &rPackageURL,
const bool bWarnUser )
{
//check if we have a string in anyTitle. For example "unopkg gui \" caused anyTitle to be void
//and anyTitle.get<OUString> throws as RuntimeException.
uno::Any anyTitle = ::ucbhelper::Content( rPackageURL, rCmdEnv.get() ).getPropertyValue( OUSTR("Title") );
OUString sName;
if ( ! (anyTitle >>= sName) )
{
OSL_ENSURE(0, "Could not get file name for extension.");
return;
}
rCmdEnv->setWarnUser( bWarnUser );
uno::Reference< task::XAbortChannel > xAbortChannel( xPackageManager->createAbortChannel() );
OUString sTitle = searchAndReplaceAll( m_sAddingPackages, OUSTR("%EXTENSION_NAME"), sName );
rCmdEnv->progressSection( sTitle, xAbortChannel );
try
{
uno::Reference< deployment::XPackage > xPackage( xPackageManager->addPackage(
rPackageURL, OUString() /* detect media-type */,
xAbortChannel, rCmdEnv.get() ) );
OSL_ASSERT( xPackage.is() );
// long nPos = m_pDialog->addPackageToList( xPackage, xPackageManager );
// m_pDialog->selectEntry( nPos );
}
catch ( ucb::CommandFailedException & )
{
// When the extension is already installed we'll get a dialog asking if we want to overwrite. If we then press
// cancel this exception is thrown.
}
catch ( ucb::CommandAbortedException & )
{
// User clicked the cancel button
// TODO: handle cancel
}
rCmdEnv->setWarnUser( false );
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::_removeExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv,
const uno::Reference< deployment::XPackageManager > &xPackageManager,
const uno::Reference< deployment::XPackage > &xPackage )
{
uno::Reference< task::XAbortChannel > xAbortChannel( xPackageManager->createAbortChannel() );
OUString sTitle = searchAndReplaceAll( m_sRemovingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName() );
rCmdEnv->progressSection( sTitle, xAbortChannel );
OUString id( dp_misc::getIdentifier( xPackage ) );
try
{
xPackageManager->removePackage( id, xPackage->getName(), xAbortChannel, rCmdEnv.get() );
m_pDialog->removeEntry( xPackage );
}
catch ( ucb::CommandAbortedException & )
{}
// Check, if there are still updates to be notified via menu bar icon
uno::Sequence< uno::Sequence< rtl::OUString > > aItemList;
UpdateDialog::createNotifyJob( false, aItemList );
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::_checkForUpdates( const uno::Sequence< uno::Reference< deployment::XPackageManager > > &rPackageManagers,
const uno::Reference< deployment::XPackageManager > &xPackageManager,
const uno::Reference< deployment::XPackage > &xPackage )
{
UpdateDialog* pUpdateDialog;
std::vector< UpdateData > vData;
const ::vos::OGuard guard( Application::GetSolarMutex() );
if ( xPackageManager.is() && xPackage.is() )
pUpdateDialog = new UpdateDialog( m_xContext, m_pDialog, new SelectedPackage( xPackage, xPackageManager ),
uno::Sequence< uno::Reference< deployment::XPackageManager > >(), &vData );
else
pUpdateDialog = new UpdateDialog( m_xContext, m_pDialog, rtl::Reference< SelectedPackage >(),
rPackageManagers, &vData );
if ( ( pUpdateDialog->Execute() == RET_OK ) && !vData.empty() )
{
pUpdateDialog->notifyMenubar( true, false ); // prepare the checking, if there updates to be notified via menu bar icon
// If there is at least one directly downloadable dialog then we
// open the install dialog.
::std::vector< UpdateData > dataDownload;
int countWebsiteDownload = 0;
typedef std::vector< dp_gui::UpdateData >::const_iterator cit;
for ( cit i = vData.begin(); i < vData.end(); i++ )
{
if ( i->sWebsiteURL.getLength() > 0 )
countWebsiteDownload ++;
else
dataDownload.push_back( *i );
}
short nDialogResult = RET_OK;
if ( !dataDownload.empty() )
{
nDialogResult = UpdateInstallDialog( m_pDialog, dataDownload, m_xContext ).Execute();
pUpdateDialog->notifyMenubar( false, true ); // Check, if there are still pending updates to be notified via menu bar icon
}
else
pUpdateDialog->notifyMenubar( false, false ); // Check, if there are pending updates to be notified via menu bar icon
//Now start the webbrowser and navigate to the websites where we get the updates
if ( RET_OK == nDialogResult )
{
for ( cit i = vData.begin(); i < vData.end(); i++ )
{
if ( i->sWebsiteURL.getLength() > 0 )
m_pDialog->openWebBrowser( i->sWebsiteURL );
}
}
}
delete pUpdateDialog;
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::_enableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv,
const uno::Reference< deployment::XPackage > &xPackage )
{
if ( !xPackage.is() )
return;
uno::Reference< task::XAbortChannel > xAbortChannel( xPackage->createAbortChannel() );
OUString sTitle = searchAndReplaceAll( m_sEnablingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName() );
rCmdEnv->progressSection( sTitle, xAbortChannel );
try
{
xPackage->registerPackage( xAbortChannel, rCmdEnv.get() );
m_pDialog->updatePackageInfo( xPackage );
}
catch ( ::ucb::CommandAbortedException & )
{}
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::_disableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv,
const uno::Reference< deployment::XPackage > &xPackage )
{
if ( !xPackage.is() )
return;
uno::Reference< task::XAbortChannel > xAbortChannel( xPackage->createAbortChannel() );
OUString sTitle = searchAndReplaceAll( m_sDisablingPackages, OUSTR("%EXTENSION_NAME"), xPackage->getDisplayName() );
rCmdEnv->progressSection( sTitle, xAbortChannel );
try
{
xPackage->revokePackage( xAbortChannel, rCmdEnv.get() );
m_pDialog->updatePackageInfo( xPackage );
}
catch ( ::ucb::CommandAbortedException & )
{}
}
//------------------------------------------------------------------------------
void ExtensionCmdQueue::Thread::onTerminated()
{
::osl::MutexGuard g(m_mutex);
m_bTerminated = true;
}
//------------------------------------------------------------------------------
OUString ExtensionCmdQueue::Thread::searchAndReplaceAll( const OUString &rSource,
const OUString &rWhat,
const OUString &rWith )
{
OUString aRet( rSource );
sal_Int32 nLen = rWhat.getLength();
if ( !nLen )
return aRet;
sal_Int32 nIndex = rSource.indexOf( rWhat );
while ( nIndex != -1 )
{
aRet = aRet.replaceAt( nIndex, nLen, rWith );
nIndex = aRet.indexOf( rWhat, nIndex + rWith.getLength() );
}
return aRet;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
ExtensionCmdQueue::ExtensionCmdQueue( ExtMgrDialog * pDialog,
TheExtensionManager *pManager,
const uno::Reference< uno::XComponentContext > &rContext )
: m_thread( new Thread( pDialog, pManager, rContext ) )
{
m_thread->launch();
}
ExtensionCmdQueue::~ExtensionCmdQueue() {
stop();
}
void ExtensionCmdQueue::addExtension( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const ::rtl::OUString & extensionURL,
const bool bWarnUser )
{
m_thread->addExtension( rPackageManager, extensionURL, bWarnUser );
}
void ExtensionCmdQueue::removeExtension( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const uno::Reference< deployment::XPackage > &rPackage )
{
m_thread->removeExtension( rPackageManager, rPackage );
}
void ExtensionCmdQueue::enableExtension( const uno::Reference< deployment::XPackage > &rPackage,
const bool bEnable )
{
m_thread->enableExtension( rPackage, bEnable );
}
void ExtensionCmdQueue::checkForUpdates( const uno::Sequence< uno::Reference< deployment::XPackageManager > > &rPackageManagers )
{
m_thread->checkForUpdates( rPackageManagers );
}
void ExtensionCmdQueue::checkForUpdate( const uno::Reference< deployment::XPackageManager > &rPackageManager,
const uno::Reference< deployment::XPackage > &rPackage )
{
m_thread->checkForUpdate( rPackageManager, rPackage );
}
void ExtensionCmdQueue::stop()
{
m_thread->stop();
}
void ExtensionCmdQueue::stopAndWait()
{
m_thread->stop();
m_thread->join();
}
bool ExtensionCmdQueue::hasTerminated()
{
return m_thread->hasTerminated();
}
} //namespace dp_gui
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment