1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_desktop.hxx" 30 31 #include <cppuhelper/implbase3.hxx> 32 33 #include "comphelper/servicedecl.hxx" 34 35 #include "com/sun/star/deployment/UpdateInformationProvider.hpp" 36 #include "com/sun/star/deployment/XPackage.hpp" 37 #include "com/sun/star/deployment/XPackageInformationProvider.hpp" 38 #include "com/sun/star/deployment/ExtensionManager.hpp" 39 #include "com/sun/star/deployment/XUpdateInformationProvider.hpp" 40 #include "com/sun/star/lang/XServiceInfo.hpp" 41 #include "com/sun/star/registry/XRegistryKey.hpp" 42 #include "com/sun/star/task/XAbortChannel.hpp" 43 #include "com/sun/star/uno/XComponentContext.hpp" 44 #include "com/sun/star/ucb/XCommandEnvironment.hpp" 45 #include "com/sun/star/xml/dom/XElement.hpp" 46 #include "com/sun/star/xml/dom/XNode.hpp" 47 48 #include "com/sun/star/uno/Reference.hxx" 49 #include "rtl/ustring.hxx" 50 #include "ucbhelper/content.hxx" 51 52 #include "dp_dependencies.hxx" 53 #include "dp_descriptioninfoset.hxx" 54 #include "dp_identifier.hxx" 55 #include "dp_version.hxx" 56 #include "dp_misc.h" 57 #include "dp_update.hxx" 58 59 namespace beans = com::sun::star::beans ; 60 namespace deployment = com::sun::star::deployment ; 61 namespace lang = com::sun::star::lang ; 62 namespace registry = com::sun::star::registry ; 63 namespace task = com::sun::star::task ; 64 namespace css_ucb = com::sun::star::ucb ; 65 namespace uno = com::sun::star::uno ; 66 namespace xml = com::sun::star::xml ; 67 68 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) 69 70 namespace dp_info { 71 72 class PackageInformationProvider : 73 public ::cppu::WeakImplHelper1< deployment::XPackageInformationProvider > 74 75 { 76 public: 77 PackageInformationProvider( uno::Reference< uno::XComponentContext >const& xContext); 78 virtual ~PackageInformationProvider(); 79 80 static uno::Sequence< rtl::OUString > getServiceNames(); 81 static rtl::OUString getImplName(); 82 83 // XPackageInformationProvider 84 virtual rtl::OUString SAL_CALL getPackageLocation( const rtl::OUString& extensionId ) 85 throw ( uno::RuntimeException ); 86 virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL isUpdateAvailable( const rtl::OUString& extensionId ) 87 throw ( uno::RuntimeException ); 88 virtual uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL getExtensionList() 89 throw ( uno::RuntimeException ); 90 //--------- 91 private: 92 93 uno::Reference< uno::XComponentContext> mxContext; 94 95 rtl::OUString getPackageLocation( const rtl::OUString& repository, 96 const rtl::OUString& _sExtensionId ); 97 98 uno::Reference< deployment::XUpdateInformationProvider > mxUpdateInformation; 99 }; 100 101 //------------------------------------------------------------------------------ 102 103 PackageInformationProvider::PackageInformationProvider( uno::Reference< uno::XComponentContext > const& xContext) : 104 mxContext( xContext ), 105 mxUpdateInformation( deployment::UpdateInformationProvider::create( xContext ) ) 106 { 107 } 108 109 //------------------------------------------------------------------------------ 110 111 PackageInformationProvider::~PackageInformationProvider() 112 { 113 } 114 115 //------------------------------------------------------------------------------ 116 rtl::OUString PackageInformationProvider::getPackageLocation( 117 const rtl::OUString & repository, 118 const rtl::OUString& _rExtensionId ) 119 { 120 rtl::OUString aLocationURL; 121 uno::Reference<deployment::XExtensionManager> xManager = 122 deployment::ExtensionManager::get(mxContext); 123 124 if ( xManager.is() ) 125 { 126 const uno::Sequence< uno::Reference< deployment::XPackage > > packages( 127 xManager->getDeployedExtensions( 128 repository, 129 uno::Reference< task::XAbortChannel >(), 130 uno::Reference< css_ucb::XCommandEnvironment > () ) ); 131 132 for ( int pos = packages.getLength(); pos--; ) 133 { 134 try 135 { 136 const rtl::OUString aName = packages[ pos ]->getName(); 137 const beans::Optional< rtl::OUString > aID = packages[ pos ]->getIdentifier(); 138 if ( aID.IsPresent && aID.Value.compareTo( _rExtensionId ) == 0 ) 139 { 140 aLocationURL = packages[ pos ]->getURL(); 141 break; 142 } 143 } 144 catch ( uno::RuntimeException & ) {} 145 } 146 } 147 148 return aLocationURL; 149 } 150 151 //------------------------------------------------------------------------------ 152 //------------------------------------------------------------------------------ 153 //------------------------------------------------------------------------------ 154 155 rtl::OUString SAL_CALL 156 PackageInformationProvider::getPackageLocation( const rtl::OUString& _sExtensionId ) 157 throw ( uno::RuntimeException ) 158 { 159 rtl::OUString aLocationURL = getPackageLocation( UNISTRING("user"), _sExtensionId ); 160 161 if ( aLocationURL.getLength() == 0 ) 162 { 163 aLocationURL = getPackageLocation( UNISTRING("shared"), _sExtensionId ); 164 } 165 if ( aLocationURL.getLength() == 0 ) 166 { 167 aLocationURL = getPackageLocation( UNISTRING("bundled"), _sExtensionId ); 168 } 169 if ( aLocationURL.getLength() ) 170 { 171 ::ucbhelper::Content aContent( aLocationURL, NULL ); 172 aLocationURL = aContent.getURL(); 173 } 174 return aLocationURL; 175 } 176 177 //------------------------------------------------------------------------------ 178 179 uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL 180 PackageInformationProvider::isUpdateAvailable( const rtl::OUString& _sExtensionId ) 181 throw ( uno::RuntimeException ) 182 { 183 uno::Sequence< uno::Sequence< rtl::OUString > > aList; 184 185 uno::Reference<deployment::XExtensionManager> extMgr = 186 deployment::ExtensionManager::get(mxContext); 187 188 if (!extMgr.is()) 189 { 190 OSL_ASSERT(0); 191 return aList; 192 } 193 std::vector<std::pair<uno::Reference<deployment::XPackage>, uno::Any > > errors; 194 dp_misc::UpdateInfoMap updateInfoMap; 195 if (_sExtensionId.getLength()) 196 { 197 std::vector<uno::Reference<deployment::XPackage> > vecExtensions; 198 uno::Reference<deployment::XPackage> extension; 199 try 200 { 201 extension = dp_misc::getExtensionWithHighestVersion( 202 extMgr->getExtensionsWithSameIdentifier( 203 _sExtensionId, _sExtensionId, uno::Reference<css_ucb::XCommandEnvironment>())); 204 vecExtensions.push_back(extension); 205 } 206 catch (lang::IllegalArgumentException &) 207 { 208 OSL_ASSERT(0); 209 } 210 updateInfoMap = dp_misc::getOnlineUpdateInfos( 211 mxContext, extMgr, mxUpdateInformation, &vecExtensions, errors); 212 } 213 else 214 { 215 updateInfoMap = dp_misc::getOnlineUpdateInfos( 216 mxContext, extMgr, mxUpdateInformation, NULL, errors); 217 } 218 219 int nCount = 0; 220 for (dp_misc::UpdateInfoMap::iterator i(updateInfoMap.begin()); i != updateInfoMap.end(); i++) 221 { 222 dp_misc::UpdateInfo const & info = i->second; 223 224 rtl::OUString sOnlineVersion; 225 if (info.info.is()) 226 { 227 // check, if there are unsatisfied dependencies and ignore this online update 228 dp_misc::DescriptionInfoset infoset(mxContext, info.info); 229 uno::Sequence< uno::Reference< xml::dom::XElement > > 230 ds( dp_misc::Dependencies::check( infoset ) ); 231 if ( ! ds.getLength() ) 232 sOnlineVersion = info.version; 233 } 234 235 rtl::OUString sVersionUser; 236 rtl::OUString sVersionShared; 237 rtl::OUString sVersionBundled; 238 uno::Sequence< uno::Reference< deployment::XPackage> > extensions; 239 try { 240 extensions = extMgr->getExtensionsWithSameIdentifier( 241 dp_misc::getIdentifier(info.extension), info.extension->getName(), 242 uno::Reference<css_ucb::XCommandEnvironment>()); 243 } catch (lang::IllegalArgumentException& ) { 244 OSL_ASSERT(0); 245 } 246 OSL_ASSERT(extensions.getLength() == 3); 247 if (extensions[0].is() ) 248 sVersionUser = extensions[0]->getVersion(); 249 if (extensions[1].is() ) 250 sVersionShared = extensions[1]->getVersion(); 251 if (extensions[2].is() ) 252 sVersionBundled = extensions[2]->getVersion(); 253 254 bool bSharedReadOnly = extMgr->isReadOnlyRepository(OUSTR("shared")); 255 256 dp_misc::UPDATE_SOURCE sourceUser = dp_misc::isUpdateUserExtension( 257 bSharedReadOnly, sVersionUser, sVersionShared, sVersionBundled, sOnlineVersion); 258 dp_misc::UPDATE_SOURCE sourceShared = dp_misc::isUpdateSharedExtension( 259 bSharedReadOnly, sVersionShared, sVersionBundled, sOnlineVersion); 260 261 rtl::OUString updateVersionUser; 262 rtl::OUString updateVersionShared; 263 if (sourceUser != dp_misc::UPDATE_SOURCE_NONE) 264 updateVersionUser = dp_misc::getHighestVersion( 265 rtl::OUString(), sVersionShared, sVersionBundled, sOnlineVersion); 266 if (sourceShared != dp_misc::UPDATE_SOURCE_NONE) 267 updateVersionShared = dp_misc::getHighestVersion( 268 rtl::OUString(), rtl::OUString(), sVersionBundled, sOnlineVersion); 269 rtl::OUString updateVersion; 270 if (dp_misc::compareVersions(updateVersionUser, updateVersionShared) == dp_misc::GREATER) 271 updateVersion = updateVersionUser; 272 else 273 updateVersion = updateVersionShared; 274 if (updateVersion.getLength()) 275 { 276 277 rtl::OUString aNewEntry[2]; 278 aNewEntry[0] = i->first; 279 aNewEntry[1] = updateVersion; 280 aList.realloc( ++nCount ); 281 aList[ nCount-1 ] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 ); 282 } 283 } 284 return aList; 285 } 286 287 //------------------------------------------------------------------------------ 288 uno::Sequence< uno::Sequence< rtl::OUString > > SAL_CALL PackageInformationProvider::getExtensionList() 289 throw ( uno::RuntimeException ) 290 { 291 const uno::Reference<deployment::XExtensionManager> mgr = 292 deployment::ExtensionManager::get(mxContext); 293 294 if (!mgr.is()) 295 return uno::Sequence< uno::Sequence< rtl::OUString > >(); 296 297 const uno::Sequence< uno::Sequence< uno::Reference<deployment::XPackage > > > 298 allExt = mgr->getAllExtensions( 299 uno::Reference< task::XAbortChannel >(), 300 uno::Reference< css_ucb::XCommandEnvironment > () ); 301 302 uno::Sequence< uno::Sequence< rtl::OUString > > retList; 303 304 sal_Int32 cAllIds = allExt.getLength(); 305 retList.realloc(cAllIds); 306 307 for (sal_Int32 i = 0; i < cAllIds; i++) 308 { 309 //The inner sequence contains extensions with the same identifier from 310 //all the different repositories, that is user, share, bundled. 311 const uno::Sequence< uno::Reference< deployment::XPackage > > & 312 seqExtension = allExt[i]; 313 sal_Int32 cExt = seqExtension.getLength(); 314 OSL_ASSERT(cExt == 3); 315 for (sal_Int32 j = 0; j < cExt; j++) 316 { 317 //ToDo according to the old code the first found extenions is used 318 //even if another one with the same id has a better version. 319 uno::Reference< deployment::XPackage > const & xExtension( seqExtension[j] ); 320 if (xExtension.is()) 321 { 322 rtl::OUString aNewEntry[2]; 323 aNewEntry[0] = dp_misc::getIdentifier(xExtension); 324 aNewEntry[1] = xExtension->getVersion(); 325 retList[i] = ::uno::Sequence< rtl::OUString >( aNewEntry, 2 ); 326 break; 327 } 328 } 329 } 330 return retList; 331 } 332 333 334 //------------------------------------------------------------------------------ 335 //------------------------------------------------------------------------------ 336 //------------------------------------------------------------------------------ 337 338 namespace sdecl = comphelper::service_decl; 339 sdecl::class_<PackageInformationProvider> servicePIP; 340 extern sdecl::ServiceDecl const serviceDecl( 341 servicePIP, 342 // a private one: 343 "com.sun.star.comp.deployment.PackageInformationProvider", 344 "com.sun.star.comp.deployment.PackageInformationProvider" ); 345 346 //------------------------------------------------------------------------------ 347 bool singleton_entries( 348 uno::Reference< registry::XRegistryKey > const & xRegistryKey ) 349 { 350 try { 351 uno::Reference< registry::XRegistryKey > xKey( 352 xRegistryKey->createKey( 353 serviceDecl.getImplementationName() + 354 // xxx todo: use future generated function to get singleton name 355 UNISTRING("/UNO/SINGLETONS/" 356 "com.sun.star.deployment.PackageInformationProvider") ) ); 357 xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); 358 return true; 359 } 360 catch (registry::InvalidRegistryException & exc) { 361 (void) exc; // avoid warnings 362 OSL_ENSURE( 0, ::rtl::OUStringToOString( 363 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); 364 return false; 365 } 366 } 367 368 } // namespace dp_info 369 370 371