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