summaryrefslogtreecommitdiff
path: root/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx
diff options
context:
space:
mode:
authorKurt Zenker <kz@openoffice.org>2008-05-21 11:26:33 +0000
committerKurt Zenker <kz@openoffice.org>2008-05-21 11:26:33 +0000
commitf167d090345c9c7950665e50006aff4fc0ace078 (patch)
tree32adad557a62211fd13ab0b8bfc1c45425a69d1f /desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx
parent8ee302b04c5b12cfbb25e7021225ea8dc3635333 (diff)
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
Diffstat (limited to 'desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx')
-rw-r--r--desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx1161
1 files changed, 1161 insertions, 0 deletions
diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx
new file mode 100644
index 000000000000..50aad1743fdd
--- /dev/null
+++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx
@@ -0,0 +1,1161 @@
+/*************************************************************************
+ *
+ * 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
+