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