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/implbase1.hxx> 28 29 #include "comphelper/servicedecl.hxx" 30 #include "cppuhelper/exc_hlp.hxx" 31 #include "rtl/bootstrap.hxx" 32 #include "com/sun/star/deployment/ExtensionManager.hpp" 33 #include "com/sun/star/deployment/XExtensionManager.hpp" 34 #include "com/sun/star/deployment/thePackageManagerFactory.hpp" 35 #include "com/sun/star/deployment/XPackageManager.hpp" 36 #include "com/sun/star/deployment/XPackageManagerFactory.hpp" 37 #include "com/sun/star/deployment/XPackage.hpp" 38 #include "com/sun/star/deployment/InstallException.hpp" 39 #include "com/sun/star/deployment/VersionException.hpp" 40 #include "com/sun/star/deployment/LicenseException.hpp" 41 #include "com/sun/star/lang/XServiceInfo.hpp" 42 #include "com/sun/star/registry/XRegistryKey.hpp" 43 #include "com/sun/star/beans/Optional.hpp" 44 #include "com/sun/star/task/XInteractionApprove.hpp" 45 #include "com/sun/star/beans/Ambiguous.hpp" 46 #include "com/sun/star/uno/XComponentContext.hpp" 47 #include "com/sun/star/io/XInputStream.hpp" 48 #include "com/sun/star/util/XModifyBroadcaster.hpp" 49 #include "comphelper/sequence.hxx" 50 #include "xmlscript/xml_helper.hxx" 51 #include "osl/diagnose.h" 52 #include "dp_interact.h" 53 #include "dp_resource.h" 54 #include "dp_ucb.h" 55 #include "dp_identifier.hxx" 56 #include "dp_descriptioninfoset.hxx" 57 #include "dp_extensionmanager.hxx" 58 #include "dp_commandenvironments.hxx" 59 #include "dp_properties.hxx" 60 #include "boost/bind.hpp" 61 62 #include <list> 63 #include <hash_map> 64 #include <algorithm> 65 66 namespace deploy = com::sun::star::deployment; 67 namespace lang = com::sun::star::lang; 68 namespace registry = com::sun::star::registry; 69 namespace task = com::sun::star::task; 70 namespace ucb = com::sun::star::ucb; 71 namespace uno = com::sun::star::uno; 72 namespace beans = com::sun::star::beans; 73 namespace util = com::sun::star::util; 74 namespace css = com::sun::star; 75 76 77 //#define OUSTR(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) 78 79 using ::com::sun::star::uno::Reference; 80 using ::rtl::OUString; 81 82 namespace { 83 84 struct CompIdentifiers 85 { 86 bool operator() (::std::vector<Reference<deploy::XPackage> > const & a, 87 ::std::vector<Reference<deploy::XPackage> > const & b) 88 { 89 90 if (getName(a).compareTo(getName(b)) < 0) 91 return true; 92 return false; 93 } 94 95 OUString getName(::std::vector<Reference<deploy::XPackage> > const & a); 96 }; 97 98 OUString CompIdentifiers::getName(::std::vector<Reference<deploy::XPackage> > const & a) 99 { 100 OSL_ASSERT(a.size() == 3); 101 //get the first non-null reference 102 Reference<deploy::XPackage> extension; 103 ::std::vector<Reference<deploy::XPackage> >::const_iterator it = a.begin(); 104 for (; it != a.end(); it++) 105 { 106 if (it->is()) 107 { 108 extension = *it; 109 break; 110 } 111 } 112 OSL_ASSERT(extension.is()); 113 return extension->getDisplayName(); 114 } 115 116 void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const & xCmdEnv) 117 { 118 //Write the lastmodified file 119 try { 120 ::rtl::Bootstrap::expandMacros(url); 121 ::ucbhelper::Content ucbStamp(url, xCmdEnv ); 122 dp_misc::erase_path( url, xCmdEnv ); 123 ::rtl::OString stamp("1" ); 124 Reference<css::io::XInputStream> xData( 125 ::xmlscript::createInputStream( 126 ::rtl::ByteSequence( 127 reinterpret_cast<sal_Int8 const *>(stamp.getStr()), 128 stamp.getLength() ) ) ); 129 ucbStamp.writeStream( xData, true /* replace existing */ ); 130 } 131 catch(...) 132 { 133 uno::Any exc(::cppu::getCaughtException()); 134 throw deploy::DeploymentException( 135 OUSTR("Failed to update") + url, 0, exc); 136 } 137 } 138 139 class ExtensionRemoveGuard 140 { 141 css::uno::Reference<css::deployment::XPackage> m_extension; 142 css::uno::Reference<css::deployment::XPackageManager> m_xPackageManager; 143 144 public: 145 ExtensionRemoveGuard(){}; 146 ExtensionRemoveGuard( 147 css::uno::Reference<css::deployment::XPackage> const & extension, 148 css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager): 149 m_extension(extension), m_xPackageManager(xPackageManager) {} 150 ~ExtensionRemoveGuard(); 151 152 void set(css::uno::Reference<css::deployment::XPackage> const & extension, 153 css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager) { 154 m_extension = extension; 155 m_xPackageManager = xPackageManager; 156 } 157 }; 158 159 ExtensionRemoveGuard::~ExtensionRemoveGuard() 160 { 161 try { 162 OSL_ASSERT(!(m_extension.is() && !m_xPackageManager.is())); 163 if (m_xPackageManager.is() && m_extension.is()) 164 m_xPackageManager->removePackage( 165 dp_misc::getIdentifier(m_extension), ::rtl::OUString(), 166 css::uno::Reference<css::task::XAbortChannel>(), 167 css::uno::Reference<css::ucb::XCommandEnvironment>()); 168 } catch (...) { 169 OSL_ASSERT(0); 170 } 171 } 172 173 } //end namespace 174 175 namespace dp_manager { 176 177 178 179 //------------------------------------------------------------------------------ 180 181 //ToDo: bundled extension 182 ExtensionManager::ExtensionManager( Reference< uno::XComponentContext > const& xContext) : 183 ::cppu::WeakComponentImplHelper1< css::deployment::XExtensionManager >(getMutex()), 184 m_xContext( xContext ) 185 { 186 m_xPackageManagerFactory = deploy::thePackageManagerFactory::get(m_xContext); 187 OSL_ASSERT(m_xPackageManagerFactory.is()); 188 189 m_repositoryNames.push_back(OUSTR("user")); 190 m_repositoryNames.push_back(OUSTR("shared")); 191 m_repositoryNames.push_back(OUSTR("bundled")); 192 } 193 194 //------------------------------------------------------------------------------ 195 196 ExtensionManager::~ExtensionManager() 197 { 198 } 199 200 Reference<deploy::XPackageManager> ExtensionManager::getUserRepository() 201 { 202 return m_xPackageManagerFactory->getPackageManager(OUSTR("user")); 203 } 204 Reference<deploy::XPackageManager> ExtensionManager::getSharedRepository() 205 { 206 return m_xPackageManagerFactory->getPackageManager(OUSTR("shared")); 207 } 208 Reference<deploy::XPackageManager> ExtensionManager::getBundledRepository() 209 { 210 return m_xPackageManagerFactory->getPackageManager(OUSTR("bundled")); 211 } 212 Reference<deploy::XPackageManager> ExtensionManager::getTmpRepository() 213 { 214 return m_xPackageManagerFactory->getPackageManager(OUSTR("tmp")); 215 } 216 Reference<deploy::XPackageManager> ExtensionManager::getBakRepository() 217 { 218 return m_xPackageManagerFactory->getPackageManager(OUSTR("bak")); 219 } 220 221 Reference<task::XAbortChannel> ExtensionManager::createAbortChannel() 222 throw (uno::RuntimeException) 223 { 224 return new dp_misc::AbortChannel; 225 } 226 227 css::uno::Reference<css::deployment::XPackageManager> 228 ExtensionManager::getPackageManager(::rtl::OUString const & repository) 229 throw (css::lang::IllegalArgumentException) 230 { 231 Reference<deploy::XPackageManager> xPackageManager; 232 if (repository.equals(OUSTR("user"))) 233 xPackageManager = getUserRepository(); 234 else if (repository.equals(OUSTR("shared"))) 235 xPackageManager = getSharedRepository(); 236 else if (repository.equals(OUSTR("bundled"))) 237 xPackageManager = getBundledRepository(); 238 else if (repository.equals(OUSTR("tmp"))) 239 xPackageManager = getTmpRepository(); 240 else if (repository.equals(OUSTR("bak"))) 241 xPackageManager = getBakRepository(); 242 else if (repository.equals(OUSTR("bundled_prereg"))) 243 xPackageManager = m_xPackageManagerFactory->getPackageManager(repository); 244 else 245 throw lang::IllegalArgumentException( 246 OUSTR("No valid repository name provided."), 247 static_cast<cppu::OWeakObject*>(this), 0); 248 return xPackageManager; 249 } 250 251 252 /* 253 Enters the XPackage objects into a map. They must be all from the 254 same repository. The value type of the map is a vector, where each vector 255 represents an extension with a particular identifier. The first member 256 is represents the user extension, the second the shared extension and the 257 third the bundled extension. 258 */ 259 void ExtensionManager::addExtensionsToMap( 260 id2extensions & mapExt, 261 uno::Sequence<Reference<deploy::XPackage> > const & seqExt, 262 OUString const & repository) 263 { 264 //Determine the index in the vector where these extensions are to be 265 //added. 266 ::std::list<OUString>::const_iterator citNames = 267 m_repositoryNames.begin(); 268 int index = 0; 269 for (;citNames != m_repositoryNames.end(); citNames++, index++) 270 { 271 if (citNames->equals(repository)) 272 break; 273 } 274 275 for (int i = 0; i < seqExt.getLength(); i++) 276 { 277 Reference<deploy::XPackage> const & xExtension = seqExt[i]; 278 OUString id = dp_misc::getIdentifier(xExtension); 279 id2extensions::iterator ivec = mapExt.find(id); 280 if (ivec == mapExt.end()) 281 { 282 ::std::vector<Reference<deploy::XPackage> > vec(3); 283 vec[index] = xExtension; 284 mapExt[id] = vec; 285 } 286 else 287 { 288 ivec->second[index] = xExtension; 289 } 290 } 291 } 292 293 /* 294 returns a list containing extensions with the same identifier from 295 all repositories (user, shared, bundled) If one repository does not 296 have this extension, then the list contains an empty Referenc. The list 297 is ordered according to the priority of the repostories: 298 1. user 299 2. shared 300 3. bundled 301 302 The number of elements is always three, unless the number of repository 303 changes. 304 */ 305 ::std::list<Reference<deploy::XPackage> > 306 ExtensionManager::getExtensionsWithSameId( 307 OUString const & identifier, OUString const & fileName, 308 Reference< ucb::XCommandEnvironment> const & /*xCmdEnv*/) 309 310 { 311 ::std::list<Reference<deploy::XPackage> > extensionList; 312 try 313 { //will throw an exception if the extension does not exist 314 extensionList.push_back(getUserRepository()->getDeployedPackage( 315 identifier, fileName, Reference<ucb::XCommandEnvironment>())); 316 } catch(lang::IllegalArgumentException &) 317 { 318 extensionList.push_back(Reference<deploy::XPackage>()); 319 } 320 try 321 { 322 extensionList.push_back(getSharedRepository()->getDeployedPackage( 323 identifier, fileName, Reference<ucb::XCommandEnvironment>())); 324 } catch (lang::IllegalArgumentException &) 325 { 326 extensionList.push_back(Reference<deploy::XPackage>()); 327 } 328 try 329 { 330 extensionList.push_back(getBundledRepository()->getDeployedPackage( 331 identifier, fileName, Reference<ucb::XCommandEnvironment>())); 332 } catch (lang::IllegalArgumentException &) 333 { 334 extensionList.push_back(Reference<deploy::XPackage>()); 335 } 336 OSL_ASSERT(extensionList.size() == 3); 337 return extensionList; 338 } 339 340 uno::Sequence<Reference<deploy::XPackage> > 341 ExtensionManager::getExtensionsWithSameIdentifier( 342 OUString const & identifier, 343 OUString const & fileName, 344 Reference< ucb::XCommandEnvironment> const & xCmdEnv ) 345 throw ( 346 deploy::DeploymentException, 347 ucb::CommandFailedException, 348 lang::IllegalArgumentException, 349 uno::RuntimeException) 350 { 351 try 352 { 353 ::std::list<Reference<deploy::XPackage> > listExtensions = 354 getExtensionsWithSameId( 355 identifier, fileName, xCmdEnv); 356 sal_Bool bHasExtension = false; 357 358 //throw an IllegalArgumentException if there is no extension at all. 359 typedef ::std::list<Reference<deploy::XPackage> >::const_iterator CIT; 360 for (CIT i = listExtensions.begin(); i != listExtensions.end(); i++) 361 bHasExtension |= i->is(); 362 if (!bHasExtension) 363 throw lang::IllegalArgumentException( 364 OUSTR("Could not find extension: ") + identifier + OUSTR(", ") + fileName, 365 static_cast<cppu::OWeakObject*>(this), -1); 366 367 return comphelper::containerToSequence< 368 Reference<deploy::XPackage>, 369 ::std::list<Reference<deploy::XPackage> > 370 > (listExtensions); 371 } 372 catch (deploy::DeploymentException & ) 373 { 374 throw; 375 } 376 catch ( ucb::CommandFailedException & ) 377 { 378 throw; 379 } 380 catch (lang::IllegalArgumentException &) 381 { 382 throw; 383 } 384 catch (...) 385 { 386 uno::Any exc = ::cppu::getCaughtException(); 387 throw deploy::DeploymentException( 388 OUSTR("Extension Manager: exception during getExtensionsWithSameIdentifier"), 389 static_cast<OWeakObject*>(this), exc); 390 } 391 } 392 393 394 395 bool ExtensionManager::isUserDisabled( 396 OUString const & identifier, OUString const & fileName) 397 { 398 ::std::list<Reference<deploy::XPackage> > listExtensions; 399 400 try { 401 listExtensions = getExtensionsWithSameId(identifier, fileName); 402 } catch (lang::IllegalArgumentException & ) { 403 } 404 OSL_ASSERT(listExtensions.size() == 3); 405 406 return isUserDisabled( ::comphelper::containerToSequence< 407 Reference<deploy::XPackage>, 408 ::std::list<Reference<deploy::XPackage> > 409 > (listExtensions)); 410 } 411 412 bool ExtensionManager::isUserDisabled( 413 uno::Sequence<Reference<deploy::XPackage> > const & seqExtSameId) 414 { 415 OSL_ASSERT(seqExtSameId.getLength() == 3); 416 Reference<deploy::XPackage> const & userExtension = seqExtSameId[0]; 417 if (userExtension.is()) 418 { 419 beans::Optional<beans::Ambiguous<sal_Bool> > reg = 420 userExtension->isRegistered(Reference<task::XAbortChannel>(), 421 Reference<ucb::XCommandEnvironment>()); 422 //If the value is ambiguous is than we assume that the extension 423 //is enabled, but something went wrong during enabling. We do not 424 //automatically disable user extensions. 425 if (reg.IsPresent && 426 ! reg.Value.IsAmbiguous && ! reg.Value.Value) 427 return true; 428 } 429 return false; 430 } 431 432 /* 433 This method determines the active extension (XPackage.registerPackage) with a 434 particular identifier. 435 436 The parameter bUserDisabled determines if the user extension is disabled. 437 438 When the user repository contains an extension with the given identifier and 439 it is not disabled by the user, then it is always registered. Otherwise an 440 extension is only registered when there is no registered extension in one of 441 the repositories with a higher priority. That is, if the extension is from 442 the shared repository and an active extension with the same identifer is in 443 the user repository, then the extension is not registered. Similarly a 444 bundled extension is not registered if there is an active extension with the 445 same identifier in the shared or user repository. 446 */ 447 void ExtensionManager::activateExtension( 448 OUString const & identifier, OUString const & fileName, 449 bool bUserDisabled, 450 bool bStartup, 451 Reference<task::XAbortChannel> const & xAbortChannel, 452 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 453 { 454 ::std::list<Reference<deploy::XPackage> > listExtensions; 455 try { 456 listExtensions = getExtensionsWithSameId(identifier, fileName); 457 } catch (lang::IllegalArgumentException &) { 458 } 459 OSL_ASSERT(listExtensions.size() == 3); 460 461 activateExtension( 462 ::comphelper::containerToSequence< 463 Reference<deploy::XPackage>, 464 ::std::list<Reference<deploy::XPackage> > 465 > (listExtensions), 466 bUserDisabled, bStartup, xAbortChannel, xCmdEnv); 467 468 fireModified(); 469 } 470 471 void ExtensionManager::activateExtension( 472 uno::Sequence<Reference<deploy::XPackage> > const & seqExt, 473 bool bUserDisabled, 474 bool bStartup, 475 Reference<task::XAbortChannel> const & xAbortChannel, 476 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 477 { 478 bool bActive = false; 479 sal_Int32 len = seqExt.getLength(); 480 for (sal_Int32 i = 0; i < len; i++) 481 { 482 Reference<deploy::XPackage> const & aExt = seqExt[i]; 483 if (aExt.is()) 484 { 485 //get the registration value of the current iteration 486 beans::Optional<beans::Ambiguous<sal_Bool> > optReg = 487 aExt->isRegistered(xAbortChannel, xCmdEnv); 488 //If nothing can be registered then break 489 if (!optReg.IsPresent) 490 break; 491 492 //Check if this is a disabled user extension, 493 if (i == 0 && bUserDisabled) 494 { 495 aExt->revokePackage(xAbortChannel, xCmdEnv); 496 continue; 497 } 498 499 //If we have already determined an active extension then we must 500 //make sure to unregister all extensions with the same id in 501 //repositories with a lower priority 502 if (bActive) 503 { 504 aExt->revokePackage(xAbortChannel, xCmdEnv); 505 } 506 else 507 { 508 //This is the first extension in the ordered list, which becomes 509 //the active extension 510 bActive = true; 511 //Register if not already done. 512 //reregister if the value is ambiguous, which indicates that 513 //something went wrong during last registration. 514 aExt->registerPackage(bStartup, xAbortChannel, xCmdEnv); 515 } 516 } 517 } 518 } 519 520 Reference<deploy::XPackage> ExtensionManager::backupExtension( 521 OUString const & identifier, OUString const & fileName, 522 Reference<deploy::XPackageManager> const & xPackageManager, 523 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 524 { 525 Reference<deploy::XPackage> xBackup; 526 Reference<ucb::XCommandEnvironment> tmpCmdEnv( 527 new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); 528 Reference<deploy::XPackage> xOldExtension; 529 xOldExtension = xPackageManager->getDeployedPackage( 530 identifier, fileName, tmpCmdEnv); 531 532 if (xOldExtension.is()) 533 { 534 xBackup = getTmpRepository()->addPackage( 535 xOldExtension->getURL(), uno::Sequence<beans::NamedValue>(), 536 OUString(), Reference<task::XAbortChannel>(), tmpCmdEnv); 537 538 OSL_ENSURE(xBackup.is(), "Failed to backup extension"); 539 } 540 return xBackup; 541 } 542 543 //The supported package types are actually determined by the registry. However 544 //creating a registry 545 //(desktop/source/deployment/registry/dp_registry.cxx:PackageRegistryImpl) will 546 //create all the backends, so that the registry can obtain from them the package 547 //types. Creating the registry will also set up the registry folder containing 548 //all the subfolders for the respective backends. 549 //Because all repositories support the same backends, we can just delegate this 550 //call to one of the repositories. 551 uno::Sequence< Reference<deploy::XPackageTypeInfo> > 552 ExtensionManager::getSupportedPackageTypes() 553 throw (uno::RuntimeException) 554 { 555 return getUserRepository()->getSupportedPackageTypes(); 556 } 557 //Do some necessary checks and user interaction. This function does not 558 //aquire the extension manager mutex and that mutex must not be aquired 559 //when this function is called. doChecksForAddExtension does synchronous 560 //user interactions which may require aquiring the solar mutex. 561 //Returns true if the extension can be installed. 562 bool ExtensionManager::doChecksForAddExtension( 563 Reference<deploy::XPackageManager> const & xPackageMgr, 564 uno::Sequence<beans::NamedValue> const & properties, 565 css::uno::Reference<css::deployment::XPackage> const & xTmpExtension, 566 Reference<task::XAbortChannel> const & xAbortChannel, 567 Reference<ucb::XCommandEnvironment> const & xCmdEnv, 568 Reference<deploy::XPackage> & out_existingExtension ) 569 throw (deploy::DeploymentException, 570 ucb::CommandFailedException, 571 ucb::CommandAbortedException, 572 lang::IllegalArgumentException, 573 uno::RuntimeException) 574 { 575 try 576 { 577 Reference<deploy::XPackage> xOldExtension; 578 const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension); 579 const OUString sFileName = xTmpExtension->getName(); 580 const OUString sDisplayName = xTmpExtension->getDisplayName(); 581 const OUString sVersion = xTmpExtension->getVersion(); 582 583 try 584 { 585 xOldExtension = xPackageMgr->getDeployedPackage( 586 sIdentifier, sFileName, xCmdEnv); 587 out_existingExtension = xOldExtension; 588 } 589 catch (lang::IllegalArgumentException &) 590 { 591 } 592 bool bCanInstall = false; 593 594 //This part is not guarded against other threads removing, adding, disabling ... 595 //etc. the same extension. 596 //checkInstall is safe because it notifies the user if the extension is not yet 597 //installed in the same repository. Because addExtension has its own guard 598 //(m_addMutex), another thread cannot add the extension in the meantime. 599 //checkUpdate is called if the same extension exists in the same 600 //repository. The user is asked if they want to replace it. Another 601 //thread 602 //could already remove the extension. So asking the user was not 603 //necessary. No harm is done. The other thread may also ask the user 604 //if he wants to remove the extension. This depends on the 605 //XCommandEnvironment which it passes to removeExtension. 606 if (xOldExtension.is()) 607 { 608 //throws a CommandFailedException if the user cancels 609 //the action. 610 checkUpdate(sVersion, sDisplayName,xOldExtension, xCmdEnv); 611 } 612 else 613 { 614 //throws a CommandFailedException if the user cancels 615 //the action. 616 checkInstall(sDisplayName, xCmdEnv); 617 } 618 //Prevent showing the license if requested. 619 Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv); 620 ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>()); 621 622 dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL())); 623 const ::boost::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes = 624 info.getSimpleLicenseAttributes(); 625 626 if (licenseAttributes && licenseAttributes->suppressIfRequired 627 && props.isSuppressedLicense()) 628 _xCmdEnv = Reference<ucb::XCommandEnvironment>( 629 new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler())); 630 631 bCanInstall = xTmpExtension->checkPrerequisites( 632 xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0 ? true : false; 633 634 return bCanInstall; 635 } 636 catch (deploy::DeploymentException& ) { 637 throw; 638 } catch (ucb::CommandFailedException & ) { 639 throw; 640 } catch (ucb::CommandAbortedException & ) { 641 throw; 642 } catch (lang::IllegalArgumentException &) { 643 throw; 644 } catch (uno::RuntimeException &) { 645 throw; 646 } catch (uno::Exception &) { 647 uno::Any excOccurred = ::cppu::getCaughtException(); 648 deploy::DeploymentException exc( 649 OUSTR("Extension Manager: exception in doChecksForAddExtension"), 650 static_cast<OWeakObject*>(this), excOccurred); 651 throw exc; 652 } catch (...) { 653 throw uno::RuntimeException( 654 OUSTR("Extension Manager: unexpected exception in doChecksForAddExtension"), 655 static_cast<OWeakObject*>(this)); 656 } 657 } 658 659 // Only add to shared and user repository 660 Reference<deploy::XPackage> ExtensionManager::addExtension( 661 OUString const & url, uno::Sequence<beans::NamedValue> const & properties, 662 OUString const & repository, 663 Reference<task::XAbortChannel> const & xAbortChannel, 664 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 665 throw (deploy::DeploymentException, 666 ucb::CommandFailedException, 667 ucb::CommandAbortedException, 668 lang::IllegalArgumentException, 669 uno::RuntimeException) 670 { 671 Reference<deploy::XPackage> xNewExtension; 672 //Determine the repository to use 673 Reference<deploy::XPackageManager> xPackageManager; 674 if (repository.equals(OUSTR("user"))) 675 xPackageManager = getUserRepository(); 676 else if (repository.equals(OUSTR("shared"))) 677 xPackageManager = getSharedRepository(); 678 else 679 throw lang::IllegalArgumentException( 680 OUSTR("No valid repository name provided."), 681 static_cast<cppu::OWeakObject*>(this), 0); 682 //We must make sure that the xTmpExtension is not create twice, because this 683 //would remove the first one. 684 ::osl::MutexGuard addGuard(m_addMutex); 685 686 Reference<deploy::XPackage> xTmpExtension = 687 getTempExtension(url, xAbortChannel, xCmdEnv); 688 //Make sure the extension is removed from the tmp repository in case 689 //of an exception 690 ExtensionRemoveGuard tmpExtensionRemoveGuard(xTmpExtension, getTmpRepository()); 691 ExtensionRemoveGuard bakExtensionRemoveGuard; 692 const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension); 693 const OUString sFileName = xTmpExtension->getName(); 694 Reference<deploy::XPackage> xOldExtension; 695 Reference<deploy::XPackage> xExtensionBackup; 696 697 uno::Any excOccurred2; 698 bool bUserDisabled = false; 699 bool bCanInstall = doChecksForAddExtension( 700 xPackageManager, 701 properties, 702 xTmpExtension, 703 xAbortChannel, 704 xCmdEnv, 705 xOldExtension ); 706 707 { 708 // In this garded section (getMutex) we must not use the argument xCmdEnv 709 // because it may bring up dialogs (XInteractionHandler::handle) this 710 //may potententially deadlock. See issue 711 //http://qa.openoffice.org/issues/show_bug.cgi?id=114933 712 //By not providing xCmdEnv the underlying APIs will throw an exception if 713 //the XInteractionRequest cannot be handled 714 ::osl::MutexGuard guard(getMutex()); 715 716 if (bCanInstall) 717 { 718 try 719 { 720 bUserDisabled = isUserDisabled(sIdentifier, sFileName); 721 if (xOldExtension.is()) 722 { 723 try 724 { 725 xOldExtension->revokePackage( 726 xAbortChannel, Reference<ucb::XCommandEnvironment>()); 727 //save the old user extension in case the user aborts 728 xExtensionBackup = getBakRepository()->importExtension( 729 xOldExtension, Reference<task::XAbortChannel>(), 730 Reference<ucb::XCommandEnvironment>()); 731 bakExtensionRemoveGuard.set(xExtensionBackup, getBakRepository()); 732 } 733 catch (lang::DisposedException &) 734 { 735 //Another thread might have removed the extension meanwhile 736 } 737 } 738 //check again dependencies but prevent user interaction, 739 //We can disregard the license, because the user must have already 740 //accepted it, whe we called checkPrerequisites the first time 741 SilentCheckPrerequisitesCommandEnv * pSilentCommandEnv = 742 new SilentCheckPrerequisitesCommandEnv(); 743 Reference<ucb::XCommandEnvironment> silentCommandEnv(pSilentCommandEnv); 744 745 sal_Int32 failedPrereq = xTmpExtension->checkPrerequisites( 746 xAbortChannel, silentCommandEnv, true); 747 if (failedPrereq == 0) 748 { 749 xNewExtension = xPackageManager->addPackage( 750 url, properties, OUString(), xAbortChannel, 751 Reference<ucb::XCommandEnvironment>()); 752 //If we add a user extension and there is already one which was 753 //disabled by a user, then the newly installed one is enabled. If we 754 //add to another repository then the user extension remains 755 //disabled. 756 bool bUserDisabled2 = bUserDisabled; 757 if (repository.equals(OUSTR("user"))) 758 bUserDisabled2 = false; 759 760 ::rtl::OUString const name(xNewExtension->getName()); 761 activateExtension( 762 dp_misc::getIdentifier(xNewExtension), 763 name, bUserDisabled2, false, xAbortChannel, 764 Reference<ucb::XCommandEnvironment>()); 765 } 766 else 767 { 768 if (pSilentCommandEnv->m_Exception.hasValue()) 769 ::cppu::throwException(pSilentCommandEnv->m_Exception); 770 else if ( pSilentCommandEnv->m_UnknownException.hasValue()) 771 ::cppu::throwException(pSilentCommandEnv->m_UnknownException); 772 else 773 throw deploy::DeploymentException ( 774 OUSTR("Extension Manager: exception during addExtension, ckeckPrerequisites failed"), 775 static_cast<OWeakObject*>(this), uno::Any()); 776 } 777 } 778 catch (deploy::DeploymentException& ) { 779 excOccurred2 = ::cppu::getCaughtException(); 780 } catch (ucb::CommandFailedException & ) { 781 excOccurred2 = ::cppu::getCaughtException(); 782 } catch (ucb::CommandAbortedException & ) { 783 excOccurred2 = ::cppu::getCaughtException(); 784 } catch (lang::IllegalArgumentException &) { 785 excOccurred2 = ::cppu::getCaughtException(); 786 } catch (uno::RuntimeException &) { 787 excOccurred2 = ::cppu::getCaughtException(); 788 } catch (...) { 789 excOccurred2 = ::cppu::getCaughtException(); 790 deploy::DeploymentException exc( 791 OUSTR("Extension Manager: exception during addExtension, url: ") 792 + url, static_cast<OWeakObject*>(this), excOccurred2); 793 excOccurred2 <<= exc; 794 } 795 } 796 797 if (excOccurred2.hasValue()) 798 { 799 //It does not matter what exception is thrown. We try to 800 //recover the original status. 801 //If the user aborted installation then a ucb::CommandAbortedException 802 //is thrown. 803 //Use a private AbortChannel so the user cannot interrupt. 804 try 805 { 806 if (xExtensionBackup.is()) 807 { 808 Reference<deploy::XPackage> xRestored = 809 xPackageManager->importExtension( 810 xExtensionBackup, Reference<task::XAbortChannel>(), 811 Reference<ucb::XCommandEnvironment>()); 812 } 813 activateExtension( 814 sIdentifier, sFileName, bUserDisabled, false, 815 Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>()); 816 } 817 catch (...) 818 { 819 } 820 ::cppu::throwException(excOccurred2); 821 } 822 } // leaving the garded section (getMutex()) 823 824 try 825 { 826 fireModified(); 827 828 }catch (deploy::DeploymentException& ) { 829 throw; 830 } catch (ucb::CommandFailedException & ) { 831 throw; 832 } catch (ucb::CommandAbortedException & ) { 833 throw; 834 } catch (lang::IllegalArgumentException &) { 835 throw; 836 } catch (uno::RuntimeException &) { 837 throw; 838 } catch (uno::Exception &) { 839 uno::Any excOccurred = ::cppu::getCaughtException(); 840 deploy::DeploymentException exc( 841 OUSTR("Extension Manager: exception in doChecksForAddExtension"), 842 static_cast<OWeakObject*>(this), excOccurred); 843 throw exc; 844 } catch (...) { 845 throw uno::RuntimeException( 846 OUSTR("Extension Manager: unexpected exception in doChecksForAddExtension"), 847 static_cast<OWeakObject*>(this)); 848 } 849 850 return xNewExtension; 851 } 852 853 void ExtensionManager::removeExtension( 854 OUString const & identifier, OUString const & fileName, 855 OUString const & repository, 856 Reference<task::XAbortChannel> const & xAbortChannel, 857 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 858 throw (deploy::DeploymentException, 859 ucb::CommandFailedException, 860 ucb::CommandAbortedException, 861 lang::IllegalArgumentException, 862 uno::RuntimeException) 863 { 864 uno::Any excOccurred1; 865 Reference<deploy::XPackage> xExtensionBackup; 866 Reference<deploy::XPackageManager> xPackageManager; 867 bool bUserDisabled = false; 868 ::osl::MutexGuard guard(getMutex()); 869 try 870 { 871 //Determine the repository to use 872 if (repository.equals(OUSTR("user"))) 873 xPackageManager = getUserRepository(); 874 else if (repository.equals(OUSTR("shared"))) 875 xPackageManager = getSharedRepository(); 876 else 877 throw lang::IllegalArgumentException( 878 OUSTR("No valid repository name provided."), 879 static_cast<cppu::OWeakObject*>(this), 0); 880 881 bUserDisabled = isUserDisabled(identifier, fileName); 882 //Backup the extension, in case the user cancels the action 883 xExtensionBackup = backupExtension( 884 identifier, fileName, xPackageManager, xCmdEnv); 885 886 //revoke the extension if it is active 887 Reference<deploy::XPackage> xOldExtension = 888 xPackageManager->getDeployedPackage( 889 identifier, fileName, xCmdEnv); 890 xOldExtension->revokePackage(xAbortChannel, xCmdEnv); 891 892 xPackageManager->removePackage( 893 identifier, fileName, xAbortChannel, xCmdEnv); 894 activateExtension(identifier, fileName, bUserDisabled, false, 895 xAbortChannel, xCmdEnv); 896 fireModified(); 897 } 898 catch (deploy::DeploymentException& ) { 899 excOccurred1 = ::cppu::getCaughtException(); 900 } catch (ucb::CommandFailedException & ) { 901 excOccurred1 = ::cppu::getCaughtException(); 902 } catch (ucb::CommandAbortedException & ) { 903 excOccurred1 = ::cppu::getCaughtException(); 904 } catch (lang::IllegalArgumentException &) { 905 excOccurred1 = ::cppu::getCaughtException(); 906 } catch (uno::RuntimeException &) { 907 excOccurred1 = ::cppu::getCaughtException(); 908 } catch (...) { 909 excOccurred1 = ::cppu::getCaughtException(); 910 deploy::DeploymentException exc( 911 OUSTR("Extension Manager: exception during removeEtension"), 912 static_cast<OWeakObject*>(this), excOccurred1); 913 excOccurred1 <<= exc; 914 } 915 916 if (excOccurred1.hasValue()) 917 { 918 //User aborted installation, restore the previous situation. 919 //Use a private AbortChannel so the user cannot interrupt. 920 try 921 { 922 Reference<ucb::XCommandEnvironment> tmpCmdEnv( 923 new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler())); 924 if (xExtensionBackup.is()) 925 { 926 Reference<deploy::XPackage> xRestored = 927 xPackageManager->importExtension( 928 xExtensionBackup, Reference<task::XAbortChannel>(), 929 tmpCmdEnv); 930 activateExtension( 931 identifier, fileName, bUserDisabled, false, 932 Reference<task::XAbortChannel>(), 933 tmpCmdEnv); 934 935 getTmpRepository()->removePackage( 936 dp_misc::getIdentifier(xExtensionBackup), 937 xExtensionBackup->getName(), xAbortChannel, xCmdEnv); 938 fireModified(); 939 } 940 } 941 catch (...) 942 { 943 } 944 ::cppu::throwException(excOccurred1); 945 } 946 947 if (xExtensionBackup.is()) 948 getTmpRepository()->removePackage( 949 dp_misc::getIdentifier(xExtensionBackup), 950 xExtensionBackup->getName(), xAbortChannel, xCmdEnv); 951 } 952 953 // Only enable extensions from shared and user repository 954 void ExtensionManager::enableExtension( 955 Reference<deploy::XPackage> const & extension, 956 Reference<task::XAbortChannel> const & xAbortChannel, 957 Reference<ucb::XCommandEnvironment> const & xCmdEnv) 958 throw (deploy::DeploymentException, 959 ucb::CommandFailedException, 960 ucb::CommandAbortedException, 961 lang::IllegalArgumentException, 962 uno::RuntimeException) 963 { 964 ::osl::MutexGuard guard(getMutex()); 965 bool bUserDisabled = false; 966 uno::Any excOccurred; 967 try 968 { 969 if (!extension.is()) 970 return; 971 OUString repository = extension->getRepositoryName(); 972 if (!repository.equals(OUSTR("user"))) 973 throw lang::IllegalArgumentException( 974 OUSTR("No valid repository name provided."), 975 static_cast<cppu::OWeakObject*>(this), 0); 976 977 bUserDisabled = isUserDisabled(dp_misc::getIdentifier(extension), 978 extension->getName()); 979 980 activateExtension(dp_misc::getIdentifier(extension), 981 extension->getName(), false, false, 982 xAbortChannel, xCmdEnv); 983 } 984 catch (deploy::DeploymentException& ) { 985 excOccurred = ::cppu::getCaughtException(); 986 } catch (ucb::CommandFailedException & ) { 987 excOccurred = ::cppu::getCaughtException(); 988 } catch (ucb::CommandAbortedException & ) { 989 excOccurred = ::cppu::getCaughtException(); 990 } catch (lang::IllegalArgumentException &) { 991 excOccurred = ::cppu::getCaughtException(); 992 } catch (uno::RuntimeException &) { 993 excOccurred = ::cppu::getCaughtException(); 994 } catch (...) { 995 excOccurred = ::cppu::getCaughtException(); 996 deploy::DeploymentException exc( 997 OUSTR("Extension Manager: exception during enableExtension"), 998 static_cast<OWeakObject*>(this), excOccurred); 999 excOccurred <<= exc; 1000 } 1001 1002 if (excOccurred.hasValue()) 1003 { 1004 try 1005 { 1006 activateExtension(dp_misc::getIdentifier(extension), 1007 extension->getName(), bUserDisabled, false, 1008 xAbortChannel, xCmdEnv); 1009 } 1010 catch (...) 1011 { 1012 } 1013 ::cppu::throwException(excOccurred); 1014 } 1015 } 1016 1017 /** 1018 */ 1019 sal_Int32 ExtensionManager::checkPrerequisitesAndEnable( 1020 Reference<deploy::XPackage> const & extension, 1021 Reference<task::XAbortChannel> const & xAbortChannel, 1022 Reference<ucb::XCommandEnvironment> const & xCmdEnv) 1023 throw (deploy::DeploymentException, 1024 ucb::CommandFailedException, 1025 ucb::CommandAbortedException, 1026 lang::IllegalArgumentException, 1027 uno::RuntimeException) 1028 { 1029 try 1030 { 1031 if (!extension.is()) 1032 return 0; 1033 ::osl::MutexGuard guard(getMutex()); 1034 sal_Int32 ret = 0; 1035 Reference<deploy::XPackageManager> mgr = 1036 getPackageManager(extension->getRepositoryName()); 1037 ret = mgr->checkPrerequisites(extension, xAbortChannel, xCmdEnv); 1038 if (ret) 1039 { 1040 //There are some unfulfilled prerequisites, try to revoke 1041 extension->revokePackage(xAbortChannel, xCmdEnv); 1042 } 1043 const OUString id(dp_misc::getIdentifier(extension)); 1044 activateExtension(id, extension->getName(), 1045 isUserDisabled(id, extension->getName()), false, 1046 xAbortChannel, xCmdEnv); 1047 return ret; 1048 } 1049 catch (deploy::DeploymentException& ) { 1050 throw; 1051 } catch (ucb::CommandFailedException & ) { 1052 throw; 1053 } catch (ucb::CommandAbortedException & ) { 1054 throw; 1055 } catch (lang::IllegalArgumentException &) { 1056 throw; 1057 } catch (uno::RuntimeException &) { 1058 throw; 1059 } catch (...) { 1060 uno::Any excOccurred = ::cppu::getCaughtException(); 1061 deploy::DeploymentException exc( 1062 OUSTR("Extension Manager: exception during disableExtension"), 1063 static_cast<OWeakObject*>(this), excOccurred); 1064 throw exc; 1065 } 1066 } 1067 1068 1069 void ExtensionManager::disableExtension( 1070 Reference<deploy::XPackage> const & extension, 1071 Reference<task::XAbortChannel> const & xAbortChannel, 1072 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 1073 throw (deploy::DeploymentException, 1074 ucb::CommandFailedException, 1075 ucb::CommandAbortedException, 1076 lang::IllegalArgumentException, 1077 uno::RuntimeException) 1078 { 1079 ::osl::MutexGuard guard(getMutex()); 1080 uno::Any excOccurred; 1081 bool bUserDisabled = false; 1082 try 1083 { 1084 if (!extension.is()) 1085 return; 1086 const OUString repository( extension->getRepositoryName()); 1087 if (!repository.equals(OUSTR("user"))) 1088 throw lang::IllegalArgumentException( 1089 OUSTR("No valid repository name provided."), 1090 static_cast<cppu::OWeakObject*>(this), 0); 1091 1092 const OUString id(dp_misc::getIdentifier(extension)); 1093 bUserDisabled = isUserDisabled(id, extension->getName()); 1094 1095 activateExtension(id, extension->getName(), true, false, 1096 xAbortChannel, xCmdEnv); 1097 } 1098 catch (deploy::DeploymentException& ) { 1099 excOccurred = ::cppu::getCaughtException(); 1100 } catch (ucb::CommandFailedException & ) { 1101 excOccurred = ::cppu::getCaughtException(); 1102 } catch (ucb::CommandAbortedException & ) { 1103 excOccurred = ::cppu::getCaughtException(); 1104 } catch (lang::IllegalArgumentException &) { 1105 excOccurred = ::cppu::getCaughtException(); 1106 } catch (uno::RuntimeException &) { 1107 excOccurred = ::cppu::getCaughtException(); 1108 } catch (...) { 1109 excOccurred = ::cppu::getCaughtException(); 1110 deploy::DeploymentException exc( 1111 OUSTR("Extension Manager: exception during disableExtension"), 1112 static_cast<OWeakObject*>(this), excOccurred); 1113 excOccurred <<= exc; 1114 } 1115 1116 if (excOccurred.hasValue()) 1117 { 1118 try 1119 { 1120 activateExtension(dp_misc::getIdentifier(extension), 1121 extension->getName(), bUserDisabled, false, 1122 xAbortChannel, xCmdEnv); 1123 } 1124 catch (...) 1125 { 1126 } 1127 ::cppu::throwException(excOccurred); 1128 } 1129 } 1130 1131 uno::Sequence< Reference<deploy::XPackage> > 1132 ExtensionManager::getDeployedExtensions( 1133 OUString const & repository, 1134 Reference<task::XAbortChannel> const &xAbort, 1135 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 1136 throw (deploy::DeploymentException, 1137 ucb::CommandFailedException, 1138 ucb::CommandAbortedException, 1139 lang::IllegalArgumentException, 1140 uno::RuntimeException) 1141 { 1142 return getPackageManager(repository)->getDeployedPackages( 1143 xAbort, xCmdEnv); 1144 } 1145 1146 Reference<deploy::XPackage> 1147 ExtensionManager::getDeployedExtension( 1148 OUString const & repository, 1149 OUString const & identifier, 1150 OUString const & filename, 1151 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 1152 throw (deploy::DeploymentException, 1153 ucb::CommandFailedException, 1154 lang::IllegalArgumentException, 1155 uno::RuntimeException) 1156 { 1157 return getPackageManager(repository)->getDeployedPackage( 1158 identifier, filename, xCmdEnv); 1159 } 1160 1161 uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > 1162 ExtensionManager::getAllExtensions( 1163 Reference<task::XAbortChannel> const & xAbort, 1164 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 1165 throw (deploy::DeploymentException, 1166 ucb::CommandFailedException, 1167 ucb::CommandAbortedException, 1168 lang::IllegalArgumentException, 1169 uno::RuntimeException) 1170 { 1171 try 1172 { 1173 id2extensions mapExt; 1174 1175 uno::Sequence<Reference<deploy::XPackage> > userExt = 1176 getUserRepository()->getDeployedPackages(xAbort, xCmdEnv); 1177 addExtensionsToMap(mapExt, userExt, OUSTR("user")); 1178 uno::Sequence<Reference<deploy::XPackage> > sharedExt = 1179 getSharedRepository()->getDeployedPackages(xAbort, xCmdEnv); 1180 addExtensionsToMap(mapExt, sharedExt, OUSTR("shared")); 1181 uno::Sequence<Reference<deploy::XPackage> > bundledExt = 1182 getBundledRepository()->getDeployedPackages(xAbort, xCmdEnv); 1183 addExtensionsToMap(mapExt, bundledExt, OUSTR("bundled")); 1184 addExtensionsToMap(mapExt, bundledExt, OUSTR("bundled_prereg")); 1185 1186 // Create the tmp repository to trigger its clean up (deletion 1187 // of old temporary data.) 1188 getTmpRepository(); 1189 1190 //copy the values of the map to a vector for sorting 1191 ::std::vector< ::std::vector<Reference<deploy::XPackage> > > 1192 vecExtensions; 1193 id2extensions::const_iterator mapIt = mapExt.begin(); 1194 for (;mapIt != mapExt.end(); mapIt++) 1195 vecExtensions.push_back(mapIt->second); 1196 1197 //sort the element according to the identifier 1198 ::std::sort(vecExtensions.begin(), vecExtensions.end(), CompIdentifiers()); 1199 1200 ::std::vector< ::std::vector<Reference<deploy::XPackage> > >::const_iterator 1201 citVecVec = vecExtensions.begin(); 1202 sal_Int32 j = 0; 1203 uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > seqSeq(vecExtensions.size()); 1204 for (;citVecVec != vecExtensions.end(); citVecVec++, j++) 1205 { 1206 seqSeq[j] = comphelper::containerToSequence(*citVecVec); 1207 } 1208 return seqSeq; 1209 1210 } catch (deploy::DeploymentException& ) { 1211 throw; 1212 } catch (ucb::CommandFailedException & ) { 1213 throw; 1214 } catch (ucb::CommandAbortedException & ) { 1215 throw; 1216 } catch (lang::IllegalArgumentException &) { 1217 throw; 1218 } catch (uno::RuntimeException &) { 1219 throw; 1220 } catch (...) { 1221 uno::Any exc = ::cppu::getCaughtException(); 1222 throw deploy::DeploymentException( 1223 OUSTR("Extension Manager: exception during enableExtension"), 1224 static_cast<OWeakObject*>(this), exc); 1225 } 1226 } 1227 1228 //only to be called from unopkg!!! 1229 void ExtensionManager::reinstallDeployedExtensions( 1230 OUString const & repository, 1231 Reference<task::XAbortChannel> const & xAbortChannel, 1232 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 1233 throw (deploy::DeploymentException, 1234 ucb::CommandFailedException, ucb::CommandAbortedException, 1235 lang::IllegalArgumentException, uno::RuntimeException) 1236 { 1237 try 1238 { 1239 Reference<deploy::XPackageManager> 1240 xPackageManager = getPackageManager(repository); 1241 1242 ::osl::MutexGuard guard(getMutex()); 1243 xPackageManager->reinstallDeployedPackages(xAbortChannel, xCmdEnv); 1244 //We must sync here, otherwise we will get exceptions when extensions 1245 //are removed. 1246 dp_misc::syncRepositories(xCmdEnv); 1247 const uno::Sequence< Reference<deploy::XPackage> > extensions( 1248 xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv)); 1249 1250 for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos ) 1251 { 1252 try 1253 { 1254 const OUString id = dp_misc::getIdentifier(extensions[ pos ]); 1255 const OUString fileName = extensions[ pos ]->getName(); 1256 OSL_ASSERT(id.getLength()); 1257 activateExtension(id, fileName, false, true, xAbortChannel, xCmdEnv ); 1258 } 1259 catch (lang::DisposedException &) 1260 { 1261 } 1262 } 1263 } catch (deploy::DeploymentException& ) { 1264 throw; 1265 } catch (ucb::CommandFailedException & ) { 1266 throw; 1267 } catch (ucb::CommandAbortedException & ) { 1268 throw; 1269 } catch (lang::IllegalArgumentException &) { 1270 throw; 1271 } catch (uno::RuntimeException &) { 1272 throw; 1273 } catch (...) { 1274 uno::Any exc = ::cppu::getCaughtException(); 1275 throw deploy::DeploymentException( 1276 OUSTR("Extension Manager: exception during enableExtension"), 1277 static_cast<OWeakObject*>(this), exc); 1278 } 1279 } 1280 1281 /** Works on the bundled repository. That is using the variables 1282 BUNDLED_EXTENSIONS and BUNDLED_EXTENSIONS_USER. 1283 */ 1284 void ExtensionManager::synchronizeBundledPrereg( 1285 Reference<task::XAbortChannel> const & xAbortChannel, 1286 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 1287 throw (deploy::DeploymentException, 1288 uno::RuntimeException) 1289 { 1290 try 1291 { 1292 String sSynchronizingBundled(StrSyncRepository::get()); 1293 sSynchronizingBundled.SearchAndReplaceAllAscii( "%NAME", OUSTR("bundled")); 1294 dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled); 1295 1296 Reference<deploy::XPackageManagerFactory> xPackageManagerFactory( 1297 deploy::thePackageManagerFactory::get(m_xContext)); 1298 1299 Reference<deploy::XPackageManager> xMgr = 1300 xPackageManagerFactory->getPackageManager(OUSTR("bundled_prereg")); 1301 xMgr->synchronize(xAbortChannel, xCmdEnv); 1302 progressBundled.update(OUSTR("\n\n")); 1303 1304 uno::Sequence<Reference<deploy::XPackage> > extensions = xMgr->getDeployedPackages( 1305 xAbortChannel, xCmdEnv); 1306 try 1307 { 1308 for (sal_Int32 i = 0; i < extensions.getLength(); i++) 1309 { 1310 extensions[i]->registerPackage(true, xAbortChannel, xCmdEnv); 1311 } 1312 } 1313 catch (...) 1314 { 1315 OSL_ASSERT(0); 1316 } 1317 OUString lastSyncBundled(RTL_CONSTASCII_USTRINGPARAM( 1318 "$BUNDLED_EXTENSIONS_PREREG/lastsynchronized")); 1319 writeLastModified(lastSyncBundled, xCmdEnv); 1320 1321 } catch (deploy::DeploymentException& ) { 1322 throw; 1323 } catch (ucb::CommandFailedException & ) { 1324 throw; 1325 } catch (ucb::CommandAbortedException & ) { 1326 throw; 1327 } catch (lang::IllegalArgumentException &) { 1328 throw; 1329 } catch (uno::RuntimeException &) { 1330 throw; 1331 } catch (...) { 1332 uno::Any exc = ::cppu::getCaughtException(); 1333 throw deploy::DeploymentException( 1334 OUSTR("Extension Manager: exception in synchronize"), 1335 static_cast<OWeakObject*>(this), exc); 1336 } 1337 } 1338 1339 sal_Bool ExtensionManager::synchronize( 1340 Reference<task::XAbortChannel> const & xAbortChannel, 1341 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 1342 throw (deploy::DeploymentException, 1343 ucb::CommandFailedException, 1344 ucb::CommandAbortedException, 1345 lang::IllegalArgumentException, 1346 uno::RuntimeException) 1347 { 1348 try 1349 { 1350 sal_Bool bModified = sal_False; 1351 1352 ::osl::MutexGuard guard(getMutex()); 1353 String sSynchronizingShared(StrSyncRepository::get()); 1354 sSynchronizingShared.SearchAndReplaceAllAscii( "%NAME", OUSTR("shared")); 1355 dp_misc::ProgressLevel progressShared(xCmdEnv, sSynchronizingShared); 1356 bModified = getSharedRepository()->synchronize(xAbortChannel, xCmdEnv); 1357 progressShared.update(OUSTR("\n\n")); 1358 1359 String sSynchronizingBundled(StrSyncRepository::get()); 1360 sSynchronizingBundled.SearchAndReplaceAllAscii( "%NAME", OUSTR("bundled")); 1361 dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled); 1362 bModified |= getBundledRepository()->synchronize(xAbortChannel, xCmdEnv); 1363 progressBundled.update(OUSTR("\n\n")); 1364 1365 //Always determine the active extension. This is necessary for the 1366 //first-start optimization. The setup creates the registration data for the 1367 //bundled extensions (brand_layer/share/prereg/bundled), which is copied to the user 1368 //installation (user_installation/extension/bundled) when a user starts OOo 1369 //for the first time after running setup. All bundled extensions are registered 1370 //at that moment. However, extensions with the same identifier can be in the 1371 //shared or user repository, in which case the respective bundled extensions must 1372 //be revoked. 1373 try 1374 { 1375 const uno::Sequence<uno::Sequence<Reference<deploy::XPackage> > > 1376 seqSeqExt = getAllExtensions(xAbortChannel, xCmdEnv); 1377 for (sal_Int32 i = 0; i < seqSeqExt.getLength(); i++) 1378 { 1379 uno::Sequence<Reference<deploy::XPackage> > const & seqExt = 1380 seqSeqExt[i]; 1381 activateExtension(seqExt, isUserDisabled(seqExt), true, 1382 xAbortChannel, xCmdEnv); 1383 } 1384 } 1385 catch (...) 1386 { 1387 //We catch the exception, so we can write the lastmodified file 1388 //so we will no repeat this everytime OOo starts. 1389 OSL_ENSURE(0, "Extensions Manager: synchronize"); 1390 } 1391 OUString lastSyncBundled(RTL_CONSTASCII_USTRINGPARAM( 1392 "$BUNDLED_EXTENSIONS_USER/lastsynchronized")); 1393 writeLastModified(lastSyncBundled, xCmdEnv); 1394 OUString lastSyncShared(RTL_CONSTASCII_USTRINGPARAM( 1395 "$SHARED_EXTENSIONS_USER/lastsynchronized")); 1396 writeLastModified(lastSyncShared, xCmdEnv); 1397 return bModified; 1398 } catch (deploy::DeploymentException& ) { 1399 throw; 1400 } catch (ucb::CommandFailedException & ) { 1401 throw; 1402 } catch (ucb::CommandAbortedException & ) { 1403 throw; 1404 } catch (lang::IllegalArgumentException &) { 1405 throw; 1406 } catch (uno::RuntimeException &) { 1407 throw; 1408 } catch (...) { 1409 uno::Any exc = ::cppu::getCaughtException(); 1410 throw deploy::DeploymentException( 1411 OUSTR("Extension Manager: exception in synchronize"), 1412 static_cast<OWeakObject*>(this), exc); 1413 } 1414 } 1415 1416 // Notify the user when a new extension is to be installed. This is only the 1417 // case when one uses the system integration to install an extension (double 1418 // clicking on .oxt file etc.)). The function must only be called if there is no 1419 // extension with the same identifier already deployed. Then the checkUpdate 1420 // function will inform the user that the extension is about to be installed In 1421 // case the user cancels the installation a CommandFailed exception is 1422 // thrown. 1423 void ExtensionManager::checkInstall( 1424 OUString const & displayName, 1425 Reference<ucb::XCommandEnvironment> const & cmdEnv) 1426 { 1427 uno::Any request( 1428 deploy::InstallException( 1429 OUSTR("Extension ") + displayName + 1430 OUSTR(" is about to be installed."), 1431 static_cast<OWeakObject *>(this), displayName)); 1432 bool approve = false, abort = false; 1433 if (! dp_misc::interactContinuation( 1434 request, task::XInteractionApprove::static_type(), 1435 cmdEnv, &approve, &abort )) 1436 { 1437 OSL_ASSERT( !approve && !abort ); 1438 throw deploy::DeploymentException( 1439 dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName, 1440 static_cast<OWeakObject *>(this), request ); 1441 } 1442 if (abort || !approve) 1443 throw ucb::CommandFailedException( 1444 dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName, 1445 static_cast<OWeakObject *>(this), request ); 1446 } 1447 1448 /* The function will make the user interaction in case there is an extension 1449 installed with the same id. This function may only be called if there is already 1450 an extension. 1451 */ 1452 void ExtensionManager::checkUpdate( 1453 OUString const & newVersion, 1454 OUString const & newDisplayName, 1455 Reference<deploy::XPackage> const & oldExtension, 1456 Reference<ucb::XCommandEnvironment> const & xCmdEnv ) 1457 { 1458 // package already deployed, interact --force: 1459 uno::Any request( 1460 (deploy::VersionException( 1461 dp_misc::getResourceString( 1462 RID_STR_PACKAGE_ALREADY_ADDED ) + newDisplayName, 1463 static_cast<OWeakObject *>(this), newVersion, newDisplayName, 1464 oldExtension ) ) ); 1465 bool replace = false, abort = false; 1466 if (! dp_misc::interactContinuation( 1467 request, task::XInteractionApprove::static_type(), 1468 xCmdEnv, &replace, &abort )) { 1469 OSL_ASSERT( !replace && !abort ); 1470 throw deploy::DeploymentException( 1471 dp_misc::getResourceString( 1472 RID_STR_ERROR_WHILE_ADDING) + newDisplayName, 1473 static_cast<OWeakObject *>(this), request ); 1474 } 1475 if (abort || !replace) 1476 throw ucb::CommandFailedException( 1477 dp_misc::getResourceString( 1478 RID_STR_PACKAGE_ALREADY_ADDED) + newDisplayName, 1479 static_cast<OWeakObject *>(this), request ); 1480 } 1481 1482 Reference<deploy::XPackage> ExtensionManager::getTempExtension( 1483 OUString const & url, 1484 Reference<task::XAbortChannel> const & xAbortChannel, 1485 Reference<ucb::XCommandEnvironment> const & /*xCmdEnv*/) 1486 1487 { 1488 Reference<ucb::XCommandEnvironment> tmpCmdEnvA(new TmpRepositoryCommandEnv()); 1489 Reference<deploy::XPackage> xTmpPackage = getTmpRepository()->addPackage( 1490 url, uno::Sequence<beans::NamedValue>(),OUString(), xAbortChannel, tmpCmdEnvA); 1491 if (!xTmpPackage.is()) 1492 { 1493 throw deploy::DeploymentException( 1494 OUSTR("Extension Manager: Failed to create temporary XPackage for url: ") + url, 1495 static_cast<OWeakObject*>(this), uno::Any()); 1496 1497 } 1498 return xTmpPackage; 1499 } 1500 1501 uno::Sequence<Reference<deploy::XPackage> > SAL_CALL 1502 ExtensionManager::getExtensionsWithUnacceptedLicenses( 1503 OUString const & repository, 1504 Reference<ucb::XCommandEnvironment> const & xCmdEnv) 1505 throw (deploy::DeploymentException, 1506 uno::RuntimeException) 1507 { 1508 Reference<deploy::XPackageManager> 1509 xPackageManager = getPackageManager(repository); 1510 ::osl::MutexGuard guard(getMutex()); 1511 return xPackageManager->getExtensionsWithUnacceptedLicenses(xCmdEnv); 1512 } 1513 1514 sal_Bool ExtensionManager::isReadOnlyRepository(::rtl::OUString const & repository) 1515 throw (uno::RuntimeException) 1516 { 1517 return getPackageManager(repository)->isReadOnly(); 1518 } 1519 //------------------------------------------------------------------------------ 1520 //------------------------------------------------------------------------------ 1521 //------------------------------------------------------------------------------ 1522 1523 namespace sdecl = comphelper::service_decl; 1524 sdecl::class_<ExtensionManager> servicePIP; 1525 extern sdecl::ServiceDecl const serviceDecl( 1526 servicePIP, 1527 // a private one: 1528 "com.sun.star.comp.deployment.ExtensionManager", 1529 "com.sun.star.comp.deployment.ExtensionManager"); 1530 1531 //------------------------------------------------------------------------------ 1532 bool singleton_entries( 1533 uno::Reference< registry::XRegistryKey > const & xRegistryKey ) 1534 { 1535 try { 1536 uno::Reference< registry::XRegistryKey > xKey( 1537 xRegistryKey->createKey( 1538 serviceDecl.getImplementationName() + 1539 // xxx todo: use future generated function to get singleton name 1540 OUSTR("/UNO/SINGLETONS/" 1541 "com.sun.star.deployment.ExtensionManager") ) ); 1542 xKey->setStringValue( serviceDecl.getSupportedServiceNames()[0] ); 1543 return true; 1544 } 1545 catch (registry::InvalidRegistryException & exc) { 1546 (void) exc; // avoid warnings 1547 OSL_ENSURE( 0, ::rtl::OUStringToOString( 1548 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); 1549 return false; 1550 } 1551 } 1552 1553 // XModifyBroadcaster 1554 //______________________________________________________________________________ 1555 void ExtensionManager::addModifyListener( 1556 Reference<util::XModifyListener> const & xListener ) 1557 throw (uno::RuntimeException) 1558 { 1559 check(); 1560 rBHelper.addListener( ::getCppuType( &xListener ), xListener ); 1561 } 1562 1563 //______________________________________________________________________________ 1564 void ExtensionManager::removeModifyListener( 1565 Reference<util::XModifyListener> const & xListener ) 1566 throw (uno::RuntimeException) 1567 { 1568 check(); 1569 rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); 1570 } 1571 1572 void ExtensionManager::check() 1573 { 1574 ::osl::MutexGuard guard( getMutex() ); 1575 if (rBHelper.bInDispose || rBHelper.bDisposed) { 1576 throw lang::DisposedException( 1577 OUSTR("ExtensionManager instance has already been disposed!"), 1578 static_cast<OWeakObject *>(this) ); 1579 } 1580 } 1581 1582 void ExtensionManager::fireModified() 1583 { 1584 ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer( 1585 util::XModifyListener::static_type() ); 1586 if (pContainer != 0) { 1587 pContainer->forEach<util::XModifyListener>( 1588 boost::bind(&util::XModifyListener::modified, _1, 1589 lang::EventObject(static_cast<OWeakObject *>(this))) ); 1590 } 1591 } 1592 1593 } // namespace dp_manager 1594 1595 1596