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