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