1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dp_gui_extensioncmdqueue.cxx,v $
11 * $Revision: 1.7.4.3 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_desktop.hxx"
38 #include "sal/config.h"
42 #include "com/sun/star/beans/PropertyValue.hpp"
44 #include "com/sun/star/deployment/DependencyException.hpp"
45 #include "com/sun/star/deployment/LicenseException.hpp"
46 #include "com/sun/star/deployment/LicenseIndividualAgreementException.hpp"
47 #include "com/sun/star/deployment/VersionException.hpp"
48 #include "com/sun/star/deployment/InstallException.hpp"
49 #include "com/sun/star/deployment/PlatformException.hpp"
51 #include "com/sun/star/deployment/ui/LicenseDialog.hpp"
52 #include "com/sun/star/deployment/DeploymentException.hpp"
53 #include "com/sun/star/deployment/UpdateInformationProvider.hpp"
54 #include "com/sun/star/deployment/XPackage.hpp"
55 #include "com/sun/star/deployment/XPackageManager.hpp"
57 #include "com/sun/star/task/XAbortChannel.hpp"
58 #include "com/sun/star/task/XInteractionAbort.hpp"
59 #include "com/sun/star/task/XInteractionApprove.hpp"
61 #include "com/sun/star/ucb/CommandAbortedException.hpp"
62 #include "com/sun/star/ucb/CommandFailedException.hpp"
63 #include "com/sun/star/ucb/XCommandEnvironment.hpp"
65 #include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp"
67 #include "com/sun/star/uno/Reference.hxx"
68 #include "com/sun/star/uno/RuntimeException.hpp"
69 #include "com/sun/star/uno/Sequence.hxx"
70 #include "com/sun/star/uno/XInterface.hpp"
71 #include "com/sun/star/uno/TypeClass.hpp"
72 #include "osl/diagnose.h"
73 #include "osl/mutex.hxx"
74 #include "rtl/ref.hxx"
75 #include "rtl/ustring.h"
76 #include "rtl/ustring.hxx"
77 #include "sal/types.h"
78 #include "ucbhelper/content.hxx"
79 #include "cppuhelper/exc_hlp.hxx"
80 #include "cppuhelper/implbase3.hxx"
81 #include "comphelper/anytostring.hxx"
82 #include "vcl/msgbox.hxx"
83 #include "toolkit/helper/vclunohelper.hxx"
86 #include "dp_gui_thread.hxx"
87 #include "dp_gui_extensioncmdqueue.hxx"
88 #include "dp_gui_dependencydialog.hxx"
89 #include "dp_gui_dialog2.hxx"
90 #include "dp_gui_shared.hxx"
91 #include "dp_gui_theextmgr.hxx"
92 #include "dp_gui_updatedialog.hxx"
93 #include "dp_gui_updateinstalldialog.hxx"
94 #include "dp_dependencies.hxx"
95 #include "dp_identifier.hxx"
96 #include "dp_version.hxx"
99 #include <boost/shared_ptr.hpp>
101 #if (defined(_MSC_VER) && (_MSC_VER < 1400))
102 #define _WIN32_WINNT 0x0400
106 #include "tools/prewin.h"
108 #include "tools/postwin.h"
112 using namespace ::com::sun::star
;
113 using ::rtl::OUString
;
117 OUString
getVersion( const uno::Reference
< deployment::XPackage
> &rPackage
)
119 OUString
sVersion( rPackage
->getVersion());
120 return ( sVersion
.getLength() == 0 ) ? OUString( RTL_CONSTASCII_USTRINGPARAM( "0" ) ) : sVersion
;
128 //==============================================================================
131 : public ::cppu::WeakImplHelper3
< ucb::XCommandEnvironment
,
132 task::XInteractionHandler
,
133 ucb::XProgressHandler
>
135 uno::Reference
< task::XInteractionHandler
> m_xHandler
;
136 uno::Reference
< uno::XComponentContext
> m_xContext
;
137 uno::Reference
< task::XAbortChannel
> m_xAbortChannel
;
139 DialogHelper
*m_pDialogHelper
;
143 sal_Int32 m_nCurrentProgress
;
145 void updateProgress();
147 void update_( uno::Any
const & Status
) throw ( uno::RuntimeException
);
150 virtual ~ProgressCmdEnv();
152 /** When param bAskWhenInstalling = true, then the user is asked if he
153 agrees to install this extension. In case this extension is already installed
154 then the user is also notified and asked if he wants to replace that existing
155 extension. In first case an interaction request with an InstallException
156 will be handled and in the second case a VersionException will be handled.
159 ProgressCmdEnv( const uno::Reference
< uno::XComponentContext
> rContext
,
160 DialogHelper
*pDialogHelper
,
161 const OUString
&rTitle
)
162 : m_xContext( rContext
),
163 m_pDialogHelper( pDialogHelper
),
169 Dialog
* activeDialog() { return m_pDialogHelper
->getWindow(); }
171 void setTitle( const OUString
& rNewTitle
) { m_sTitle
= rNewTitle
; }
172 void startProgress();
174 void progressSection( const OUString
&rText
,
175 const uno::Reference
< task::XAbortChannel
> &xAbortChannel
= 0 );
176 inline bool isAborted() const { return m_bAborted
; }
177 inline void setWarnUser( bool bNewVal
) { m_bWarnUser
= bNewVal
; }
179 // XCommandEnvironment
180 virtual uno::Reference
< task::XInteractionHandler
> SAL_CALL
getInteractionHandler()
181 throw ( uno::RuntimeException
);
182 virtual uno::Reference
< ucb::XProgressHandler
> SAL_CALL
getProgressHandler()
183 throw ( uno::RuntimeException
);
185 // XInteractionHandler
186 virtual void SAL_CALL
handle( uno::Reference
< task::XInteractionRequest
> const & xRequest
)
187 throw ( uno::RuntimeException
);
190 virtual void SAL_CALL
push( uno::Any
const & Status
)
191 throw ( uno::RuntimeException
);
192 virtual void SAL_CALL
update( uno::Any
const & Status
)
193 throw ( uno::RuntimeException
);
194 virtual void SAL_CALL
pop() throw ( uno::RuntimeException
);
197 //------------------------------------------------------------------------------
200 enum E_CMD_TYPE
{ ADD
, ENABLE
, DISABLE
, REMOVE
, CHECK_FOR_UPDATES
};
202 E_CMD_TYPE m_eCmdType
;
204 OUString m_sExtensionURL
;
205 uno::Reference
< deployment::XPackageManager
> m_xPackageManager
;
206 uno::Reference
< deployment::XPackage
> m_xPackage
;
207 std::vector
< TUpdateListEntry
> m_vExtensionList
;
209 ExtensionCmd( const E_CMD_TYPE eCommand
,
210 const uno::Reference
< deployment::XPackageManager
> &rPackageManager
,
211 const OUString
&rExtensionURL
,
212 const bool bWarnUser
)
213 : m_eCmdType( eCommand
),
214 m_bWarnUser( bWarnUser
),
215 m_sExtensionURL( rExtensionURL
),
216 m_xPackageManager( rPackageManager
) {};
217 ExtensionCmd( const E_CMD_TYPE eCommand
,
218 const uno::Reference
< deployment::XPackageManager
> &rPackageManager
,
219 const uno::Reference
< deployment::XPackage
> &rPackage
)
220 : m_eCmdType( eCommand
),
221 m_bWarnUser( false ),
222 m_xPackageManager( rPackageManager
),
223 m_xPackage( rPackage
) {};
224 ExtensionCmd( const E_CMD_TYPE eCommand
,
225 const uno::Reference
< deployment::XPackage
> &rPackage
)
226 : m_eCmdType( eCommand
),
227 m_bWarnUser( false ),
228 m_xPackage( rPackage
) {};
229 ExtensionCmd( const E_CMD_TYPE eCommand
,
230 const std::vector
< TUpdateListEntry
> &vExtensionList
)
231 : m_eCmdType( eCommand
),
232 m_bWarnUser( false ),
233 m_vExtensionList( vExtensionList
) {};
236 typedef ::boost::shared_ptr
< ExtensionCmd
> TExtensionCmd
;
238 //------------------------------------------------------------------------------
239 class ExtensionCmdQueue::Thread
: public dp_gui::Thread
242 Thread( DialogHelper
*pDialogHelper
,
243 TheExtensionManager
*pManager
,
244 const uno::Reference
< uno::XComponentContext
> & rContext
);
246 void addExtension( const uno::Reference
< deployment::XPackageManager
> &rPackageManager
,
247 const OUString
&rExtensionURL
,
248 const bool bWarnUser
);
249 void removeExtension( const uno::Reference
< deployment::XPackageManager
> &rPackageManager
,
250 const uno::Reference
< deployment::XPackage
> &rPackage
);
251 void enableExtension( const uno::Reference
< deployment::XPackage
> &rPackage
,
252 const bool bEnable
);
253 void checkForUpdates( const std::vector
< TUpdateListEntry
> &vExtensionList
);
255 bool hasTerminated();
258 static OUString
searchAndReplaceAll( const OUString
&rSource
,
259 const OUString
&rWhat
,
260 const OUString
&rWith
);
262 Thread( Thread
& ); // not defined
263 void operator =( Thread
& ); // not defined
267 virtual void execute();
268 virtual void SAL_CALL
onTerminated();
270 void _addExtension( ::rtl::Reference
< ProgressCmdEnv
> &rCmdEnv
,
271 const uno::Reference
< deployment::XPackageManager
> &xPackageManager
,
272 const OUString
&rPackageURL
,
273 const bool bWarnUser
);
274 void _removeExtension( ::rtl::Reference
< ProgressCmdEnv
> &rCmdEnv
,
275 const uno::Reference
< deployment::XPackageManager
> &xPackageManager
,
276 const uno::Reference
< deployment::XPackage
> &xPackage
);
277 void _enableExtension( ::rtl::Reference
< ProgressCmdEnv
> &rCmdEnv
,
278 const uno::Reference
< deployment::XPackage
> &xPackage
);
279 void _disableExtension( ::rtl::Reference
< ProgressCmdEnv
> &rCmdEnv
,
280 const uno::Reference
< deployment::XPackage
> &xPackage
);
281 void _checkForUpdates( const std::vector
< TUpdateListEntry
> &vExtensionList
);
283 enum Input
{ NONE
, START
, STOP
};
285 uno::Reference
< uno::XComponentContext
> m_xContext
;
286 std::queue
< TExtensionCmd
> m_queue
;
288 DialogHelper
*m_pDialogHelper
;
289 TheExtensionManager
*m_pManager
;
291 const OUString m_sEnablingPackages
;
292 const OUString m_sDisablingPackages
;
293 const OUString m_sAddingPackages
;
294 const OUString m_sRemovingPackages
;
295 const OUString m_sDefaultCmd
;
296 osl::Condition m_wakeup
;
304 //------------------------------------------------------------------------------
305 void ProgressCmdEnv::startProgress()
307 m_nCurrentProgress
= 0;
309 if ( m_pDialogHelper
)
310 m_pDialogHelper
->showProgress( true );
313 //------------------------------------------------------------------------------
314 void ProgressCmdEnv::stopProgress()
316 if ( m_pDialogHelper
)
317 m_pDialogHelper
->showProgress( false );
320 //------------------------------------------------------------------------------
321 void ProgressCmdEnv::progressSection( const OUString
&rText
,
322 const uno::Reference
< task::XAbortChannel
> &xAbortChannel
)
324 m_xAbortChannel
= xAbortChannel
;
327 m_nCurrentProgress
= 0;
328 if ( m_pDialogHelper
)
330 m_pDialogHelper
->updateProgress( rText
, xAbortChannel
);
331 m_pDialogHelper
->updateProgress( 5 );
336 //------------------------------------------------------------------------------
337 void ProgressCmdEnv::updateProgress()
341 long nProgress
= ((m_nCurrentProgress
*5) % 100) + 5;
342 if ( m_pDialogHelper
)
343 m_pDialogHelper
->updateProgress( nProgress
);
347 //------------------------------------------------------------------------------
348 ProgressCmdEnv::~ProgressCmdEnv()
350 // TODO: stop all threads and wait
354 //------------------------------------------------------------------------------
355 // XCommandEnvironment
356 //------------------------------------------------------------------------------
357 uno::Reference
< task::XInteractionHandler
> ProgressCmdEnv::getInteractionHandler()
358 throw ( uno::RuntimeException
)
363 //------------------------------------------------------------------------------
364 uno::Reference
< ucb::XProgressHandler
> ProgressCmdEnv::getProgressHandler()
365 throw ( uno::RuntimeException
)
370 //------------------------------------------------------------------------------
371 // XInteractionHandler
372 //------------------------------------------------------------------------------
373 void ProgressCmdEnv::handle( uno::Reference
< task::XInteractionRequest
> const & xRequest
)
374 throw ( uno::RuntimeException
)
376 uno::Any
request( xRequest
->getRequest() );
377 OSL_ASSERT( request
.getValueTypeClass() == uno::TypeClass_EXCEPTION
);
378 dp_misc::TRACE( OUSTR("[dp_gui_cmdenv.cxx] incoming request:\n")
379 + ::comphelper::anyToString(request
) + OUSTR("\n"));
381 lang::WrappedTargetException wtExc
;
382 deployment::DependencyException depExc
;
383 deployment::LicenseException licExc
;
384 deployment::LicenseIndividualAgreementException licAgreementExc
;
385 deployment::VersionException verExc
;
386 deployment::InstallException instExc
;
387 deployment::PlatformException platExc
;
390 bool approve
= false;
393 if (request
>>= wtExc
) {
394 // handable deployment error signalled, e.g.
395 // bundle item registration failed, notify cause only:
397 deployment::DeploymentException dpExc
;
398 if (wtExc
.TargetException
>>= dpExc
)
401 ucb::CommandFailedException cfExc
;
402 if (wtExc
.TargetException
>>= cfExc
)
403 cause
= cfExc
.Reason
;
405 cause
= wtExc
.TargetException
;
409 // ignore intermediate errors of legacy packages, i.e.
410 // former pkgchk behaviour:
411 const uno::Reference
< deployment::XPackage
> xPackage( wtExc
.Context
, uno::UNO_QUERY
);
412 OSL_ASSERT( xPackage
.is() );
415 const uno::Reference
< deployment::XPackageTypeInfo
> xPackageType( xPackage
->getPackageType() );
416 OSL_ASSERT( xPackageType
.is() );
417 if (xPackageType
.is())
419 approve
= ( xPackage
->isBundle() &&
420 xPackageType
->getMediaType().matchAsciiL(
421 RTL_CONSTASCII_STRINGPARAM(
423 "vnd.sun.star.legacy-package-bundle") ));
428 else if (request
>>= depExc
)
430 std::vector
< rtl::OUString
> deps
;
431 for (sal_Int32 i
= 0; i
< depExc
.UnsatisfiedDependencies
.getLength();
435 dp_misc::Dependencies::getErrorText( depExc
.UnsatisfiedDependencies
[i
]) );
438 vos::OGuard
guard(Application::GetSolarMutex());
439 short n
= DependencyDialog( m_pDialogHelper
? m_pDialogHelper
->getWindow() : NULL
, deps
).Execute();
440 // Distinguish between closing the dialog and programatically
441 // canceling the dialog (headless VCL):
442 approve
= n
== RET_OK
443 || (n
== RET_CANCEL
&& !Application::IsDialogCancelEnabled());
446 else if (request
>>= licAgreementExc
)
448 vos::OGuard
aSolarGuard( Application::GetSolarMutex() );
449 ResId
warnId(WARNINGBOX_NOSHAREDALLOWED
, *DeploymentGuiResMgr::get());
450 WarningBox
warn( m_pDialogHelper
? m_pDialogHelper
->getWindow() : NULL
, warnId
);
451 String msgText
= warn
.GetMessText();
452 msgText
.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() );
453 msgText
.SearchAndReplaceAllAscii("%NAME", licAgreementExc
.ExtensionName
);
454 warn
.SetMessText(msgText
);
458 else if (request
>>= licExc
)
460 uno::Reference
< ui::dialogs::XExecutableDialog
> xDialog(
461 deployment::ui::LicenseDialog::create(
462 m_xContext
, VCLUnoHelper::GetInterface( m_pDialogHelper
? m_pDialogHelper
->getWindow() : NULL
), licExc
.Text
) );
463 sal_Int16 res
= xDialog
->execute();
464 if ( res
== ui::dialogs::ExecutableDialogResults::CANCEL
)
466 else if ( res
== ui::dialogs::ExecutableDialogResults::OK
)
473 else if (request
>>= verExc
)
476 switch (dp_misc::comparePackageVersions( verExc
.New
, verExc
.Deployed
))
479 id
= RID_WARNINGBOX_VERSION_LESS
;
482 id
= RID_WARNINGBOX_VERSION_EQUAL
;
484 default: // dp_misc::GREATER
485 id
= RID_WARNINGBOX_VERSION_GREATER
;
488 OSL_ASSERT( verExc
.New
.is() && verExc
.Deployed
.is() );
489 bool bEqualNames
= verExc
.New
->getDisplayName().equals(
490 verExc
.Deployed
->getDisplayName());
492 vos::OGuard
guard(Application::GetSolarMutex());
493 WarningBox
box( m_pDialogHelper
? m_pDialogHelper
->getWindow() : NULL
, ResId(id
, *DeploymentGuiResMgr::get()));
497 s
= box
.GetMessText();
499 else if (id
== RID_WARNINGBOX_VERSION_EQUAL
)
501 //hypothetical: requires two instances of an extension with the same
502 //version to have different display names. Probably the developer forgot
503 //to change the version.
504 s
= String(ResId(RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES
, *DeploymentGuiResMgr::get()));
506 else if (id
== RID_WARNINGBOX_VERSION_LESS
)
508 s
= String(ResId(RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES
, *DeploymentGuiResMgr::get()));
510 else if (id
== RID_WARNINGBOX_VERSION_GREATER
)
512 s
= String(ResId(RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES
, *DeploymentGuiResMgr::get()));
514 s
.SearchAndReplaceAllAscii( "$NAME", verExc
.New
->getDisplayName());
515 s
.SearchAndReplaceAllAscii( "$OLDNAME", verExc
.Deployed
->getDisplayName());
516 s
.SearchAndReplaceAllAscii( "$NEW", getVersion(verExc
.New
) );
517 s
.SearchAndReplaceAllAscii( "$DEPLOYED", getVersion(verExc
.Deployed
) );
519 approve
= box
.Execute() == RET_OK
;
523 else if (request
>>= instExc
)
531 if ( m_pDialogHelper
)
533 vos::OGuard
guard(Application::GetSolarMutex());
535 approve
= m_pDialogHelper
->installExtensionWarn( instExc
.New
->getDisplayName() );
542 else if (request
>>= platExc
)
544 vos::OGuard
guard( Application::GetSolarMutex() );
545 String
sMsg( ResId( RID_STR_UNSUPPORTED_PLATFORM
, *DeploymentGuiResMgr::get() ) );
546 sMsg
.SearchAndReplaceAllAscii( "%Name", platExc
.package
->getDisplayName() );
547 ErrorBox
box( m_pDialogHelper
? m_pDialogHelper
->getWindow() : NULL
, WB_OK
, sMsg
);
552 if (approve
== false && abort
== false)
554 // forward to UUI handler:
555 if (! m_xHandler
.is()) {
557 uno::Sequence
< uno::Any
> handlerArgs( 1 );
558 handlerArgs
[ 0 ] <<= beans::PropertyValue(
559 OUSTR("Context"), -1, uno::Any( m_sTitle
),
560 beans::PropertyState_DIRECT_VALUE
);
561 m_xHandler
.set( m_xContext
->getServiceManager()
562 ->createInstanceWithArgumentsAndContext(
563 OUSTR("com.sun.star.uui.InteractionHandler"),
564 handlerArgs
, m_xContext
), uno::UNO_QUERY_THROW
);
566 m_xHandler
->handle( xRequest
);
571 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > conts(
572 xRequest
->getContinuations() );
573 uno::Reference
< task::XInteractionContinuation
> const * pConts
= conts
.getConstArray();
574 sal_Int32 len
= conts
.getLength();
575 for ( sal_Int32 pos
= 0; pos
< len
; ++pos
)
578 uno::Reference
< task::XInteractionApprove
> xInteractionApprove( pConts
[ pos
], uno::UNO_QUERY
);
579 if (xInteractionApprove
.is()) {
580 xInteractionApprove
->select();
581 // don't query again for ongoing continuations:
586 uno::Reference
< task::XInteractionAbort
> xInteractionAbort( pConts
[ pos
], uno::UNO_QUERY
);
587 if (xInteractionAbort
.is()) {
588 xInteractionAbort
->select();
589 // don't query again for ongoing continuations:
597 //------------------------------------------------------------------------------
599 //------------------------------------------------------------------------------
600 void ProgressCmdEnv::push( uno::Any
const & rStatus
)
601 throw( uno::RuntimeException
)
606 //------------------------------------------------------------------------------
607 void ProgressCmdEnv::update_( uno::Any
const & rStatus
)
608 throw( uno::RuntimeException
)
611 if ( rStatus
.hasValue() && !( rStatus
>>= text
) )
613 if ( rStatus
.getValueTypeClass() == uno::TypeClass_EXCEPTION
)
614 text
= static_cast< uno::Exception
const *>( rStatus
.getValue() )->Message
;
615 if ( text
.getLength() == 0 )
616 text
= ::comphelper::anyToString( rStatus
); // fallback
618 const ::vos::OGuard
aGuard( Application::GetSolarMutex() );
619 const ::std::auto_ptr
< ErrorBox
> aBox( new ErrorBox( m_pDialogHelper
? m_pDialogHelper
->getWindow() : NULL
, WB_OK
, text
) );
622 ++m_nCurrentProgress
;
626 //------------------------------------------------------------------------------
627 void ProgressCmdEnv::update( uno::Any
const & rStatus
)
628 throw( uno::RuntimeException
)
633 //------------------------------------------------------------------------------
634 void ProgressCmdEnv::pop()
635 throw( uno::RuntimeException
)
637 update_( uno::Any() ); // no message
640 //------------------------------------------------------------------------------
641 ExtensionCmdQueue::Thread::Thread( DialogHelper
*pDialogHelper
,
642 TheExtensionManager
*pManager
,
643 const uno::Reference
< uno::XComponentContext
> & rContext
) :
644 m_xContext( rContext
),
645 m_pDialogHelper( pDialogHelper
),
646 m_pManager( pManager
),
647 m_sEnablingPackages( DialogHelper::getResourceString( RID_STR_ENABLING_PACKAGES
) ),
648 m_sDisablingPackages( DialogHelper::getResourceString( RID_STR_DISABLING_PACKAGES
) ),
649 m_sAddingPackages( DialogHelper::getResourceString( RID_STR_ADDING_PACKAGES
) ),
650 m_sRemovingPackages( DialogHelper::getResourceString( RID_STR_REMOVING_PACKAGES
) ),
651 m_sDefaultCmd( DialogHelper::getResourceString( RID_STR_ADD_PACKAGES
) ),
653 m_bTerminated( false ),
657 OSL_ASSERT( pDialogHelper
);
660 //------------------------------------------------------------------------------
661 void ExtensionCmdQueue::Thread::addExtension( const uno::Reference
< deployment::XPackageManager
> &rPackageManager
,
662 const ::rtl::OUString
&rExtensionURL
,
663 const bool bWarnUser
)
665 ::osl::MutexGuard
aGuard( m_mutex
);
667 //If someone called stop then we do not add the extension -> game over!
671 if ( rExtensionURL
.getLength() )
673 TExtensionCmd
pEntry( new ExtensionCmd( ExtensionCmd::ADD
, rPackageManager
, rExtensionURL
, bWarnUser
) );
675 m_queue
.push( pEntry
);
681 //------------------------------------------------------------------------------
682 void ExtensionCmdQueue::Thread::removeExtension( const uno::Reference
< deployment::XPackageManager
> &rPackageManager
,
683 const uno::Reference
< deployment::XPackage
> &rPackage
)
685 ::osl::MutexGuard
aGuard( m_mutex
);
687 //If someone called stop then we do not remove the extension -> game over!
691 if ( rPackageManager
.is() && rPackage
.is() )
693 TExtensionCmd
pEntry( new ExtensionCmd( ExtensionCmd::REMOVE
, rPackageManager
, rPackage
) );
695 m_queue
.push( pEntry
);
701 //------------------------------------------------------------------------------
702 void ExtensionCmdQueue::Thread::enableExtension( const uno::Reference
< deployment::XPackage
> &rPackage
,
705 ::osl::MutexGuard
aGuard( m_mutex
);
707 //If someone called stop then we do not remove the extension -> game over!
713 TExtensionCmd
pEntry( new ExtensionCmd( bEnable
? ExtensionCmd::ENABLE
:
714 ExtensionCmd::DISABLE
,
716 m_queue
.push( pEntry
);
722 //------------------------------------------------------------------------------
723 void ExtensionCmdQueue::Thread::checkForUpdates( const std::vector
< TUpdateListEntry
> &vExtensionList
)
725 ::osl::MutexGuard
aGuard( m_mutex
);
727 //If someone called stop then we do not update the extension -> game over!
731 TExtensionCmd
pEntry( new ExtensionCmd( ExtensionCmd::CHECK_FOR_UPDATES
, vExtensionList
) );
732 m_queue
.push( pEntry
);
737 //------------------------------------------------------------------------------
738 //Stopping this thread will not abort the installation of extensions.
739 void ExtensionCmdQueue::Thread::stop()
741 osl::MutexGuard
aGuard( m_mutex
);
747 //------------------------------------------------------------------------------
748 bool ExtensionCmdQueue::Thread::hasTerminated()
750 osl::MutexGuard
aGuard( m_mutex
);
751 return m_bTerminated
;
754 //------------------------------------------------------------------------------
755 bool ExtensionCmdQueue::Thread::isBusy()
757 osl::MutexGuard
aGuard( m_mutex
);
761 //------------------------------------------------------------------------------
762 ExtensionCmdQueue::Thread::~Thread() {}
764 //------------------------------------------------------------------------------
765 void ExtensionCmdQueue::Thread::execute()
768 //Needed for use of the service "com.sun.star.system.SystemShellExecute" in
769 //DialogHelper::openWebBrowser
771 HRESULT r
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
775 if ( m_wakeup
.wait() != osl::Condition::result_ok
)
777 dp_misc::TRACE( "dp_gui::ExtensionCmdQueue::Thread::run: ignored "
778 "osl::Condition::wait failure\n" );
785 osl::MutexGuard
aGuard( m_mutex
);
788 nSize
= m_queue
.size();
792 // If this thread has been woken up by anything else except start, stop
793 // then input is NONE and we wait again.
794 // We only install the extension which are currently in the queue.
795 // The progressbar will be set to show the progress of the current number
796 // of extensions. If we allowed to add extensions now then the progressbar may
797 // have reached the end while we still install newly added extensions.
798 if ( ( eInput
== NONE
) || ( nSize
== 0 ) )
800 if ( eInput
== STOP
)
803 ::rtl::Reference
< ProgressCmdEnv
> currentCmdEnv( new ProgressCmdEnv( m_xContext
, m_pDialogHelper
, m_sDefaultCmd
) );
805 // Do not lock the following part with addExtension. addExtension may be called in the main thread.
806 // If the message box "Do you want to install the extension (or similar)" is shown and then
807 // addExtension is called, which then blocks the main thread, then we deadlock.
808 bool bStartProgress
= true;
810 while ( !currentCmdEnv
->isAborted() && --nSize
>= 0 )
813 osl::MutexGuard
aGuard( m_mutex
);
819 TExtensionCmd pEntry
;
821 ::osl::MutexGuard
queueGuard( m_mutex
);
822 pEntry
= m_queue
.front();
826 if ( bStartProgress
&& ( pEntry
->m_eCmdType
!= ExtensionCmd::CHECK_FOR_UPDATES
) )
828 currentCmdEnv
->startProgress();
829 bStartProgress
= false;
832 switch ( pEntry
->m_eCmdType
) {
833 case ExtensionCmd::ADD
:
834 _addExtension( currentCmdEnv
, pEntry
->m_xPackageManager
, pEntry
->m_sExtensionURL
, pEntry
->m_bWarnUser
);
836 case ExtensionCmd::REMOVE
:
837 _removeExtension( currentCmdEnv
, pEntry
->m_xPackageManager
, pEntry
->m_xPackage
);
839 case ExtensionCmd::ENABLE
:
840 _enableExtension( currentCmdEnv
, pEntry
->m_xPackage
);
842 case ExtensionCmd::DISABLE
:
843 _disableExtension( currentCmdEnv
, pEntry
->m_xPackage
);
845 case ExtensionCmd::CHECK_FOR_UPDATES
:
846 _checkForUpdates( pEntry
->m_vExtensionList
);
850 //catch ( deployment::DeploymentException &)
853 //catch ( lang::IllegalArgumentException &)
856 catch ( ucb::CommandAbortedException
& )
858 //This exception is thrown when the user clicks cancel on the progressbar.
859 //Then we cancel the installation of all extensions and remove them from
862 ::osl::MutexGuard
queueGuard2(m_mutex
);
863 while ( --nSize
>= 0 )
868 catch ( ucb::CommandFailedException
& )
870 //This exception is thrown when a user clicked cancel in the messagebox which was
871 //startet by the interaction handler. For example the user will be asked if he/she
872 //really wants to install the extension.
873 //These interaction are run for exectly one extension at a time. Therefore we continue
874 //with installing the remaining extensions.
877 catch ( uno::Exception
& )
879 //Todo display the user an error
880 //see also DialogImpl::SyncPushButton::Click()
881 uno::Any
exc( ::cppu::getCaughtException() );
883 deployment::DeploymentException dpExc
;
884 if ((exc
>>= dpExc
) &&
885 dpExc
.Cause
.getValueTypeClass() == uno::TypeClass_EXCEPTION
)
887 // notify error cause only:
888 msg
= reinterpret_cast< uno::Exception
const * >( dpExc
.Cause
.getValue() )->Message
;
890 if (msg
.getLength() == 0) // fallback for debugging purposes
891 msg
= ::comphelper::anyToString(exc
);
893 const ::vos::OGuard
guard( Application::GetSolarMutex() );
894 ::std::auto_ptr
<ErrorBox
> box(
895 new ErrorBox( currentCmdEnv
->activeDialog(), WB_OK
, msg
) );
896 if ( m_pDialogHelper
)
897 box
->SetText( m_pDialogHelper
->getWindow()->GetText() );
899 //Continue with installation of the remaining extensions
902 osl::MutexGuard
aGuard( m_mutex
);
908 // when leaving the while loop with break, we should set working to false, too
909 osl::MutexGuard
aGuard( m_mutex
);
913 if ( !bStartProgress
)
914 currentCmdEnv
->stopProgress();
918 // m_pDialog->m_bAddingExtensions = false;
919 // m_pDialog->updateButtonStates();
925 //------------------------------------------------------------------------------
926 void ExtensionCmdQueue::Thread::_addExtension( ::rtl::Reference
< ProgressCmdEnv
> &rCmdEnv
,
927 const uno::Reference
< deployment::XPackageManager
> &xPackageManager
,
928 const OUString
&rPackageURL
,
929 const bool bWarnUser
)
931 //check if we have a string in anyTitle. For example "unopkg gui \" caused anyTitle to be void
932 //and anyTitle.get<OUString> throws as RuntimeException.
936 anyTitle
= ::ucbhelper::Content( rPackageURL
, rCmdEnv
.get() ).getPropertyValue( OUSTR("Title") );
938 catch ( uno::Exception
& )
944 if ( ! (anyTitle
>>= sName
) )
946 OSL_ENSURE(0, "Could not get file name for extension.");
950 rCmdEnv
->setWarnUser( bWarnUser
);
951 uno::Reference
< task::XAbortChannel
> xAbortChannel( xPackageManager
->createAbortChannel() );
952 OUString sTitle
= searchAndReplaceAll( m_sAddingPackages
, OUSTR("%EXTENSION_NAME"), sName
);
953 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
957 uno::Reference
< deployment::XPackage
> xPackage( xPackageManager
->addPackage(
958 rPackageURL
, OUString() /* detect media-type */,
959 xAbortChannel
, rCmdEnv
.get() ) );
960 OSL_ASSERT( xPackage
.is() );
962 catch ( ucb::CommandFailedException
& )
964 // When the extension is already installed we'll get a dialog asking if we want to overwrite. If we then press
965 // cancel this exception is thrown.
967 catch ( ucb::CommandAbortedException
& )
969 // User clicked the cancel button
970 // TODO: handle cancel
972 rCmdEnv
->setWarnUser( false );
975 //------------------------------------------------------------------------------
976 void ExtensionCmdQueue::Thread::_removeExtension( ::rtl::Reference
< ProgressCmdEnv
> &rCmdEnv
,
977 const uno::Reference
< deployment::XPackageManager
> &xPackageManager
,
978 const uno::Reference
< deployment::XPackage
> &xPackage
)
980 uno::Reference
< task::XAbortChannel
> xAbortChannel( xPackageManager
->createAbortChannel() );
981 OUString sTitle
= searchAndReplaceAll( m_sRemovingPackages
, OUSTR("%EXTENSION_NAME"), xPackage
->getDisplayName() );
982 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
984 OUString
id( dp_misc::getIdentifier( xPackage
) );
987 xPackageManager
->removePackage( id
, xPackage
->getName(), xAbortChannel
, rCmdEnv
.get() );
989 catch ( ucb::CommandAbortedException
& )
992 // Check, if there are still updates to be notified via menu bar icon
993 uno::Sequence
< uno::Sequence
< rtl::OUString
> > aItemList
;
994 UpdateDialog::createNotifyJob( false, aItemList
);
997 //------------------------------------------------------------------------------
998 void ExtensionCmdQueue::Thread::_checkForUpdates( const std::vector
< TUpdateListEntry
> &vExtensionList
)
1000 UpdateDialog
* pUpdateDialog
;
1001 std::vector
< UpdateData
> vData
;
1003 const ::vos::OGuard
guard( Application::GetSolarMutex() );
1005 pUpdateDialog
= new UpdateDialog( m_xContext
, m_pDialogHelper
? m_pDialogHelper
->getWindow() : NULL
, vExtensionList
, &vData
);
1007 pUpdateDialog
->notifyMenubar( true, false ); // prepare the checking, if there updates to be notified via menu bar icon
1009 if ( ( pUpdateDialog
->Execute() == RET_OK
) && !vData
.empty() )
1011 // If there is at least one directly downloadable dialog then we
1012 // open the install dialog.
1013 ::std::vector
< UpdateData
> dataDownload
;
1014 int countWebsiteDownload
= 0;
1015 typedef std::vector
< dp_gui::UpdateData
>::const_iterator cit
;
1017 for ( cit i
= vData
.begin(); i
< vData
.end(); i
++ )
1019 if ( i
->sWebsiteURL
.getLength() > 0 )
1020 countWebsiteDownload
++;
1022 dataDownload
.push_back( *i
);
1025 short nDialogResult
= RET_OK
;
1026 if ( !dataDownload
.empty() )
1028 nDialogResult
= UpdateInstallDialog( m_pDialogHelper
? m_pDialogHelper
->getWindow() : NULL
, dataDownload
, m_xContext
).Execute();
1029 pUpdateDialog
->notifyMenubar( false, true ); // Check, if there are still pending updates to be notified via menu bar icon
1032 pUpdateDialog
->notifyMenubar( false, false ); // Check, if there are pending updates to be notified via menu bar icon
1034 //Now start the webbrowser and navigate to the websites where we get the updates
1035 if ( RET_OK
== nDialogResult
)
1037 for ( cit i
= vData
.begin(); i
< vData
.end(); i
++ )
1039 if ( m_pDialogHelper
&& ( i
->sWebsiteURL
.getLength() > 0 ) )
1040 m_pDialogHelper
->openWebBrowser( i
->sWebsiteURL
, m_pDialogHelper
->getWindow()->GetText() );
1045 pUpdateDialog
->notifyMenubar( false, false ); // check if there updates to be notified via menu bar icon
1047 delete pUpdateDialog
;
1050 //------------------------------------------------------------------------------
1051 void ExtensionCmdQueue::Thread::_enableExtension( ::rtl::Reference
< ProgressCmdEnv
> &rCmdEnv
,
1052 const uno::Reference
< deployment::XPackage
> &xPackage
)
1054 if ( !xPackage
.is() )
1057 uno::Reference
< task::XAbortChannel
> xAbortChannel( xPackage
->createAbortChannel() );
1058 OUString sTitle
= searchAndReplaceAll( m_sEnablingPackages
, OUSTR("%EXTENSION_NAME"), xPackage
->getDisplayName() );
1059 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
1063 xPackage
->registerPackage( xAbortChannel
, rCmdEnv
.get() );
1064 if ( m_pDialogHelper
)
1065 m_pDialogHelper
->updatePackageInfo( xPackage
);
1067 catch ( ::ucb::CommandAbortedException
& )
1071 //------------------------------------------------------------------------------
1072 void ExtensionCmdQueue::Thread::_disableExtension( ::rtl::Reference
< ProgressCmdEnv
> &rCmdEnv
,
1073 const uno::Reference
< deployment::XPackage
> &xPackage
)
1075 if ( !xPackage
.is() )
1078 uno::Reference
< task::XAbortChannel
> xAbortChannel( xPackage
->createAbortChannel() );
1079 OUString sTitle
= searchAndReplaceAll( m_sDisablingPackages
, OUSTR("%EXTENSION_NAME"), xPackage
->getDisplayName() );
1080 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
1084 xPackage
->revokePackage( xAbortChannel
, rCmdEnv
.get() );
1085 if ( m_pDialogHelper
)
1086 m_pDialogHelper
->updatePackageInfo( xPackage
);
1088 catch ( ::ucb::CommandAbortedException
& )
1092 //------------------------------------------------------------------------------
1093 void ExtensionCmdQueue::Thread::onTerminated()
1095 ::osl::MutexGuard
g(m_mutex
);
1096 m_bTerminated
= true;
1099 //------------------------------------------------------------------------------
1100 OUString
ExtensionCmdQueue::Thread::searchAndReplaceAll( const OUString
&rSource
,
1101 const OUString
&rWhat
,
1102 const OUString
&rWith
)
1104 OUString
aRet( rSource
);
1105 sal_Int32 nLen
= rWhat
.getLength();
1110 sal_Int32 nIndex
= rSource
.indexOf( rWhat
);
1111 while ( nIndex
!= -1 )
1113 aRet
= aRet
.replaceAt( nIndex
, nLen
, rWith
);
1114 nIndex
= aRet
.indexOf( rWhat
, nIndex
+ rWith
.getLength() );
1120 //------------------------------------------------------------------------------
1121 //------------------------------------------------------------------------------
1122 //------------------------------------------------------------------------------
1123 ExtensionCmdQueue::ExtensionCmdQueue( DialogHelper
* pDialogHelper
,
1124 TheExtensionManager
*pManager
,
1125 const uno::Reference
< uno::XComponentContext
> &rContext
)
1126 : m_thread( new Thread( pDialogHelper
, pManager
, rContext
) )
1131 ExtensionCmdQueue::~ExtensionCmdQueue() {
1135 void ExtensionCmdQueue::addExtension( const uno::Reference
< deployment::XPackageManager
> &rPackageManager
,
1136 const ::rtl::OUString
& extensionURL
,
1137 const bool bWarnUser
)
1139 m_thread
->addExtension( rPackageManager
, extensionURL
, bWarnUser
);
1142 void ExtensionCmdQueue::removeExtension( const uno::Reference
< deployment::XPackageManager
> &rPackageManager
,
1143 const uno::Reference
< deployment::XPackage
> &rPackage
)
1145 m_thread
->removeExtension( rPackageManager
, rPackage
);
1148 void ExtensionCmdQueue::enableExtension( const uno::Reference
< deployment::XPackage
> &rPackage
,
1149 const bool bEnable
)
1151 m_thread
->enableExtension( rPackage
, bEnable
);
1154 void ExtensionCmdQueue::checkForUpdates( const std::vector
< TUpdateListEntry
> &vExtensionList
)
1156 m_thread
->checkForUpdates( vExtensionList
);
1159 void ExtensionCmdQueue::stop()
1164 void ExtensionCmdQueue::stopAndWait()
1170 bool ExtensionCmdQueue::hasTerminated()
1172 return m_thread
->hasTerminated();
1175 bool ExtensionCmdQueue::isBusy()
1177 return m_thread
->isBusy();
1180 void handleInteractionRequest( const uno::Reference
< uno::XComponentContext
> & xContext
,
1181 const uno::Reference
< task::XInteractionRequest
> & xRequest
)
1183 ::rtl::Reference
< ProgressCmdEnv
> xCmdEnv( new ProgressCmdEnv( xContext
, NULL
, OUSTR("Extension Manager") ) );
1184 xCmdEnv
->handle( xRequest
);
1187 } //namespace dp_gui