| /************************************************************** |
| * |
| * 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 <cppuhelper/implbase3.hxx> |
| |
| #include "comphelper/servicedecl.hxx" |
| |
| #include "com/sun/star/deployment/UpdateInformationProvider.hpp" |
| #include "com/sun/star/deployment/XPackage.hpp" |
| #include "com/sun/star/deployment/XPackageInformationProvider.hpp" |
| #include "com/sun/star/deployment/ExtensionManager.hpp" |
| #include "com/sun/star/deployment/XUpdateInformationProvider.hpp" |
| #include "com/sun/star/lang/XServiceInfo.hpp" |
| #include "com/sun/star/registry/XRegistryKey.hpp" |
| #include "com/sun/star/task/XAbortChannel.hpp" |
| #include "com/sun/star/uno/XComponentContext.hpp" |
| #include "com/sun/star/ucb/XCommandEnvironment.hpp" |
| #include "com/sun/star/xml/dom/XElement.hpp" |
| #include "com/sun/star/xml/dom/XNode.hpp" |
| |
| #include "com/sun/star/uno/Reference.hxx" |
| #include "rtl/ustring.hxx" |
| #include "ucbhelper/content.hxx" |
| |
| #include "dp_dependencies.hxx" |
| #include "dp_descriptioninfoset.hxx" |
| #include "dp_identifier.hxx" |
| #include "dp_version.hxx" |
| #include "dp_misc.h" |
| #include "dp_update.hxx" |
| |
| namespace beans = com::sun::star::beans ; |
| namespace deployment = com::sun::star::deployment ; |
| namespace lang = com::sun::star::lang ; |
| namespace registry = com::sun::star::registry ; |
| namespace task = com::sun::star::task ; |
| namespace css_ucb = com::sun::star::ucb ; |
| namespace uno = com::sun::star::uno ; |
| namespace xml = com::sun::star::xml ; |
| |
| #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) |
| |
| namespace dp_info { |
| |
| class PackageInformationProvider : |
| public ::cppu::WeakImplHelper1< deployment::XPackageInformationProvider > |
| |
| { |
| public: |
| PackageInformationProvider( uno::Reference< uno::XComponentContext >const& xContext); |
| virtual ~PackageInformationProvider(); |
| |
| static uno::Sequence< rtl::OUString > getServiceNames(); |
| static rtl::OUString getImplName(); |
| |
| // XPackageInformationProvider |
| virtual rtl::OUString SAL_CALL getPackageLocation( const rtl::OUString& extensionId ) |
| throw ( uno::RuntimeException ); |
| virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL isUpdateAvailable( const rtl::OUString& extensionId ) |
| throw ( uno::RuntimeException ); |
| virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL getExtensionList() |
| throw ( uno::RuntimeException ); |
| //--------- |
| private: |
| |
| uno::Reference< uno::XComponentContext> mxContext; |
| |
| rtl::OUString getPackageLocation( const rtl::OUString& repository, |
| const rtl::OUString& _sExtensionId ); |
| |
| uno::Reference< deployment::XUpdateInformationProvider > mxUpdateInformation; |
| }; |
| |
| //------------------------------------------------------------------------------ |
| |
| PackageInformationProvider::PackageInformationProvider( uno::Reference< uno::XComponentContext > const& xContext) : |
| mxContext( xContext ), |
| mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext ) ) |
| { |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| PackageInformationProvider::~PackageInformationProvider() |
| { |
| } |
| |
| //------------------------------------------------------------------------------ |
| rtl::OUString PackageInformationProvider::getPackageLocation( |
| const rtl::OUString & repository, |
| const rtl::OUString& _rExtensionId ) |
| { |
| rtl::OUString aLocationURL; |
| uno::Reference<deployment::XExtensionManager> xManager = |
| deployment::ExtensionManager::get(mxContext); |
| |
| if ( xManager.is() ) |
| { |
| const uno::Sequence< uno::Reference< deployment::XPackage > > packages( |
| xManager->getDeployedExtensions( |
| repository, |
| uno::Reference< task::XAbortChannel >(), |
| uno::Reference< css_ucb::XCommandEnvironment > () ) ); |
| |
| for ( int pos = packages.getLength(); pos--; ) |
| { |
| try |
| { |
| const rtl::OUString aName = packages[ pos ]->getName(); |
| const beans::Optional< rtl::OUString > aID = packages[ pos ]->getIdentifier(); |
| if ( aID.IsPresent && aID.Value.compareTo( _rExtensionId ) == 0 ) |
| { |
| aLocationURL = packages[ pos ]->getURL(); |
| break; |
| } |
| } |
| catch ( uno::RuntimeException & ) {} |
| } |
| } |
| |
| return aLocationURL; |
| } |
| |
| //------------------------------------------------------------------------------ |
| //------------------------------------------------------------------------------ |
| //------------------------------------------------------------------------------ |
| |
| rtl::OUString SAL_CALL |
| PackageInformationProvider::getPackageLocation( const rtl::OUString& _sExtensionId ) |
| throw ( uno::RuntimeException ) |
| { |
| rtl::OUString aLocationURL = getPackageLocation( UNISTRING("user"), _sExtensionId ); |
| |
| if ( aLocationURL.getLength() == 0 ) |
| { |
| aLocationURL = getPackageLocation( UNISTRING("shared"), _sExtensionId ); |
| } |
| if ( aLocationURL.getLength() == 0 ) |
| { |
| aLocationURL = getPackageLocation( UNISTRING("bundled"), _sExtensionId ); |
| } |
| if ( aLocationURL.getLength() == 0 ) |
| { |
| aLocationURL = getPackageLocation( UNISTRING("bundled_prereg"), _sExtensionId ); |
| } |
| if ( aLocationURL.getLength() ) |
| { |
| ::ucbhelper::Content aContent( aLocationURL, NULL ); |
| aLocationURL = aContent.getURL(); |
| } |
| return aLocationURL; |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL |
| PackageInformationProvider::isUpdateAvailable( const rtl::OUString& _sExtensionId ) |
| throw ( uno::RuntimeException ) |
| { |
| uno::Sequence< uno::Sequence< rtl::OUString > > aList; |
| |
| uno::Reference<deployment::XExtensionManager> extMgr = |
| deployment::ExtensionManager::get(mxContext); |
| |
| if (!extMgr.is()) |
| { |
| OSL_ASSERT(0); |
| return aList; |
| } |
| std::vector<std::pair<uno::Reference<deployment::XPackage>, uno::Any > > errors; |
| dp_misc::UpdateInfoMap updateInfoMap; |
| if (_sExtensionId.getLength()) |
| { |
| std::vector<uno::Reference<deployment::XPackage> > vecExtensions; |
| uno::Reference<deployment::XPackage> extension; |
| try |
| { |
| extension = dp_misc::getExtensionWithHighestVersion( |
| extMgr->getExtensionsWithSameIdentifier( |
| _sExtensionId, _sExtensionId, uno::Reference<css_ucb::XCommandEnvironment>())); |
| vecExtensions.push_back(extension); |
| } |
| catch (lang::IllegalArgumentException &) |
| { |
| OSL_ASSERT(0); |
| } |
| updateInfoMap = dp_misc::getOnlineUpdateInfos( |
| mxContext, extMgr, mxUpdateInformation, &vecExtensions, errors); |
| } |
| else |
| { |
| updateInfoMap = dp_misc::getOnlineUpdateInfos( |
| mxContext, extMgr, mxUpdateInformation, NULL, errors); |
| } |
| |
| int nCount = 0; |
| for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); i++) |
| { |
| dp_misc::UpdateInfo const & info = i->second; |
| |
| rtl::OUString sOnlineVersion; |
| if (info.info.is()) |
| { |
| // check, if there are unsatisfied dependencies and ignore this online update |
| dp_misc::DescriptionInfoset infoset(mxContext, info.info); |
| uno::Sequence< uno::Reference< xml::dom::XElement > > |
| ds( dp_misc::Dependencies::check( infoset ) ); |
| if ( ! ds.getLength() ) |
| sOnlineVersion = info.version; |
| } |
| |
| rtl::OUString sVersionUser; |
| rtl::OUString sVersionShared; |
| rtl::OUString sVersionBundled; |
| uno::Sequence< uno::Reference< deployment::XPackage> > extensions; |
| try { |
| extensions = extMgr->getExtensionsWithSameIdentifier( |
| dp_misc::getIdentifier(info.extension), info.extension->getName(), |
| uno::Reference<css_ucb::XCommandEnvironment>()); |
| } catch (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); |
| |
| rtl::OUString updateVersionUser; |
| rtl::OUString updateVersionShared; |
| if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) |
| updateVersionUser = dp_misc::getHighestVersion( |
| rtl::OUString(), sVersionShared, sVersionBundled, sOnlineVersion); |
| if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) |
| updateVersionShared = dp_misc::getHighestVersion( |
| rtl::OUString(), rtl::OUString(), sVersionBundled, sOnlineVersion); |
| rtl::OUString updateVersion; |
| if (dp_misc::compareVersions(updateVersionUser, updateVersionShared) == dp_misc::GREATER) |
| updateVersion = updateVersionUser; |
| else |
| updateVersion = updateVersionShared; |
| if (updateVersion.getLength()) |
| { |
| |
| rtl::OUString aNewEntry[2]; |
| aNewEntry[0] = i->first; |
| aNewEntry[1] = updateVersion; |
| aList.realloc( ++nCount ); |
| aList[ nCount-1 ] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 ); |
| } |
| } |
| return aList; |
| } |
| |
| //------------------------------------------------------------------------------ |
| uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL PackageInformationProvider::getExtensionList() |
| throw ( uno::RuntimeException ) |
| { |
| const uno::Reference<deployment::XExtensionManager> mgr = |
| deployment::ExtensionManager::get(mxContext); |
| |
| if (!mgr.is()) |
| return uno::Sequence< uno::Sequence< rtl::OUString > >(); |
| |
| const uno::Sequence< uno::Sequence< uno::Reference<deployment::XPackage > > > |
| allExt = mgr->getAllExtensions( |
| uno::Reference< task::XAbortChannel >(), |
| uno::Reference< css_ucb::XCommandEnvironment > () ); |
| |
| uno::Sequence< uno::Sequence< rtl::OUString > > retList; |
| |
| sal_Int32 cAllIds = allExt.getLength(); |
| retList.realloc(cAllIds); |
| |
| for (sal_Int32 i = 0; i < cAllIds; i++) |
| { |
| //The inner sequence contains extensions with the same identifier from |
| //all the different repositories, that is user, share, bundled. |
| const uno::Sequence< uno::Reference< deployment::XPackage > > & |
| seqExtension = allExt[i]; |
| sal_Int32 cExt = seqExtension.getLength(); |
| OSL_ASSERT(cExt == 3); |
| for (sal_Int32 j = 0; j < cExt; j++) |
| { |
| //ToDo according to the old code the first found extenions is used |
| //even if another one with the same id has a better version. |
| uno::Reference< deployment::XPackage > const & xExtension( seqExtension[j] ); |
| if (xExtension.is()) |
| { |
| rtl::OUString aNewEntry[2]; |
| aNewEntry[0] = dp_misc::getIdentifier(xExtension); |
| aNewEntry[1] = xExtension->getVersion(); |
| retList[i] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 ); |
| break; |
| } |
| } |
| } |
| return retList; |
| } |
| |
| |
| //------------------------------------------------------------------------------ |
| //------------------------------------------------------------------------------ |
| //------------------------------------------------------------------------------ |
| |
| namespace sdecl = comphelper::service_decl; |
| sdecl::class_<PackageInformationProvider> servicePIP; |
| extern sdecl::ServiceDecl const serviceDecl( |
| servicePIP, |
| // a private one: |
| "com.sun.star.comp.deployment.PackageInformationProvider", |
| "com.sun.star.comp.deployment.PackageInformationProvider" ); |
| |
| //------------------------------------------------------------------------------ |
| bool singleton_entries( |
| uno::Reference< registry::XRegistryKey > const & xRegistryKey ) |
| { |
| try { |
| uno::Reference< registry::XRegistryKey > xKey( |
| xRegistryKey->createKey( |
| serviceDecl.getImplementationName() + |
| // xxx todo: use future generated function to get singleton name |
| UNISTRING("/UNO/SINGLETONS/" |
| "com.sun.star.deployment.PackageInformationProvider") ) ); |
| xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); |
| return true; |
| } |
| catch (registry::InvalidRegistryException & exc) { |
| (void) exc; // avoid warnings |
| OSL_ENSURE( 0, ::rtl::OUStringToOString( |
| exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); |
| return false; |
| } |
| } |
| |
| } // namespace dp_info |
| |
| |