diff options
author | Joachim Lingner <jl@openoffice.org> | 2010-05-28 17:50:38 +0200 |
---|---|---|
committer | Joachim Lingner <jl@openoffice.org> | 2010-05-28 17:50:38 +0200 |
commit | 776d5631f5089f94cbe87b6f869f7887aeff2092 (patch) | |
tree | d65da9c50c2b4a14c6c28c12b6186502a5fd7343 | |
parent | 3d3b46bb623c859265d2b95068845b18a1b64716 (diff) |
jl152 #i77196# new update behavior for extensions
16 files changed, 635 insertions, 209 deletions
diff --git a/desktop/source/deployment/gui/dp_gui_dialog2.cxx b/desktop/source/deployment/gui/dp_gui_dialog2.cxx index 086e39e5f18c..35634d5ef851 100644 --- a/desktop/source/deployment/gui/dp_gui_dialog2.cxx +++ b/desktop/source/deployment/gui/dp_gui_dialog2.cxx @@ -38,6 +38,7 @@ #include "dp_gui_shared.hxx" #include "dp_gui_theextmgr.hxx" #include "dp_misc.h" +#include "dp_identifier.hxx" #include "vcl/ctrl.hxx" #include "vcl/menu.hxx" @@ -106,15 +107,6 @@ struct StrAllFiles : public rtl::StaticWithInit< const OUString, StrAllFiles > }; //------------------------------------------------------------------------------ -UpdateListEntry::UpdateListEntry( const uno::Reference< deployment::XPackage > &xPackage ) : - m_xPackage( xPackage ) -{} - -//------------------------------------------------------------------------------ -UpdateListEntry::~UpdateListEntry() -{} - -//------------------------------------------------------------------------------ // ExtBoxWithBtns_Impl //------------------------------------------------------------------------------ @@ -849,9 +841,15 @@ bool ExtMgrDialog::updatePackage( const uno::Reference< deployment::XPackage > & if ( !xPackage.is() ) return false; - std::vector< TUpdateListEntry > vEntries; - TUpdateListEntry pEntry( new UpdateListEntry( xPackage ) ); - vEntries.push_back( pEntry ); + // get the extension with highest version + uno::Sequence<uno::Reference<deployment::XPackage> > seqExtensions = + m_pManager->getExtensionManager()->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(xPackage), xPackage->getName(), uno::Reference<ucb::XCommandEnvironment>()); + uno::Reference<deployment::XPackage> extension = + dp_misc::getExtensionWithHighestVersion(seqExtensions); + OSL_ASSERT(extension.is()); + std::vector< css::uno::Reference< css::deployment::XPackage > > vEntries; + vEntries.push_back(extension); m_pManager->updatePackages( vEntries ); @@ -1453,14 +1451,13 @@ IMPL_LINK( UpdateRequiredDialog, HandleUpdateBtn, void*, EMPTYARG ) { ::osl::ClearableMutexGuard aGuard( m_aMutex ); - std::vector< TUpdateListEntry > vUpdateEntries; + std::vector< uno::Reference< deployment::XPackage > > vUpdateEntries; sal_Int32 nCount = m_pExtensionBox->GetEntryCount(); for ( sal_Int32 i = 0; i < nCount; ++i ) { TEntry_Impl pEntry = m_pExtensionBox->GetEntryData( i ); - TUpdateListEntry pUpdateEntry( new UpdateListEntry( pEntry->m_xPackage ) ); - vUpdateEntries.push_back( pUpdateEntry ); + vUpdateEntries.push_back( pEntry->m_xPackage ); } aGuard.clear(); diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx index 8d82d969c4a0..954f32f4c9c6 100644 --- a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.cxx @@ -202,7 +202,7 @@ struct ExtensionCmd OUString m_sExtensionURL; OUString m_sRepository; uno::Reference< deployment::XPackage > m_xPackage; - std::vector< TUpdateListEntry > m_vExtensionList; + std::vector< uno::Reference< deployment::XPackage > > m_vExtensionList; ExtensionCmd( const E_CMD_TYPE eCommand, const OUString &rExtensionURL, @@ -218,7 +218,7 @@ struct ExtensionCmd m_bWarnUser( false ), m_xPackage( rPackage ) {}; ExtensionCmd( const E_CMD_TYPE eCommand, - const std::vector< TUpdateListEntry > &vExtensionList ) + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) : m_eCmdType( eCommand ), m_bWarnUser( false ), m_vExtensionList( vExtensionList ) {}; @@ -240,7 +240,7 @@ public: void removeExtension( const uno::Reference< deployment::XPackage > &rPackage ); void enableExtension( const uno::Reference< deployment::XPackage > &rPackage, const bool bEnable ); - void checkForUpdates( const std::vector< TUpdateListEntry > &vExtensionList ); + void checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ); void stop(); bool isBusy(); @@ -266,7 +266,7 @@ private: const uno::Reference< deployment::XPackage > &xPackage ); void _disableExtension( ::rtl::Reference< ProgressCmdEnv > &rCmdEnv, const uno::Reference< deployment::XPackage > &xPackage ); - void _checkForUpdates( const std::vector< TUpdateListEntry > &vExtensionList ); + void _checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ); enum Input { NONE, START, STOP }; @@ -696,7 +696,8 @@ void ExtensionCmdQueue::Thread::enableExtension( const uno::Reference< deploymen } //------------------------------------------------------------------------------ -void ExtensionCmdQueue::Thread::checkForUpdates( const std::vector< TUpdateListEntry > &vExtensionList ) +void ExtensionCmdQueue::Thread::checkForUpdates( + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) { ::osl::MutexGuard aGuard( m_mutex ); @@ -924,10 +925,8 @@ void ExtensionCmdQueue::Thread::_addExtension( ::rtl::Reference< ProgressCmdEnv try { - uno::Reference< deployment::XPackage > xPackage( - xExtMgr->addExtension(rPackageURL, uno::Sequence<beans::NamedValue>(), - rRepository, xAbortChannel, rCmdEnv.get() ) ); - OSL_ASSERT( xPackage.is() ); + xExtMgr->addExtension(rPackageURL, uno::Sequence<beans::NamedValue>(), + rRepository, xAbortChannel, rCmdEnv.get() ); } catch ( ucb::CommandFailedException & ) { @@ -969,7 +968,8 @@ void ExtensionCmdQueue::Thread::_removeExtension( ::rtl::Reference< ProgressCmdE } //------------------------------------------------------------------------------ -void ExtensionCmdQueue::Thread::_checkForUpdates( const std::vector< TUpdateListEntry > &vExtensionList ) +void ExtensionCmdQueue::Thread::_checkForUpdates( + const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) { UpdateDialog* pUpdateDialog; std::vector< UpdateData > vData; @@ -1126,7 +1126,7 @@ void ExtensionCmdQueue::enableExtension( const uno::Reference< deployment::XPack m_thread->enableExtension( rPackage, bEnable ); } -void ExtensionCmdQueue::checkForUpdates( const std::vector< TUpdateListEntry > &vExtensionList ) +void ExtensionCmdQueue::checkForUpdates( const std::vector<uno::Reference<deployment::XPackage > > &vExtensionList ) { m_thread->checkForUpdates( vExtensionList ); } diff --git a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx index 69ad7da24769..cfadad84cedc 100644 --- a/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx +++ b/desktop/source/deployment/gui/dp_gui_extensioncmdqueue.hxx @@ -83,7 +83,8 @@ public: void removeExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &rPackage ); void enableExtension( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &rPackage, const bool bEnable ); - void checkForUpdates( const std::vector< TUpdateListEntry > &vList ); + void checkForUpdates(const std::vector< ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage > > &vList ); /** This call does not block. It signals the internal thread that it should install the remaining extensions and then terminate. diff --git a/desktop/source/deployment/gui/dp_gui_theextmgr.cxx b/desktop/source/deployment/gui/dp_gui_theextmgr.cxx index 7c81517bbbfa..fdbc1974f61c 100644 --- a/desktop/source/deployment/gui/dp_gui_theextmgr.cxx +++ b/desktop/source/deployment/gui/dp_gui_theextmgr.cxx @@ -201,7 +201,7 @@ bool TheExtensionManager::isVisible() //------------------------------------------------------------------------------ bool TheExtensionManager::checkUpdates( bool /* bShowUpdateOnly */, bool /*bParentVisible*/ ) { - std::vector< TUpdateListEntry > vEntries; + std::vector< uno::Reference< deployment::XPackage > > vEntries; uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages; try { @@ -219,17 +219,11 @@ bool TheExtensionManager::checkUpdates( bool /* bShowUpdateOnly */, bool /*bPare for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i ) { - uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i]; - - // we don't want update notifications for bundled packages - for ( sal_Int32 j = 0; ( j < 2 ) && ( j < xPackageList.getLength() ); ++j ) + uno::Reference< deployment::XPackage > xPackage = dp_misc::getExtensionWithHighestVersion(xAllPackages[i]); + OSL_ASSERT(xPackage.is()); + if ( xPackage.is() ) { - uno::Reference< deployment::XPackage > xPackage = xPackageList[j]; - if ( xPackage.is() ) - { - TUpdateListEntry pEntry( new UpdateListEntry( xPackage ) ); - vEntries.push_back( pEntry ); - } + vEntries.push_back( xPackage ); } } @@ -255,7 +249,8 @@ bool TheExtensionManager::removePackage( const uno::Reference< deployment::XPack } //------------------------------------------------------------------------------ -bool TheExtensionManager::updatePackages( const std::vector< TUpdateListEntry > &vList ) +bool TheExtensionManager::updatePackages( + const std::vector< uno::Reference< deployment::XPackage > > &vList ) { m_pExecuteCmdQueue->checkForUpdates( vList ); diff --git a/desktop/source/deployment/gui/dp_gui_theextmgr.hxx b/desktop/source/deployment/gui/dp_gui_theextmgr.hxx index 02e3aad56915..da8d3c083f42 100644 --- a/desktop/source/deployment/gui/dp_gui_theextmgr.hxx +++ b/desktop/source/deployment/gui/dp_gui_theextmgr.hxx @@ -92,7 +92,8 @@ public: //----------------- bool checkUpdates( bool showUpdateOnly, bool parentVisible ); - bool updatePackages( const std::vector< TUpdateListEntry > &vList ); + bool updatePackages( const std::vector< ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage > > &vList ); bool enablePackage( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage, bool bEnable ); diff --git a/desktop/source/deployment/gui/dp_gui_updatedata.hxx b/desktop/source/deployment/gui/dp_gui_updatedata.hxx index 2082b92e923a..7228982da518 100644 --- a/desktop/source/deployment/gui/dp_gui_updatedata.hxx +++ b/desktop/source/deployment/gui/dp_gui_updatedata.hxx @@ -44,27 +44,42 @@ namespace com { namespace sun { namespace star { namespace xml { namespace dom { namespace dp_gui { -struct UpdateListEntry +struct UpdateData { - ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> m_xPackage; + UpdateData( ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > const & aExt): + aInstalledPackage(aExt), bIsShared(false) {}; - UpdateListEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > &xPackage ); - ~UpdateListEntry(); -}; + //When entries added to the listbox then there can be one for the user update and one + //for the shared update. However, both list entries will contain the same UpdateData. + //isShared is used to indicate which one is used for the shared entry. + bool bIsShared; -typedef ::boost::shared_ptr< UpdateListEntry > TUpdateListEntry; + //The currently installed extension which is going to be updated. If the extension exist in + //multiple repositories then it is the one with the highest version. + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > aInstalledPackage; + //The version of the update + ::rtl::OUString updateVersion; -struct UpdateData -{ - ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > aInstalledPackage; - // The content of the update information + //For online update + // ====================== + // The content of the update information. + //Only if aUpdateInfo is set then there is an online update available with a better version + //than any of the currently installed extensions with the same identifier. ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > aUpdateInfo; //The URL of the locally downloaded extension. It will only be set if there were no errors //during the download ::rtl::OUString sLocalURL; //The URL of the website wher the download can be obtained. ::rtl::OUString sWebsiteURL; + + //For local update + //===================== + //The locale extension which is used as update for the user or shared repository. + //If set then the data for the online update (aUpdateInfo, sLocalURL, sWebsiteURL) + //are to be ignored. + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > + aUpdateSource; }; } diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx index fca7d97c798a..d121ad976a06 100644 --- a/desktop/source/deployment/gui/dp_gui_updatedialog.cxx +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.cxx @@ -151,7 +151,6 @@ rtl::OUString confineToParagraph(rtl::OUString const & text) { struct UpdateDialog::DisabledUpdate { rtl::OUString name; css::uno::Sequence< rtl::OUString > unsatisfiedDependencies; - bool permission; // We also want to show release notes and publisher for disabled updates ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > aUpdateInfo; }; @@ -230,7 +229,7 @@ public: Thread( css::uno::Reference< css::uno::XComponentContext > const & context, UpdateDialog & dialog, - const std::vector< TUpdateListEntry > &vExtensionList); + const std::vector< css::uno::Reference< css::deployment::XPackage > > & vExtensionList); void stop(); @@ -245,10 +244,16 @@ private: css::uno::Reference< css::deployment::XPackage > package; rtl::OUString version; + //Indicates that the extension provides its own update URLs. + //If this is true, then we must not use the default update + //URL to find the update information. + bool bProvidesOwnUpdate; css::uno::Reference< css::xml::dom::XNode > info; + UpdateDialog::DisabledUpdate disableUpdate; + dp_gui::UpdateData updateData; }; - // A multimap in case an extension is installed in both "user" and "shared": + // A multimap in case an extension is installed in "user", "shared" or "bundled" typedef std::multimap< rtl::OUString, Entry > Map; virtual ~Thread(); @@ -267,17 +272,26 @@ private: css::uno::Sequence< rtl::OUString > const & urls, rtl::OUString const & identifier) const; - void handle( + void getOwnUpdateInformation( css::uno::Reference< css::deployment::XPackage > const & package, Map * map); + ::rtl::OUString getUpdateDisplayString( + dp_gui::UpdateData const & data, ::rtl::OUString const & version = ::rtl::OUString()) const; + + void prepareUpdateData( + ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage > const & package, + ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & updateInfo, + UpdateDialog::DisabledUpdate & out_du, + dp_gui::UpdateData & out_data) const; + bool update( - css::uno::Reference< css::deployment::XPackage > const & package, - css::uno::Reference< css::xml::dom::XNode > const & updateInfo) const; + UpdateDialog::DisabledUpdate const & du, + dp_gui::UpdateData const & data) const; css::uno::Reference< css::uno::XComponentContext > m_context; UpdateDialog & m_dialog; - std::vector< dp_gui::TUpdateListEntry > m_vExtensionList; + std::vector< css::uno::Reference< css::deployment::XPackage > > m_vExtensionList; css::uno::Reference< css::deployment::XUpdateInformationProvider > m_updateInformation; css::uno::Reference< css::task::XInteractionHandler > m_xInteractionHdl; @@ -289,7 +303,7 @@ private: UpdateDialog::Thread::Thread( css::uno::Reference< css::uno::XComponentContext > const & context, UpdateDialog & dialog, - const std::vector< dp_gui::TUpdateListEntry > &vExtensionList): + const std::vector< css::uno::Reference< css::deployment::XPackage > > &vExtensionList): m_context(context), m_dialog(dialog), m_vExtensionList(vExtensionList), @@ -328,9 +342,13 @@ void UpdateDialog::Thread::stop() { UpdateDialog::Thread::Entry::Entry( css::uno::Reference< css::deployment::XPackage > const & thePackage, rtl::OUString const & theVersion): + package(thePackage), - version(theVersion) -{} + version(theVersion), + bProvidesOwnUpdate(false), + updateData(thePackage) +{ +} UpdateDialog::Thread::~Thread() { @@ -343,10 +361,10 @@ void UpdateDialog::Thread::execute() OSL_ASSERT( ! m_vExtensionList.empty() ); Map map; - typedef std::vector< TUpdateListEntry >::const_iterator ITER; + typedef std::vector< css::uno::Reference< css::deployment::XPackage > >::const_iterator ITER; for ( ITER iIndex = m_vExtensionList.begin(); iIndex < m_vExtensionList.end(); ++iIndex ) { - css::uno::Reference< css::deployment::XPackage > p = (*iIndex)->m_xPackage; + css::uno::Reference< css::deployment::XPackage > p = *iIndex; if ( p.is() ) { { @@ -355,47 +373,113 @@ void UpdateDialog::Thread::execute() return; } } - handle( p, &map ); + getOwnUpdateInformation( p, &map ); } } - if (!map.empty()) { - const rtl::OUString sDefaultURL(dp_misc::getExtensionDefaultUpdateURL()); - if (sDefaultURL.getLength()) - { - css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > - infos( - getUpdateInformation( - css::uno::Reference< css::deployment::XPackage >(), - css::uno::Sequence< rtl::OUString >(&sDefaultURL, 1), rtl::OUString())); - for (sal_Int32 i = 0; i < infos.getLength(); ++i) { - css::uno::Reference< css::xml::dom::XNode > node( - infos[i], css::uno::UNO_QUERY_THROW); - dp_misc::DescriptionInfoset infoset(m_context, node); - boost::optional< rtl::OUString > id(infoset.getIdentifier()); - if (!id) { - continue; - } - Map::iterator end(map.upper_bound(*id)); - for (Map::iterator j(map.lower_bound(*id)); j != end; ++j) { - rtl::OUString v(infoset.getVersion()); - if (dp_misc::compareVersions(v, j->second.version) == - dp_misc::GREATER) - { - j->second.version = v; - j->second.info = node; - } - } + const rtl::OUString sDefaultURL(dp_misc::getExtensionDefaultUpdateURL()); + if (sDefaultURL.getLength()) + { + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > + infos( + getUpdateInformation( + css::uno::Reference< css::deployment::XPackage >(), + css::uno::Sequence< rtl::OUString >(&sDefaultURL, 1), rtl::OUString())); + for (sal_Int32 i = 0; i < infos.getLength(); ++i) { + css::uno::Reference< css::xml::dom::XNode > node( + infos[i], css::uno::UNO_QUERY_THROW); + dp_misc::DescriptionInfoset infoset(m_context, node); + boost::optional< rtl::OUString > id(infoset.getIdentifier()); + if (!id) { + continue; } - for (Map::const_iterator i(map.begin()); i != map.end(); ++i) { - if (i->second.info.is() && - !update( i->second.package, i->second.info )) + Map::iterator end(map.upper_bound(*id)); + for (Map::iterator j(map.lower_bound(*id)); j != end; ++j) { + //skip those extension which provide its own update urls + if (j->second.bProvidesOwnUpdate) + continue; + rtl::OUString v(infoset.getVersion()); + //look for the highest version in the online repository + if (dp_misc::compareVersions(v, j->second.version) == + dp_misc::GREATER) { - break; + j->second.version = v; + j->second.info = node; } } } } + + css::uno::Reference<css::deployment::XExtensionManager> extMgr = + css::deployment::ExtensionManager::get(m_context); + for (Map::iterator i(map.begin()); i != map.end(); ++i) + { + //determine if online updates meet the requirements + prepareUpdateData(i->second.package, i->second.info, + i->second.disableUpdate, i->second.updateData); + + //determine if the update is installed in the user or shared repository + rtl::OUString sOnlineVersion; + if (i->second.updateData.aUpdateInfo.is()) + sOnlineVersion = i->second.version; + + rtl::OUString sVersionUser; + rtl::OUString sVersionShared; + rtl::OUString sVersionBundled; + css::uno::Sequence< css::uno::Reference< css::deployment::XPackage> > extensions; + try { + extensions = extMgr->getExtensionsWithSameIdentifier( + dp_misc::getIdentifier(i->second.package), i->second.package->getName(), + css::uno::Reference<css::ucb::XCommandEnvironment>()); + } catch (css::lang::IllegalArgumentException& ) { + OSL_ASSERT(0); + } + OSL_ASSERT(extensions.getLength() == 3); + if (extensions[0].is() ) + sVersionUser = extensions[0]->getVersion(); + if (extensions[1].is() ) + sVersionShared = extensions[1]->getVersion(); + if (extensions[2].is() ) + sVersionBundled = extensions[2]->getVersion(); + + bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared")); + + dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension( + bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion); + dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension( + bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion); + + css::uno::Reference<css::deployment::XPackage> updateSource; + if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) + { + if (sourceUser == dp_misc::UPDATE_SOURCE_SHARED) + { + i->second.updateData.aUpdateSource = extensions[1]; + i->second.updateData.updateVersion = extensions[1]->getVersion(); + } + else if (sourceUser == dp_misc::UPDATE_SOURCE_BUNDLED) + { + i->second.updateData.aUpdateSource = extensions[2]; + i->second.updateData.updateVersion = extensions[2]->getVersion(); + } + if (!update(i->second.disableUpdate, i->second.updateData)) + return; + } + + if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) + { + if (sourceShared == dp_misc::UPDATE_SOURCE_BUNDLED) + { + i->second.updateData.aUpdateSource = extensions[2]; + i->second.updateData.updateVersion = extensions[2]->getVersion(); + } + i->second.updateData.bIsShared = true; + if (!update(i->second.disableUpdate, i->second.updateData)) + return; + } + } + + vos::OGuard g(Application::GetSolarMutex()); if (!m_stop) { m_dialog.checkingDone(); @@ -454,7 +538,7 @@ UpdateDialog::Thread::getUpdateInformation( css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > >(); } -void UpdateDialog::Thread::handle( +void UpdateDialog::Thread::getOwnUpdateInformation( css::uno::Reference< css::deployment::XPackage > const & package, Map * map) { @@ -464,11 +548,11 @@ void UpdateDialog::Thread::handle( if (urls.getLength() == 0) { map->insert( Map::value_type( - id, Entry(package, package->getVersion()))); + id, Entry(package, OUSTR("")))); } else { css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > infos(getUpdateInformation(package, urls, id)); - rtl::OUString latestVersion(package->getVersion()); + rtl::OUString latestVersion; sal_Int32 latestIndex = -1; for (sal_Int32 i = 0; i < infos.getLength(); ++i) { dp_misc::DescriptionInfoset infoset( @@ -490,80 +574,102 @@ void UpdateDialog::Thread::handle( } } if (latestIndex != -1) { - update( package, - css::uno::Reference< css::xml::dom::XNode >( - infos[latestIndex], css::uno::UNO_QUERY_THROW)); + Entry e(package, latestVersion); + e.info = css::uno::Reference< css::xml::dom::XNode >( + infos[latestIndex], css::uno::UNO_QUERY_THROW); + e.bProvidesOwnUpdate = true; + map->insert(Map::value_type(id, e)); } } } -bool UpdateDialog::Thread::update( - css::uno::Reference< css::deployment::XPackage > const & package, - css::uno::Reference< css::xml::dom::XNode > const & updateInfo) const +::rtl::OUString UpdateDialog::Thread::getUpdateDisplayString( + dp_gui::UpdateData const & data, ::rtl::OUString const & version) const { - dp_misc::DescriptionInfoset infoset(m_context, updateInfo); - OSL_ASSERT(infoset.getVersion().getLength() != 0); - css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > ds( - dp_misc::Dependencies::check(infoset)); - - UpdateDialog::DisabledUpdate du; - du.aUpdateInfo = updateInfo; - du.unsatisfiedDependencies.realloc(ds.getLength()); - for (sal_Int32 i = 0; i < ds.getLength(); ++i) { - du.unsatisfiedDependencies[i] = dp_misc::Dependencies::getErrorText(ds[i]); - } - du.permission = ! m_dialog.isReadOnly( package ); - const ::boost::optional< ::rtl::OUString> updateWebsiteURL(infoset.getLocalizedUpdateWebsiteURL()); - rtl::OUStringBuffer b(package->getDisplayName()); + OSL_ASSERT(data.aInstalledPackage.is()); + rtl::OUStringBuffer b(data.aInstalledPackage->getDisplayName()); b.append(static_cast< sal_Unicode >(' ')); { vos::OGuard g( Application::GetSolarMutex() ); - if ( m_stop ) - return !m_stop; - else - b.append(m_dialog.m_version); + b.append(m_dialog.m_version); } b.append(static_cast< sal_Unicode >(' ')); - b.append(infoset.getVersion()); - if (updateWebsiteURL) + if (version.getLength()) + b.append(version); + else + b.append(data.updateVersion); + + if (data.sWebsiteURL.getLength()) { b.append(static_cast< sal_Unicode >(' ')); { vos::OGuard g( Application::GetSolarMutex() ); - if ( m_stop ) - return !m_stop; - else - b.append(m_dialog.m_browserbased); + b.append(m_dialog.m_browserbased); } } - du.name = b.makeStringAndClear(); + return b.makeStringAndClear(); +} + +/** out_data will only be filled if all dependencies are ok. + */ +void UpdateDialog::Thread::prepareUpdateData( + css::uno::Reference< css::deployment::XPackage > const & package, + css::uno::Reference< css::xml::dom::XNode > const & updateInfo, + UpdateDialog::DisabledUpdate & out_du, + dp_gui::UpdateData & out_data) const +{ + if (!updateInfo.is()) + return; + dp_misc::DescriptionInfoset infoset(m_context, updateInfo); + OSL_ASSERT(infoset.getVersion().getLength() != 0); + css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > ds( + dp_misc::Dependencies::check(infoset)); + + out_du.aUpdateInfo = updateInfo; + out_du.unsatisfiedDependencies.realloc(ds.getLength()); + for (sal_Int32 i = 0; i < ds.getLength(); ++i) { + out_du.unsatisfiedDependencies[i] = dp_misc::Dependencies::getErrorText(ds[i]); + } + + const ::boost::optional< ::rtl::OUString> updateWebsiteURL(infoset.getLocalizedUpdateWebsiteURL()); + + out_du.name = getUpdateDisplayString(out_data, infoset.getVersion()); - if (du.unsatisfiedDependencies.getLength() == 0 && du.permission) + if (out_du.unsatisfiedDependencies.getLength() == 0) { - dp_gui::UpdateData data; - data.aInstalledPackage = package; - data.aUpdateInfo = updateInfo; + out_data.aUpdateInfo = updateInfo; + out_data.updateVersion = infoset.getVersion(); if (updateWebsiteURL) - data.sWebsiteURL = *updateWebsiteURL; + out_data.sWebsiteURL = *updateWebsiteURL; + } +} + +bool UpdateDialog::Thread::update( + UpdateDialog::DisabledUpdate const & du, + dp_gui::UpdateData const & data) const +{ + if (du.unsatisfiedDependencies.getLength() == 0) + { vos::OGuard g(Application::GetSolarMutex()); if (!m_stop) { - m_dialog.addEnabledUpdate(du.name, data); + m_dialog.addEnabledUpdate(getUpdateDisplayString(data), data); } return !m_stop; } else { vos::OGuard g(Application::GetSolarMutex()); if (!m_stop) { - m_dialog.addDisabledUpdate(du); + m_dialog.addDisabledUpdate(du); } return !m_stop; } + return true; } // UpdateDialog ---------------------------------------------------------- UpdateDialog::UpdateDialog( css::uno::Reference< css::uno::XComponentContext > const & context, Window * parent, - const std::vector< dp_gui::TUpdateListEntry > &vExtensionList, + const std::vector<css::uno::Reference< css::deployment::XPackage > > &vExtensionList, std::vector< dp_gui::UpdateData > * updateData): ModalDialog(parent,DpGuiResId(RID_DLG_UPDATE)), m_context(context), @@ -593,8 +699,6 @@ UpdateDialog::UpdateDialog( m_noInstall(String(DpGuiResId(RID_DLG_UPDATE_NOINSTALL))), m_noDependency(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY))), m_noDependencyCurVer(String(DpGuiResId(RID_DLG_UPDATE_NODEPENDENCY_CUR_VER))), - m_noPermission(String(DpGuiResId(RID_DLG_UPDATE_NOPERMISSION))), - m_noPermissionVista(String(DpGuiResId(RID_DLG_UPDATE_NOPERMISSION_VISTA))), m_browserbased(String(DpGuiResId(RID_DLG_UPDATE_BROWSERBASED))), m_version(String(DpGuiResId(RID_DLG_UPDATE_VERSION))), m_updateData(*updateData), @@ -651,9 +755,6 @@ UpdateDialog::UpdateDialog( if ( ! dp_misc::office_is_running()) m_help.Disable(); FreeResource(); - String sTemp(m_noPermissionVista); - sTemp.SearchAndReplaceAllAscii( "%PRODUCTNAME", BrandName::get() ); - m_noPermissionVista = sTemp; initDescription(); } @@ -983,12 +1084,25 @@ void UpdateDialog::clearDescription() bool UpdateDialog::showDescription(css::uno::Reference< css::xml::dom::XNode > const & aUpdateInfo) { dp_misc::DescriptionInfoset infoset(m_context, aUpdateInfo); - std::pair< rtl::OUString, rtl::OUString > pairPub = infoset.getLocalizedPublisherNameAndURL(); - rtl::OUString sPub = pairPub.first; - rtl::OUString sURL = pairPub.second; - rtl::OUString sRel = infoset.getLocalizedReleaseNotesURL(); + return showDescription(infoset.getLocalizedPublisherNameAndURL(), + infoset.getLocalizedReleaseNotesURL()); +} + +bool UpdateDialog::showDescription(css::uno::Reference< css::deployment::XPackage > const & aExtension) +{ + OSL_ASSERT(aExtension.is()); + css::beans::StringPair pubInfo = aExtension->getPublisherInfo(); + return showDescription(std::make_pair(pubInfo.First, pubInfo.Second), + OUSTR("")); +} - if ( sPub.getLength() == 0 && sURL.getLength() == 0 && sRel.getLength() == 0 ) +bool UpdateDialog::showDescription(std::pair< rtl::OUString, rtl::OUString > const & pairPublisher, + rtl::OUString const & sReleaseNotes) +{ + rtl::OUString sPub = pairPublisher.first; + rtl::OUString sURL = pairPublisher.second; + + if ( sPub.getLength() == 0 && sURL.getLength() == 0 && sReleaseNotes.getLength() == 0 ) // nothing to show return false; @@ -1002,7 +1116,7 @@ bool UpdateDialog::showDescription(css::uno::Reference< css::xml::dom::XNode > c bPublisher = true; } - if ( sRel.getLength() > 0 ) + if ( sReleaseNotes.getLength() > 0 ) { if ( !bPublisher ) { @@ -1011,7 +1125,7 @@ bool UpdateDialog::showDescription(css::uno::Reference< css::xml::dom::XNode > c } m_ReleaseNotesLabel.Show(); m_ReleaseNotesLink.Show(); - m_ReleaseNotesLink.SetURL( sRel ); + m_ReleaseNotesLink.SetURL( sReleaseNotes ); } return true; } @@ -1069,7 +1183,12 @@ IMPL_LINK(UpdateDialog, selectionHandler, void *, EMPTYARG) const std::vector< UpdateDialog::DisabledUpdate >::size_type sizeDisabled = m_disabledUpdates.size(); if (pos < sizeEnabled) - bInserted = showDescription(m_enabledUpdates[pos].aUpdateInfo); + { + if (m_enabledUpdates[pos].aUpdateSource.is()) + bInserted = showDescription(m_enabledUpdates[pos].aUpdateSource); + else + bInserted = showDescription(m_enabledUpdates[pos].aUpdateInfo); + } else if (pos >= sizeEnabled && pos < (sizeEnabled + sizeDisabled)) bInserted = showDescription(m_disabledUpdates[pos - sizeEnabled].aUpdateInfo); @@ -1115,16 +1234,6 @@ IMPL_LINK(UpdateDialog, selectionHandler, void *, EMPTYARG) b.appendAscii(RTL_CONSTASCII_STRINGPARAM(" ")); b.append(m_noDependencyCurVer); } - if (!data.permission) { - if (b.getLength() == 0) { - b.append(m_noInstall); - } - b.append(LF); - if (isVista()) - b.append(m_noPermissionVista); - else - b.append(m_noPermission); - } break; } case GENERAL_ERROR: @@ -1231,7 +1340,7 @@ IMPL_LINK(UpdateDialog, okHandler, void *, EMPTYARG) OSL_ASSERT(i->aInstalledPackage.is()); //If the user has no write access to the shared folder then the update //for a shared extension is disable, that is it cannot be in m_enabledUpdates - OSL_ASSERT(isReadOnly(i->aInstalledPackage) == sal_False); +// OSL_ASSERT(isReadOnly(i->aInstalledPackage) == sal_False); #if 0 // TODO: check! OSL_ASSERT(m_extensionManagerDialog.get()); @@ -1243,6 +1352,7 @@ IMPL_LINK(UpdateDialog, okHandler, void *, EMPTYARG) #endif } + for (USHORT i = 0; i < m_updates.getItemCount(); ++i) { UpdateDialog::Index const * p = static_cast< UpdateDialog::Index const * >( @@ -1251,6 +1361,7 @@ IMPL_LINK(UpdateDialog, okHandler, void *, EMPTYARG) m_updateData.push_back(m_enabledUpdates[p->index.enabledUpdate]); } } + EndDialog(RET_OK); return 0; } diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.hxx b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx index 1e72b22a68c7..32c317cb8735 100644 --- a/desktop/source/deployment/gui/dp_gui_updatedialog.hxx +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.hxx @@ -83,16 +83,17 @@ public: @param parent the parent window, may be null - @param selectedPackages - if non-null, only check for updates for the selected packages - - @param packageManagers - if non-null, check for updates for all managed packages + @param vExtensionList + check for updates for the contained extensions. There must only be one extension with + a particular identifier. If one extension is installed in several repositories, then the + one with the highest version must be used, because it contains the latest known update + information. */ UpdateDialog( com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > const & context, Window * parent, - const std::vector< dp_gui::TUpdateListEntry > &vExtensionList, + const std::vector< com::sun::star::uno::Reference< + com::sun::star::deployment::XPackage > > & vExtensionList, std::vector< dp_gui::UpdateData > * updateData); ~UpdateDialog(); @@ -142,6 +143,7 @@ private: UpdateDialog & m_dialog; }; + friend class CheckListBox; void insertItem( @@ -169,6 +171,10 @@ private: void initDescription(); void clearDescription(); + bool showDescription(::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage > const & aExtension); + bool showDescription(std::pair< rtl::OUString, rtl::OUString > const & pairPublisher, + rtl::OUString const & sReleaseNotes); bool showDescription( ::com::sun::star::uno::Reference< ::com::sun::star::xml::dom::XNode > const & aUpdateInfo); bool showDescription( const String& rDescription, bool bWithPublisher ); @@ -206,8 +212,6 @@ private: rtl::OUString m_noInstall; rtl::OUString m_noDependency; rtl::OUString m_noDependencyCurVer; - rtl::OUString m_noPermission; - rtl::OUString m_noPermissionVista; rtl::OUString m_browserbased; rtl::OUString m_version; std::vector< dp_gui::UpdateData > m_enabledUpdates; diff --git a/desktop/source/deployment/gui/dp_gui_updatedialog.src b/desktop/source/deployment/gui/dp_gui_updatedialog.src index b86a8ad66f08..325d98c88d48 100644 --- a/desktop/source/deployment/gui/dp_gui_updatedialog.src +++ b/desktop/source/deployment/gui/dp_gui_updatedialog.src @@ -244,18 +244,6 @@ ModalDialog RID_DLG_UPDATE { String RID_DLG_UPDATE_NODEPENDENCY_CUR_VER { Text[en-US] = "You have OpenOffice.org %VERSION"; }; - String RID_DLG_UPDATE_NOPERMISSION { - Text[en-US] = "No write permission (shared extension)."; - }; - String RID_DLG_UPDATE_NOPERMISSION_VISTA { - Text[en-US] = "No write permission. %PRODUCTNAME needs to run as administrator.\n" - "Please follow these steps to update this shared extension:\n" - "1. Close Extension Manager dialog.\n" - "2. Exit %PRODUCTNAME.\n" - "3. Exit %PRODUCTNAME Quickstarter located in the tray area of Windows.\n" - "4. Run %PRODUCTNAME as administrator. In order to do this call the context menu of the %PRODUCTNAME program icon and choose \'Run as administrator\'.\n" - "5. Call the Extension Manager dialog and update this shared extension.\n"; - }; String RID_DLG_UPDATE_BROWSERBASED { Text[en-US] = "browser based update"; }; diff --git a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx index f2f8b8b0d6e2..067a703ec413 100644 --- a/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx +++ b/desktop/source/deployment/gui/dp_gui_updateinstalldialog.cxx @@ -380,13 +380,12 @@ void UpdateInstallDialog::Thread::downloadExtensions() { UpdateData & curData = *i; - OSL_ASSERT(curData.aUpdateInfo.is()); + if (!curData.aUpdateInfo.is() || curData.aUpdateSource.is()) + continue; //We assume that m_aVecUpdateData contains only information about extensions which //can be downloaded directly. OSL_ASSERT(curData.sWebsiteURL.getLength() == 0); - if (!curData.aUpdateInfo.is()) - continue; //update the name of the extension which is to be downloaded { ::vos::OGuard g(Application::GetSolarMutex()); @@ -491,13 +490,11 @@ void UpdateInstallDialog::Thread::installExtensions() // osl::Thread::wait(v); bool bError = false; bool bLicenseDeclined = false; - cssu::Reference<css::deployment::XPackage> xPackage; + cssu::Reference<css::deployment::XPackage> xExtension; UpdateData & curData = *i; cssu::Exception exc; try { - if (curData.sLocalURL.getLength() == 0) - continue; cssu::Reference< css::task::XAbortChannel > xAbortChannel( curData.aInstalledPackage->createAbortChannel() ); { @@ -507,9 +504,35 @@ void UpdateInstallDialog::Thread::installExtensions() } m_abort = xAbortChannel; } - xPackage = m_dialog.getExtensionManager()->addExtension( - curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(), - curData.aInstalledPackage->getRepositoryName(), xAbortChannel, m_updateCmdEnv.get()); + if (!curData.aUpdateSource.is() && curData.sLocalURL.getLength()) + { + css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); + if (!curData.bIsShared) + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); + else + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.sLocalURL, css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); + } + else if (curData.aUpdateSource.is()) + { + OSL_ASSERT(curData.aUpdateSource.is()); + //I am not sure if we should obtain the install properties and pass them into + //add extension. Currently it contains only "SUPPRESS_LICENSE". So it it could happen + //that a license is displayed when updating from the shared repository, although the + //shared extension was installed using "SUPPRESS_LICENSE". + css::beans::NamedValue prop(OUSTR("EXTENSION_UPDATE"), css::uno::makeAny(OUSTR("1"))); + if (!curData.bIsShared) + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("user"), xAbortChannel, m_updateCmdEnv.get()); + else + xExtension = m_dialog.getExtensionManager()->addExtension( + curData.aUpdateSource->getURL(), css::uno::Sequence<css::beans::NamedValue>(&prop, 1), + OUSTR("shared"), xAbortChannel, m_updateCmdEnv.get()); + } } catch (css::deployment::DeploymentException & de) { @@ -538,7 +561,7 @@ void UpdateInstallDialog::Thread::installExtensions() m_dialog.setError(UpdateInstallDialog::ERROR_LICENSE_DECLINED, curData.aInstalledPackage->getDisplayName(), OUString()); } - else if (!xPackage.is() || bError) + else if (!xExtension.is() || bError) { ::vos::OGuard g(Application::GetSolarMutex()); if (m_stop) { diff --git a/desktop/source/deployment/inc/dp_misc.h b/desktop/source/deployment/inc/dp_misc.h index a0ca7f53be03..161b91a6bcde 100644 --- a/desktop/source/deployment/inc/dp_misc.h +++ b/desktop/source/deployment/inc/dp_misc.h @@ -179,6 +179,52 @@ DESKTOP_DEPLOYMENTMISC_DLLPUBLIC void syncRepositories(::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment> const & xCmdEnv); +enum UPDATE_SOURCE +{ + UPDATE_SOURCE_NONE, + UPDATE_SOURCE_SHARED, + UPDATE_SOURCE_BUNDLED, + UPDATE_SOURCE_ONLINE +}; + +/* determine if an update is available which is installed in the + user repository. + + If the return value is UPDATE_SOURCE_NONE, then no update is + available, otherwise the return value determine from which the + repository the update is used. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +UPDATE_SOURCE isUpdateUserExtension( + bool bReadOnlyShared, + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion); + +/* determine if an update is available which is installed in the + shared repository. + + If the return value is UPDATE_SOURCE_NONE, then no update is + available, otherwise the return value determine from which the + repository the update is used. +*/ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +UPDATE_SOURCE isUpdateSharedExtension( + bool bReadOnlyShared, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion); + +/* determines the extension with the highest identifier and returns it + + */ +DESKTOP_DEPLOYMENTMISC_DLLPUBLIC +::com::sun::star::uno::Reference< ::com::sun::star::deployment::XPackage> +getExtensionWithHighestVersion( + ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::deployment::XPackage> > const & seqExtensionsWithSameId); } diff --git a/desktop/source/deployment/manager/dp_extensionmanager.cxx b/desktop/source/deployment/manager/dp_extensionmanager.cxx index fddefb5ad277..251e70a19ce6 100644 --- a/desktop/source/deployment/manager/dp_extensionmanager.cxx +++ b/desktop/source/deployment/manager/dp_extensionmanager.cxx @@ -250,7 +250,8 @@ void ExtensionManager::addExtensionsToMap( */ ::std::list<Reference<deploy::XPackage> > ExtensionManager::getExtensionsWithSameId( - OUString const & identifier, OUString const & fileName) + OUString const & identifier, OUString const & fileName, + Reference< ucb::XCommandEnvironment> const & xCmdEnv) { ::std::list<Reference<deploy::XPackage> > extensionList; @@ -282,13 +283,70 @@ void ExtensionManager::addExtensionsToMap( return extensionList; } +uno::Sequence<Reference<deploy::XPackage> > +ExtensionManager::getExtensionsWithSameIdentifier( + OUString const & identifier, + OUString const & fileName, + Reference< ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + deploy::DeploymentException, + ucb::CommandFailedException, + lang::IllegalArgumentException, + uno::RuntimeException) +{ + try + { + ::std::list<Reference<deploy::XPackage> > listExtensions = + getExtensionsWithSameId( + identifier, fileName, xCmdEnv); + sal_Bool bHasExtension = false; + + //throw an IllegalArgumentException if there is no extension at all. + typedef ::std::list<Reference<deploy::XPackage> >::const_iterator CIT; + for (CIT i = listExtensions.begin(); i != listExtensions.end(); i++) + bHasExtension |= i->is(); + if (!bHasExtension) + throw lang::IllegalArgumentException( + OUSTR("Could not find extension: ") + identifier + OUSTR(", ") + fileName, + static_cast<cppu::OWeakObject*>(this), -1); + + return comphelper::containerToSequence< + Reference<deploy::XPackage>, + ::std::list<Reference<deploy::XPackage> > + > (listExtensions); + } + catch (deploy::DeploymentException & ) + { + throw; + } + catch ( ucb::CommandFailedException & ) + { + throw; + } + catch (lang::IllegalArgumentException &) + { + throw; + } + catch (...) + { + uno::Any exc = ::cppu::getCaughtException(); + throw deploy::DeploymentException( + OUSTR("Extension Manager: exception during getExtensionsWithSameIdentifier"), + static_cast<OWeakObject*>(this), exc); + } +} + bool ExtensionManager::isUserDisabled( OUString const & identifier, OUString const & fileName) { - ::std::list<Reference<deploy::XPackage> > listExtensions = - getExtensionsWithSameId(identifier, fileName); + ::std::list<Reference<deploy::XPackage> > listExtensions; + + try { + listExtensions = getExtensionsWithSameId(identifier, fileName); + } catch (lang::IllegalArgumentException & ) { + } OSL_ASSERT(listExtensions.size() == 3); return isUserDisabled( ::comphelper::containerToSequence< @@ -339,8 +397,11 @@ void ExtensionManager::activateExtension( Reference<task::XAbortChannel> const & xAbortChannel, Reference<ucb::XCommandEnvironment> const & xCmdEnv ) { - ::std::list<Reference<deploy::XPackage> > listExtensions = - getExtensionsWithSameId(identifier, fileName); + ::std::list<Reference<deploy::XPackage> > listExtensions; + try { + listExtensions = getExtensionsWithSameId(identifier, fileName); + } catch (lang::IllegalArgumentException &) { + } OSL_ASSERT(listExtensions.size() == 3); activateExtension( @@ -510,9 +571,11 @@ Reference<deploy::XPackage> ExtensionManager::addExtension( ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>()); if (licenseAttributes && licenseAttributes->suppressIfRequired && props.isSuppressedLicense()) - _xCmdEnv = Reference<ucb::XCommandEnvironment>(new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler())); + _xCmdEnv = Reference<ucb::XCommandEnvironment>( + new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler())); + bCanInstall = xTmpExtension->checkPrerequisites( - xAbortChannel, _xCmdEnv, xOldExtension.is()) == 0 ? true : false; + xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0 ? true : false; } catch (deploy::DeploymentException& ) { excOccurred1 = ::cppu::getCaughtException(); diff --git a/desktop/source/deployment/manager/dp_extensionmanager.hxx b/desktop/source/deployment/manager/dp_extensionmanager.hxx index ad0e7d95df7e..54624514adce 100644 --- a/desktop/source/deployment/manager/dp_extensionmanager.hxx +++ b/desktop/source/deployment/manager/dp_extensionmanager.hxx @@ -163,6 +163,17 @@ public: css::lang::IllegalArgumentException, css::uno::RuntimeException); + virtual css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > + SAL_CALL getExtensionsWithSameIdentifier( + ::rtl::OUString const & identifier, + ::rtl::OUString const & filename, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv ) + throw ( + css::deployment::DeploymentException, + css::ucb::CommandFailedException, + css::lang::IllegalArgumentException, + css::uno::RuntimeException); + virtual css::uno::Sequence< css::uno::Sequence<css::uno::Reference<css::deployment::XPackage> > > SAL_CALL getAllExtensions( css::uno::Reference<css::task::XAbortChannel> const &, @@ -252,7 +263,9 @@ private: ::std::list<css::uno::Reference<css::deployment::XPackage> > getExtensionsWithSameId(::rtl::OUString const & identifier, - ::rtl::OUString const & fileName); + ::rtl::OUString const & fileName, + css::uno::Reference< css::ucb::XCommandEnvironment> const & xCmdEnv = + css::uno::Reference< css::ucb::XCommandEnvironment>()); css::uno::Reference<css::deployment::XPackage> backupExtension( ::rtl::OUString const & identifier, ::rtl::OUString const & fileName, diff --git a/desktop/source/deployment/manager/dp_properties.cxx b/desktop/source/deployment/manager/dp_properties.cxx index b04e8131ee15..df579944c6e4 100644 --- a/desktop/source/deployment/manager/dp_properties.cxx +++ b/desktop/source/deployment/manager/dp_properties.cxx @@ -50,6 +50,8 @@ using ::com::sun::star::uno::Reference; using ::rtl::OUString; #define PROP_SUPPRESS_LICENSE "SUPPRESS_LICENSE" +#define PROP_EXTENSION_UPDATE "EXTENSION_UPDATE" + namespace dp_manager { //Reading the file @@ -89,17 +91,11 @@ ExtensionProperties::ExtensionProperties( css::beans::NamedValue const & v = properties[i]; if (v.Name.equals(OUSTR(PROP_SUPPRESS_LICENSE))) { - OUString value; - if (v.Value >>= value) - { - if (value.equals(OUSTR("1"))) - m_prop_suppress_license = OUSTR("1"); - } - else - { - throw lang::IllegalArgumentException( - OUSTR("Extension Manager: wrong property value"), 0, -1); - } + m_prop_suppress_license = getPropertyValue(v); + } + else if (v.Name.equals(OUSTR(PROP_EXTENSION_UPDATE))) + { + m_prop_extension_update = getPropertyValue(v); } else { @@ -109,6 +105,21 @@ ExtensionProperties::ExtensionProperties( } } +OUString ExtensionProperties::getPropertyValue(css::beans::NamedValue const & v) +{ + OUString value(OUSTR("0")); + if (v.Value >>= value) + { + if (value.equals(OUSTR("1"))) + value = OUSTR("1"); + } + else + { + throw lang::IllegalArgumentException( + OUSTR("Extension Manager: wrong property value"), 0, -1); + } + return value; +} void ExtensionProperties::write() { ::ucbhelper::Content contentProps(m_propFileUrl, m_xCmdEnv); @@ -142,6 +153,17 @@ bool ExtensionProperties::isSuppressedLicense() return ret; } +bool ExtensionProperties::isExtensionUpdate() +{ + bool ret = false; + if (m_prop_extension_update) + { + if (m_prop_extension_update->equals(OUSTR("1"))) + ret = true; + } + return ret; +} + } // namespace dp_manager diff --git a/desktop/source/deployment/manager/dp_properties.hxx b/desktop/source/deployment/manager/dp_properties.hxx index 197155653de1..97fc8b8c5394 100644 --- a/desktop/source/deployment/manager/dp_properties.hxx +++ b/desktop/source/deployment/manager/dp_properties.hxx @@ -53,6 +53,9 @@ protected: ::rtl::OUString m_propFileUrl; const css::uno::Reference<css::ucb::XCommandEnvironment> m_xCmdEnv; ::boost::optional< ::rtl::OUString> m_prop_suppress_license; + ::boost::optional< ::rtl::OUString> m_prop_extension_update; + + ::rtl::OUString getPropertyValue(css::beans::NamedValue const & v); public: virtual ~ExtensionProperties() {}; @@ -66,6 +69,8 @@ public: void write(); bool isSuppressedLicense(); + + bool isExtensionUpdate(); }; } diff --git a/desktop/source/deployment/misc/dp_misc.cxx b/desktop/source/deployment/misc/dp_misc.cxx index 5269e3d8aac5..53d488095ecd 100644 --- a/desktop/source/deployment/misc/dp_misc.cxx +++ b/desktop/source/deployment/misc/dp_misc.cxx @@ -30,6 +30,7 @@ #include "dp_misc.h" +#include "dp_version.hxx" #include "dp_interact.h" #include "rtl/uri.hxx" #include "rtl/digest.h" @@ -630,6 +631,147 @@ void syncRepositories(Reference<ucb::XCommandEnvironment> const & xCmdEnv) } } +/* returns the index of the greatest version, starting with 0 + + */ +int determineHighestVersion( + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + int index = 0; + OUString greatest = userVersion; + if (dp_misc::compareVersions(sharedVersion, greatest) == dp_misc::GREATER) + { + index = 1; + greatest = sharedVersion; + } + if (dp_misc::compareVersions(bundledVersion, greatest) == dp_misc::GREATER) + { + index = 2; + greatest = bundledVersion; + } + if (dp_misc::compareVersions(onlineVersion, greatest) == dp_misc::GREATER) + { + index = 3; + } + return index; +} + +UPDATE_SOURCE isUpdateUserExtension( + bool bReadOnlyShared, + ::rtl::OUString const & userVersion, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE; + if (bReadOnlyShared) + { + if (userVersion.getLength()) + { + int index = determineHighestVersion( + userVersion, sharedVersion, bundledVersion, onlineVersion); + if (index == 1) + retVal = UPDATE_SOURCE_SHARED; + else if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + else if (sharedVersion.getLength()) + { + int index = determineHighestVersion( + OUString(), sharedVersion, bundledVersion, onlineVersion); + if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + + } + else if (bundledVersion.getLength()) + { + int index = determineHighestVersion( + OUString(), OUString(), bundledVersion, onlineVersion); + if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + } + else + { + if (userVersion.getLength()) + { + int index = determineHighestVersion( + userVersion, sharedVersion, bundledVersion, onlineVersion); + if (index == 1) + retVal = UPDATE_SOURCE_SHARED; + else if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + } + + return retVal; +} + +UPDATE_SOURCE isUpdateSharedExtension( + bool bReadOnlyShared, + ::rtl::OUString const & sharedVersion, + ::rtl::OUString const & bundledVersion, + ::rtl::OUString const & onlineVersion) +{ + if (bReadOnlyShared) + return UPDATE_SOURCE_NONE; + UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE; + + if (sharedVersion.getLength()) + { + int index = determineHighestVersion( + OUString(), sharedVersion, bundledVersion, onlineVersion); + if (index == 2) + retVal = UPDATE_SOURCE_BUNDLED; + else if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + else if (bundledVersion.getLength()) + { + int index = determineHighestVersion( + OUString(), OUString(), bundledVersion, onlineVersion); + if (index == 3) + retVal = UPDATE_SOURCE_ONLINE; + } + return retVal; +} + +Reference<deployment::XPackage> +getExtensionWithHighestVersion( + Sequence<Reference<deployment::XPackage> > const & seqExt) +{ + if (seqExt.getLength() == 0) + return Reference<deployment::XPackage>(); + + Reference<deployment::XPackage> greatest; + sal_Int32 len = seqExt.getLength(); + + for (sal_Int32 i = 0; i < len; i++) + { + if (!greatest.is()) + { + greatest = seqExt[i]; + continue; + } + Reference<deployment::XPackage> const & current = seqExt[i]; + //greatest has a value + if (! current.is()) + continue; + + if (dp_misc::compareVersions(current->getVersion(), greatest->getVersion()) == dp_misc::GREATER) + greatest = current; + } + return greatest; +} } |