| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_desktop.hxx" |
| |
| #include "vcl/svapp.hxx" |
| #include "vcl/msgbox.hxx" |
| |
| #include "vos/mutex.hxx" |
| |
| #include "toolkit/helper/vclunohelper.hxx" |
| |
| #include "com/sun/star/beans/XPropertySet.hpp" |
| |
| #include "dp_gui_dialog2.hxx" |
| #include "dp_gui_extensioncmdqueue.hxx" |
| #include "dp_gui_theextmgr.hxx" |
| #include "dp_gui_theextmgr.hxx" |
| #include "dp_identifier.hxx" |
| #include "dp_update.hxx" |
| |
| #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) |
| |
| #define USER_PACKAGE_MANAGER OUSTR("user") |
| #define SHARED_PACKAGE_MANAGER OUSTR("shared") |
| #define BUNDLED_PACKAGE_MANAGER OUSTR("bundled") |
| |
| using namespace ::com::sun::star; |
| using ::rtl::OUString; |
| |
| namespace dp_gui { |
| |
| //------------------------------------------------------------------------------ |
| |
| ::rtl::Reference< TheExtensionManager > TheExtensionManager::s_ExtMgr; |
| |
| //------------------------------------------------------------------------------ |
| // TheExtensionManager |
| //------------------------------------------------------------------------------ |
| |
| TheExtensionManager::TheExtensionManager( Window *pParent, |
| const uno::Reference< uno::XComponentContext > &xContext ) : |
| m_xContext( xContext ), |
| m_pParent( pParent ), |
| m_pExtMgrDialog( NULL ), |
| m_pUpdReqDialog( NULL ), |
| m_pExecuteCmdQueue( NULL ) |
| { |
| m_xExtensionManager = deployment::ExtensionManager::get( xContext ); |
| m_xExtensionManager->addModifyListener( this ); |
| |
| uno::Reference< lang::XMultiServiceFactory > xConfig( |
| xContext->getServiceManager()->createInstanceWithContext( |
| OUSTR("com.sun.star.configuration.ConfigurationProvider"), xContext ), uno::UNO_QUERY_THROW); |
| uno::Any args[1]; |
| beans::PropertyValue aValue( OUSTR("nodepath"), 0, uno::Any( OUSTR("/org.openoffice.Office.OptionsDialog/Nodes") ), |
| beans::PropertyState_DIRECT_VALUE ); |
| args[0] <<= aValue; |
| m_xNameAccessNodes = uno::Reference< container::XNameAccess >( |
| xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"), |
| uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW); |
| |
| // get the 'get more extensions here' url |
| uno::Reference< container::XNameAccess > xNameAccessRepositories; |
| beans::PropertyValue aValue2( OUSTR("nodepath"), 0, uno::Any( OUSTR("/org.openoffice.Office.ExtensionManager/ExtensionRepositories") ), |
| beans::PropertyState_DIRECT_VALUE ); |
| args[0] <<= aValue2; |
| xNameAccessRepositories = uno::Reference< container::XNameAccess > ( |
| xConfig->createInstanceWithArguments( OUSTR("com.sun.star.configuration.ConfigurationAccess"), |
| uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW); |
| try |
| { //throws css::container::NoSuchElementException, css::lang::WrappedTargetException |
| uno::Any value = xNameAccessRepositories->getByName( OUSTR( "WebsiteLink" ) ); |
| m_sGetExtensionsURL = value.get< OUString > (); |
| } |
| catch ( uno::Exception& ) |
| {} |
| |
| if ( dp_misc::office_is_running() ) |
| { |
| // the registration should be done after the construction has been ended |
| // otherwise an exception prevents object creation, but it is registered as a listener |
| m_xDesktop.set( xContext->getServiceManager()->createInstanceWithContext( |
| OUSTR("com.sun.star.frame.Desktop"), xContext ), uno::UNO_QUERY ); |
| if ( m_xDesktop.is() ) |
| m_xDesktop->addTerminateListener( this ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| TheExtensionManager::~TheExtensionManager() |
| { |
| if ( m_pUpdReqDialog ) |
| delete m_pUpdReqDialog; |
| if ( m_pExtMgrDialog ) |
| delete m_pExtMgrDialog; |
| if ( m_pExecuteCmdQueue ) |
| delete m_pExecuteCmdQueue; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void TheExtensionManager::createDialog( const bool bCreateUpdDlg ) |
| { |
| const ::vos::OGuard guard( Application::GetSolarMutex() ); |
| |
| if ( bCreateUpdDlg ) |
| { |
| if ( !m_pUpdReqDialog ) |
| { |
| m_pUpdReqDialog = new UpdateRequiredDialog( NULL, this ); |
| delete m_pExecuteCmdQueue; |
| m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pUpdReqDialog, this, m_xContext ); |
| createPackageList(); |
| } |
| } |
| else if ( !m_pExtMgrDialog ) |
| { |
| m_pExtMgrDialog = new ExtMgrDialog( m_pParent, this ); |
| delete m_pExecuteCmdQueue; |
| m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pExtMgrDialog, this, m_xContext ); |
| m_pExtMgrDialog->setGetExtensionsURL( m_sGetExtensionsURL ); |
| createPackageList(); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void TheExtensionManager::Show() |
| { |
| const ::vos::OGuard guard( Application::GetSolarMutex() ); |
| |
| getDialog()->Show(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void TheExtensionManager::SetText( const ::rtl::OUString &rTitle ) |
| { |
| const ::vos::OGuard guard( Application::GetSolarMutex() ); |
| |
| getDialog()->SetText( rTitle ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| void TheExtensionManager::ToTop( sal_uInt16 nFlags ) |
| { |
| const ::vos::OGuard guard( Application::GetSolarMutex() ); |
| |
| getDialog()->ToTop( nFlags ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool TheExtensionManager::Close() |
| { |
| if ( m_pExtMgrDialog ) |
| return m_pExtMgrDialog->Close(); |
| else if ( m_pUpdReqDialog ) |
| return m_pUpdReqDialog->Close(); |
| else |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| sal_Int16 TheExtensionManager::execute() |
| { |
| sal_Int16 nRet = 0; |
| |
| if ( m_pUpdReqDialog ) |
| { |
| nRet = m_pUpdReqDialog->Execute(); |
| delete m_pUpdReqDialog; |
| m_pUpdReqDialog = NULL; |
| } |
| |
| return nRet; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool TheExtensionManager::isVisible() |
| { |
| return getDialog()->IsVisible(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool TheExtensionManager::checkUpdates( bool /* bShowUpdateOnly */, bool /*bParentVisible*/ ) |
| { |
| std::vector< uno::Reference< deployment::XPackage > > vEntries; |
| uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; |
| |
| try { |
| xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(), |
| uno::Reference< ucb::XCommandEnvironment >() ); |
| } catch ( deployment::DeploymentException & ) { |
| return false; |
| } catch ( ucb::CommandFailedException & ) { |
| return false; |
| } catch ( ucb::CommandAbortedException & ) { |
| return false; |
| } catch ( lang::IllegalArgumentException & e ) { |
| throw uno::RuntimeException( e.Message, e.Context ); |
| } |
| |
| for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) |
| { |
| uno::Reference< deployment::XPackage > xPackage = dp_misc::getExtensionWithHighestVersion(xAllPackages[i]); |
| OSL_ASSERT(xPackage.is()); |
| if ( xPackage.is() ) |
| { |
| vEntries.push_back( xPackage ); |
| } |
| } |
| |
| m_pExecuteCmdQueue->checkForUpdates( vEntries ); |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool TheExtensionManager::installPackage( const OUString &rPackageURL, bool bWarnUser ) |
| { |
| if ( rPackageURL.getLength() == 0 ) |
| return false; |
| |
| createDialog( false ); |
| |
| bool bInstall = true; |
| bool bInstallForAll = false; |
| |
| // DV! missing function is read only repository from extension manager |
| if ( !bWarnUser && ! m_xExtensionManager->isReadOnlyRepository( SHARED_PACKAGE_MANAGER ) ) |
| bInstall = getDialogHelper()->installForAllUsers( bInstallForAll ); |
| |
| if ( !bInstall ) |
| return false; |
| |
| if ( bInstallForAll ) |
| m_pExecuteCmdQueue->addExtension( rPackageURL, SHARED_PACKAGE_MANAGER, false ); |
| else |
| m_pExecuteCmdQueue->addExtension( rPackageURL, USER_PACKAGE_MANAGER, bWarnUser ); |
| |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool TheExtensionManager::queryTermination() |
| { |
| if ( dp_misc::office_is_running() ) |
| return true; |
| // the standalone application unopkg must not close ( and quit ) the dialog |
| // when there are still actions in the queue |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void TheExtensionManager::terminateDialog() |
| { |
| if ( ! dp_misc::office_is_running() ) |
| { |
| const ::vos::OGuard guard( Application::GetSolarMutex() ); |
| delete m_pExtMgrDialog; |
| m_pExtMgrDialog = NULL; |
| delete m_pUpdReqDialog; |
| m_pUpdReqDialog = NULL; |
| Application::Quit(); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void TheExtensionManager::createPackageList() |
| { |
| uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; |
| |
| try { |
| xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(), |
| uno::Reference< ucb::XCommandEnvironment >() ); |
| } catch ( deployment::DeploymentException & ) { |
| return; |
| } catch ( ucb::CommandFailedException & ) { |
| return; |
| } catch ( ucb::CommandAbortedException & ) { |
| return; |
| } catch ( lang::IllegalArgumentException & e ) { |
| throw uno::RuntimeException( e.Message, e.Context ); |
| } |
| |
| for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) |
| { |
| uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i]; |
| |
| for ( sal_Int32 j = 0; j < xPackageList.getLength(); ++j ) |
| { |
| uno::Reference< deployment::XPackage > xPackage = xPackageList[j]; |
| if ( xPackage.is() ) |
| { |
| PackageState eState = getPackageState( xPackage ); |
| getDialogHelper()->addPackageToList( xPackage ); |
| // When the package is enabled, we can stop here, otherwise we have to look for |
| // another version of this package |
| if ( ( eState == REGISTERED ) || ( eState == NOT_AVAILABLE ) ) |
| break; |
| } |
| } |
| } |
| |
| uno::Sequence< uno::Reference< deployment::XPackage > > xNoLicPackages; |
| xNoLicPackages = m_xExtensionManager->getExtensionsWithUnacceptedLicenses( SHARED_PACKAGE_MANAGER, |
| uno::Reference< ucb::XCommandEnvironment >() ); |
| for ( sal_Int32 i = 0; i < xNoLicPackages.getLength(); ++i ) |
| { |
| uno::Reference< deployment::XPackage > xPackage = xNoLicPackages[i]; |
| if ( xPackage.is() ) |
| { |
| getDialogHelper()->addPackageToList( xPackage, true ); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| PackageState TheExtensionManager::getPackageState( const uno::Reference< deployment::XPackage > &xPackage ) const |
| { |
| try { |
| beans::Optional< beans::Ambiguous< sal_Bool > > option( |
| xPackage->isRegistered( uno::Reference< task::XAbortChannel >(), |
| uno::Reference< ucb::XCommandEnvironment >() ) ); |
| if ( option.IsPresent ) |
| { |
| ::beans::Ambiguous< sal_Bool > const & reg = option.Value; |
| if ( reg.IsAmbiguous ) |
| return AMBIGUOUS; |
| else |
| return reg.Value ? REGISTERED : NOT_REGISTERED; |
| } |
| else |
| return NOT_AVAILABLE; |
| } |
| catch ( uno::RuntimeException & ) { |
| throw; |
| } |
| catch ( uno::Exception & exc) { |
| (void) exc; |
| OSL_ENSURE( 0, ::rtl::OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| return NOT_AVAILABLE; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| bool TheExtensionManager::isReadOnly( const uno::Reference< deployment::XPackage > &xPackage ) const |
| { |
| if ( m_xExtensionManager.is() && xPackage.is() ) |
| { |
| return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() ); |
| } |
| else |
| return true; |
| } |
| |
| //------------------------------------------------------------------------------ |
| // The function investigates if the extension supports options. |
| bool TheExtensionManager::supportsOptions( const uno::Reference< deployment::XPackage > &xPackage ) const |
| { |
| bool bOptions = false; |
| |
| if ( ! xPackage->isBundle() ) |
| return false; |
| |
| beans::Optional< OUString > aId = xPackage->getIdentifier(); |
| |
| //a bundle must always have an id |
| OSL_ASSERT( aId.IsPresent ); |
| |
| //iterate over all available nodes |
| uno::Sequence< OUString > seqNames = m_xNameAccessNodes->getElementNames(); |
| |
| for ( int i = 0; i < seqNames.getLength(); i++ ) |
| { |
| uno::Any anyNode = m_xNameAccessNodes->getByName( seqNames[i] ); |
| //If we have a node then then it must contain the set of leaves. This is part of OptionsDialog.xcs |
| uno::Reference< XInterface> xIntNode = anyNode.get< uno::Reference< XInterface > >(); |
| uno::Reference< container::XNameAccess > xNode( xIntNode, uno::UNO_QUERY_THROW ); |
| |
| uno::Any anyLeaves = xNode->getByName( OUSTR("Leaves") ); |
| uno::Reference< XInterface > xIntLeaves = anyLeaves.get< uno::Reference< XInterface > >(); |
| uno::Reference< container::XNameAccess > xLeaves( xIntLeaves, uno::UNO_QUERY_THROW ); |
| |
| //iterate over all available leaves |
| uno::Sequence< OUString > seqLeafNames = xLeaves->getElementNames(); |
| for ( int j = 0; j < seqLeafNames.getLength(); j++ ) |
| { |
| uno::Any anyLeaf = xLeaves->getByName( seqLeafNames[j] ); |
| uno::Reference< XInterface > xIntLeaf = anyLeaf.get< uno::Reference< XInterface > >(); |
| uno::Reference< beans::XPropertySet > xLeaf( xIntLeaf, uno::UNO_QUERY_THROW ); |
| //investigate the Id property if it matches the extension identifier which |
| //has been passed in. |
| uno::Any anyValue = xLeaf->getPropertyValue( OUSTR("Id") ); |
| |
| OUString sId = anyValue.get< OUString >(); |
| if ( sId == aId.Value ) |
| { |
| bOptions = true; |
| break; |
| } |
| } |
| if ( bOptions ) |
| break; |
| } |
| return bOptions; |
| } |
| |
| //------------------------------------------------------------------------------ |
| // XEventListener |
| void TheExtensionManager::disposing( lang::EventObject const & rEvt ) |
| throw ( uno::RuntimeException ) |
| { |
| bool shutDown = (rEvt.Source == m_xDesktop); |
| |
| if ( shutDown && m_xDesktop.is() ) |
| { |
| m_xDesktop->removeTerminateListener( this ); |
| m_xDesktop.clear(); |
| } |
| |
| if ( shutDown ) |
| { |
| if ( dp_misc::office_is_running() ) |
| { |
| const ::vos::OGuard guard( Application::GetSolarMutex() ); |
| delete m_pExtMgrDialog; |
| m_pExtMgrDialog = NULL; |
| delete m_pUpdReqDialog; |
| m_pUpdReqDialog = NULL; |
| } |
| s_ExtMgr.clear(); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| // XTerminateListener |
| void TheExtensionManager::queryTermination( ::lang::EventObject const & ) |
| throw ( frame::TerminationVetoException, uno::RuntimeException ) |
| { |
| DialogHelper *pDialogHelper = getDialogHelper(); |
| |
| if ( m_pExecuteCmdQueue->isBusy() || ( pDialogHelper && pDialogHelper->isBusy() ) ) |
| { |
| ToTop( TOTOP_RESTOREWHENMIN ); |
| throw frame::TerminationVetoException( |
| OUSTR("The office cannot be closed while the Extension Manager is running"), |
| uno::Reference<XInterface>(static_cast<frame::XTerminateListener*>(this), uno::UNO_QUERY)); |
| } |
| else |
| { |
| if ( m_pExtMgrDialog ) |
| m_pExtMgrDialog->Close(); |
| if ( m_pUpdReqDialog ) |
| m_pUpdReqDialog->Close(); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| void TheExtensionManager::notifyTermination( ::lang::EventObject const & rEvt ) |
| throw ( uno::RuntimeException ) |
| { |
| disposing( rEvt ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| // XModifyListener |
| void TheExtensionManager::modified( ::lang::EventObject const & /*rEvt*/ ) |
| throw ( uno::RuntimeException ) |
| { |
| getDialogHelper()->prepareChecking(); |
| createPackageList(); |
| getDialogHelper()->checkEntries(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| ::rtl::Reference< TheExtensionManager > TheExtensionManager::get( const uno::Reference< uno::XComponentContext > &xContext, |
| const uno::Reference< awt::XWindow > &xParent, |
| const OUString & extensionURL ) |
| { |
| if ( s_ExtMgr.is() ) |
| { |
| OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); |
| if ( extensionURL.getLength() ) |
| s_ExtMgr->installPackage( extensionURL, true ); |
| return s_ExtMgr; |
| } |
| |
| Window * pParent = DIALOG_NO_PARENT; |
| if ( xParent.is() ) |
| pParent = VCLUnoHelper::GetWindow(xParent); |
| |
| ::rtl::Reference<TheExtensionManager> that( new TheExtensionManager( pParent, xContext ) ); |
| |
| const ::vos::OGuard guard( Application::GetSolarMutex() ); |
| if ( ! s_ExtMgr.is() ) |
| { |
| OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); |
| s_ExtMgr = that; |
| } |
| |
| if ( extensionURL.getLength() ) |
| s_ExtMgr->installPackage( extensionURL, true ); |
| |
| return s_ExtMgr; |
| } |
| |
| } //namespace dp_gui |
| |