update credits
[LibreOffice.git] / desktop / source / deployment / manager / dp_extensionmanager.cxx
blob85f0566b326dafcfef7281c8bc6fb6c0c717c681
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <cppuhelper/implbase1.hxx>
23 #include "comphelper/servicedecl.hxx"
24 #include "cppuhelper/exc_hlp.hxx"
25 #include "rtl/bootstrap.hxx"
26 #include "com/sun/star/deployment/ExtensionManager.hpp"
27 #include "com/sun/star/deployment/XExtensionManager.hpp"
28 #include "com/sun/star/deployment/thePackageManagerFactory.hpp"
29 #include "com/sun/star/deployment/XPackageManager.hpp"
30 #include "com/sun/star/deployment/XPackageManagerFactory.hpp"
31 #include "com/sun/star/deployment/XPackage.hpp"
32 #include "com/sun/star/deployment/InstallException.hpp"
33 #include "com/sun/star/deployment/VersionException.hpp"
34 #include "com/sun/star/deployment/LicenseException.hpp"
35 #include "com/sun/star/lang/XServiceInfo.hpp"
36 #include "com/sun/star/registry/XRegistryKey.hpp"
37 #include "com/sun/star/beans/Optional.hpp"
38 #include "com/sun/star/task/XInteractionApprove.hpp"
39 #include "com/sun/star/beans/Ambiguous.hpp"
40 #include "com/sun/star/uno/XComponentContext.hpp"
41 #include "com/sun/star/io/XInputStream.hpp"
42 #include "com/sun/star/util/XModifyBroadcaster.hpp"
43 #include "comphelper/sequence.hxx"
44 #include "xmlscript/xml_helper.hxx"
45 #include "osl/diagnose.h"
46 #include "dp_interact.h"
47 #include "dp_resource.h"
48 #include "dp_ucb.h"
49 #include "dp_identifier.hxx"
50 #include "dp_descriptioninfoset.hxx"
51 #include "dp_extensionmanager.hxx"
52 #include "dp_commandenvironments.hxx"
53 #include "dp_properties.hxx"
54 #include "boost/bind.hpp"
56 #include <list>
57 #include <boost/unordered_map.hpp>
58 #include <algorithm>
59 #include <set>
61 namespace deploy = com::sun::star::deployment;
62 namespace lang = com::sun::star::lang;
63 namespace registry = com::sun::star::registry;
64 namespace task = com::sun::star::task;
65 namespace ucb = com::sun::star::ucb;
66 namespace uno = com::sun::star::uno;
67 namespace beans = com::sun::star::beans;
68 namespace util = com::sun::star::util;
70 using ::com::sun::star::uno::Reference;
72 namespace {
74 struct CompIdentifiers
76 bool operator() (::std::vector<Reference<deploy::XPackage> > const & a,
77 ::std::vector<Reference<deploy::XPackage> > const & b)
79 if (getName(a).compareTo(getName(b)) < 0)
80 return true;
81 return false;
84 OUString getName(::std::vector<Reference<deploy::XPackage> > const & a);
87 OUString CompIdentifiers::getName(::std::vector<Reference<deploy::XPackage> > const & a)
89 OSL_ASSERT(a.size() == 3);
90 //get the first non-null reference
91 Reference<deploy::XPackage> extension;
92 ::std::vector<Reference<deploy::XPackage> >::const_iterator it = a.begin();
93 for (; it != a.end(); ++it)
95 if (it->is())
97 extension = *it;
98 break;
101 OSL_ASSERT(extension.is());
102 return extension->getDisplayName();
105 void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const & xCmdEnv, Reference< uno::XComponentContext > const & xContext)
107 //Write the lastmodified file
108 try {
109 ::rtl::Bootstrap::expandMacros(url);
110 ::ucbhelper::Content ucbStamp(url, xCmdEnv, xContext);
111 dp_misc::erase_path( url, xCmdEnv );
112 OString stamp("1" );
113 Reference<css::io::XInputStream> xData(
114 ::xmlscript::createInputStream(
115 ::rtl::ByteSequence(
116 reinterpret_cast<sal_Int8 const *>(stamp.getStr()),
117 stamp.getLength() ) ) );
118 ucbStamp.writeStream( xData, true /* replace existing */ );
120 catch(...)
122 uno::Any exc(::cppu::getCaughtException());
123 throw deploy::DeploymentException("Failed to update" + url, 0, exc);
127 class ExtensionRemoveGuard
129 css::uno::Reference<css::deployment::XPackage> m_extension;
130 css::uno::Reference<css::deployment::XPackageManager> m_xPackageManager;
132 public:
133 ExtensionRemoveGuard(){};
134 ExtensionRemoveGuard(
135 css::uno::Reference<css::deployment::XPackage> const & extension,
136 css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager):
137 m_extension(extension), m_xPackageManager(xPackageManager) {}
138 ~ExtensionRemoveGuard();
140 void set(css::uno::Reference<css::deployment::XPackage> const & extension,
141 css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager) {
142 m_extension = extension;
143 m_xPackageManager = xPackageManager;
147 ExtensionRemoveGuard::~ExtensionRemoveGuard()
149 try {
150 OSL_ASSERT(!(m_extension.is() && !m_xPackageManager.is()));
151 if (m_xPackageManager.is() && m_extension.is())
152 m_xPackageManager->removePackage(
153 dp_misc::getIdentifier(m_extension), OUString(),
154 css::uno::Reference<css::task::XAbortChannel>(),
155 css::uno::Reference<css::ucb::XCommandEnvironment>());
156 } catch (...) {
157 OSL_ASSERT(0);
163 namespace dp_manager {
165 //------------------------------------------------------------------------------
167 //ToDo: bundled extension
168 ExtensionManager::ExtensionManager( Reference< uno::XComponentContext > const& xContext) :
169 ::cppu::WeakComponentImplHelper1< css::deployment::XExtensionManager >(getMutex()),
170 m_xContext( xContext )
172 m_xPackageManagerFactory = deploy::thePackageManagerFactory::get(m_xContext);
173 OSL_ASSERT(m_xPackageManagerFactory.is());
175 m_repositoryNames.push_back("user");
176 m_repositoryNames.push_back("shared");
177 m_repositoryNames.push_back("bundled");
180 //------------------------------------------------------------------------------
182 ExtensionManager::~ExtensionManager()
186 Reference<deploy::XPackageManager> ExtensionManager::getUserRepository()
188 return m_xPackageManagerFactory->getPackageManager("user");
190 Reference<deploy::XPackageManager> ExtensionManager::getSharedRepository()
192 return m_xPackageManagerFactory->getPackageManager("shared");
194 Reference<deploy::XPackageManager> ExtensionManager::getBundledRepository()
196 return m_xPackageManagerFactory->getPackageManager("bundled");
198 Reference<deploy::XPackageManager> ExtensionManager::getTmpRepository()
200 return m_xPackageManagerFactory->getPackageManager("tmp");
202 Reference<deploy::XPackageManager> ExtensionManager::getBakRepository()
204 return m_xPackageManagerFactory->getPackageManager("bak");
207 Reference<task::XAbortChannel> ExtensionManager::createAbortChannel()
208 throw (uno::RuntimeException)
210 return new dp_misc::AbortChannel;
213 css::uno::Reference<css::deployment::XPackageManager>
214 ExtensionManager::getPackageManager(OUString const & repository)
215 throw (css::lang::IllegalArgumentException, css::uno::RuntimeException)
217 Reference<deploy::XPackageManager> xPackageManager;
218 if (repository == "user")
219 xPackageManager = getUserRepository();
220 else if (repository == "shared")
221 xPackageManager = getSharedRepository();
222 else if (repository == "bundled")
223 xPackageManager = getBundledRepository();
224 else if (repository == "tmp")
225 xPackageManager = getTmpRepository();
226 else if (repository == "bak")
227 xPackageManager = getBakRepository();
228 else
229 throw lang::IllegalArgumentException(
230 "No valid repository name provided.",
231 static_cast<cppu::OWeakObject*>(this), 0);
232 return xPackageManager;
236 Enters the XPackage objects into a map. They must be all from the
237 same repository. The value type of the map is a vector, where each vector
238 represents an extension with a particular identifier. The first member
239 represents the user extension, the second the shared extension and the
240 third the bundled extension.
242 void ExtensionManager::addExtensionsToMap(
243 id2extensions & mapExt,
244 uno::Sequence<Reference<deploy::XPackage> > const & seqExt,
245 OUString const & repository)
247 //Determine the index in the vector where these extensions are to be
248 //added.
249 ::std::list<OUString>::const_iterator citNames =
250 m_repositoryNames.begin();
251 int index = 0;
252 for (;citNames != m_repositoryNames.end(); ++citNames, ++index)
254 if (citNames->equals(repository))
255 break;
258 for (int i = 0; i < seqExt.getLength(); ++i)
260 Reference<deploy::XPackage> const & xExtension = seqExt[i];
261 OUString id = dp_misc::getIdentifier(xExtension);
262 id2extensions::iterator ivec = mapExt.find(id);
263 if (ivec == mapExt.end())
265 ::std::vector<Reference<deploy::XPackage> > vec(3);
266 vec[index] = xExtension;
267 mapExt[id] = vec;
269 else
271 ivec->second[index] = xExtension;
277 returns a list containing extensions with the same identifier from
278 all repositories (user, shared, bundled). If one repository does not
279 have this extension, then the list contains an empty Reference. The list
280 is ordered according to the priority of the repostories:
281 1. user
282 2. shared
283 3. bundled
285 The number of elements is always three, unless the number of repository
286 changes.
288 ::std::list<Reference<deploy::XPackage> >
289 ExtensionManager::getExtensionsWithSameId(
290 OUString const & identifier, OUString const & fileName,
291 Reference< ucb::XCommandEnvironment> const & /*xCmdEnv*/)
294 ::std::list<Reference<deploy::XPackage> > extensionList;
295 Reference<deploy::XPackageManager> lRepos[] = {
296 getUserRepository(), getSharedRepository(), getBundledRepository() };
297 for (int i(0); i != SAL_N_ELEMENTS(lRepos); ++i)
299 Reference<deploy::XPackage> xPackage;
302 xPackage = lRepos[i]->getDeployedPackage(
303 identifier, fileName, Reference<ucb::XCommandEnvironment>());
305 catch(const lang::IllegalArgumentException &)
307 // thrown if the extension does not exist in this repository
309 extensionList.push_back(xPackage);
311 OSL_ASSERT(extensionList.size() == 3);
312 return extensionList;
315 uno::Sequence<Reference<deploy::XPackage> >
316 ExtensionManager::getExtensionsWithSameIdentifier(
317 OUString const & identifier,
318 OUString const & fileName,
319 Reference< ucb::XCommandEnvironment> const & xCmdEnv )
320 throw (
321 deploy::DeploymentException,
322 ucb::CommandFailedException,
323 lang::IllegalArgumentException,
324 uno::RuntimeException)
328 ::std::list<Reference<deploy::XPackage> > listExtensions =
329 getExtensionsWithSameId(
330 identifier, fileName, xCmdEnv);
331 sal_Bool bHasExtension = false;
333 //throw an IllegalArgumentException if there is no extension at all.
334 typedef ::std::list<Reference<deploy::XPackage> >::const_iterator CIT;
335 for (CIT i = listExtensions.begin(); i != listExtensions.end(); ++i)
336 bHasExtension |= i->is();
337 if (!bHasExtension)
338 throw lang::IllegalArgumentException(
339 "Could not find extension: " + identifier + ", " + fileName,
340 static_cast<cppu::OWeakObject*>(this), -1);
342 return comphelper::containerToSequence<
343 Reference<deploy::XPackage>,
344 ::std::list<Reference<deploy::XPackage> >
345 > (listExtensions);
347 catch ( const deploy::DeploymentException & )
349 throw;
351 catch ( const ucb::CommandFailedException & )
353 throw;
355 catch (const lang::IllegalArgumentException &)
357 throw;
359 catch (...)
361 uno::Any exc = ::cppu::getCaughtException();
362 throw deploy::DeploymentException(
363 "Extension Manager: exception during getExtensionsWithSameIdentifier",
364 static_cast<OWeakObject*>(this), exc);
368 bool ExtensionManager::isUserDisabled(
369 OUString const & identifier, OUString const & fileName)
371 ::std::list<Reference<deploy::XPackage> > listExtensions;
373 try {
374 listExtensions = getExtensionsWithSameId(identifier, fileName);
375 } catch ( const lang::IllegalArgumentException & ) {
377 OSL_ASSERT(listExtensions.size() == 3);
379 return isUserDisabled( ::comphelper::containerToSequence<
380 Reference<deploy::XPackage>,
381 ::std::list<Reference<deploy::XPackage> >
382 > (listExtensions));
385 bool ExtensionManager::isUserDisabled(
386 uno::Sequence<Reference<deploy::XPackage> > const & seqExtSameId)
388 OSL_ASSERT(seqExtSameId.getLength() == 3);
389 Reference<deploy::XPackage> const & userExtension = seqExtSameId[0];
390 if (userExtension.is())
392 beans::Optional<beans::Ambiguous<sal_Bool> > reg =
393 userExtension->isRegistered(Reference<task::XAbortChannel>(),
394 Reference<ucb::XCommandEnvironment>());
395 //If the value is ambiguous is than we assume that the extension
396 //is enabled, but something went wrong during enabling. We do not
397 //automatically disable user extensions.
398 if (reg.IsPresent &&
399 ! reg.Value.IsAmbiguous && ! reg.Value.Value)
400 return true;
402 return false;
406 This method determines the active extension (XPackage.registerPackage) with a
407 particular identifier.
409 The parameter bUserDisabled determines if the user extension is disabled.
411 When the user repository contains an extension with the given identifier and
412 it is not disabled by the user, then it is always registered. Otherwise an
413 extension is only registered when there is no registered extension in one of
414 the repositories with a higher priority. That is, if the extension is from
415 the shared repository and an active extension with the same identifer is in
416 the user repository, then the extension is not registered. Similarly a
417 bundled extension is not registered if there is an active extension with the
418 same identifier in the shared or user repository.
420 void ExtensionManager::activateExtension(
421 OUString const & identifier, OUString const & fileName,
422 bool bUserDisabled,
423 bool bStartup,
424 Reference<task::XAbortChannel> const & xAbortChannel,
425 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
427 ::std::list<Reference<deploy::XPackage> > listExtensions;
428 try {
429 listExtensions = getExtensionsWithSameId(identifier, fileName);
430 } catch (const lang::IllegalArgumentException &) {
432 OSL_ASSERT(listExtensions.size() == 3);
434 activateExtension(
435 ::comphelper::containerToSequence<
436 Reference<deploy::XPackage>,
437 ::std::list<Reference<deploy::XPackage> >
438 > (listExtensions),
439 bUserDisabled, bStartup, xAbortChannel, xCmdEnv);
441 fireModified();
444 void ExtensionManager::activateExtension(
445 uno::Sequence<Reference<deploy::XPackage> > const & seqExt,
446 bool bUserDisabled,
447 bool bStartup,
448 Reference<task::XAbortChannel> const & xAbortChannel,
449 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
451 bool bActive = false;
452 sal_Int32 len = seqExt.getLength();
453 for (sal_Int32 i = 0; i < len; i++)
455 Reference<deploy::XPackage> const & aExt = seqExt[i];
456 if (aExt.is())
458 //get the registration value of the current iteration
459 beans::Optional<beans::Ambiguous<sal_Bool> > optReg =
460 aExt->isRegistered(xAbortChannel, xCmdEnv);
461 //If nothing can be registered then break
462 if (!optReg.IsPresent)
463 break;
465 //Check if this is a disabled user extension,
466 if (i == 0 && bUserDisabled)
468 aExt->revokePackage(bStartup, xAbortChannel, xCmdEnv);
469 continue;
472 //If we have already determined an active extension then we must
473 //make sure to unregister all extensions with the same id in
474 //repositories with a lower priority
475 if (bActive)
477 aExt->revokePackage(bStartup, xAbortChannel, xCmdEnv);
479 else
481 //This is the first extension in the ordered list, which becomes
482 //the active extension
483 bActive = true;
484 //Register if not already done.
485 //reregister if the value is ambiguous, which indicates that
486 //something went wrong during last registration.
487 aExt->registerPackage(bStartup, xAbortChannel, xCmdEnv);
493 Reference<deploy::XPackage> ExtensionManager::backupExtension(
494 OUString const & identifier, OUString const & fileName,
495 Reference<deploy::XPackageManager> const & xPackageManager,
496 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
498 Reference<deploy::XPackage> xBackup;
499 Reference<ucb::XCommandEnvironment> tmpCmdEnv(
500 new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler()));
501 Reference<deploy::XPackage> xOldExtension;
502 xOldExtension = xPackageManager->getDeployedPackage(
503 identifier, fileName, tmpCmdEnv);
505 if (xOldExtension.is())
507 xBackup = getTmpRepository()->addPackage(
508 xOldExtension->getURL(), uno::Sequence<beans::NamedValue>(),
509 OUString(), Reference<task::XAbortChannel>(), tmpCmdEnv);
511 OSL_ENSURE(xBackup.is(), "Failed to backup extension");
513 return xBackup;
516 //The supported package types are actually determined by the registry. However
517 //creating a registry
518 //(desktop/source/deployment/registry/dp_registry.cxx:PackageRegistryImpl) will
519 //create all the backends, so that the registry can obtain from them the package
520 //types. Creating the registry will also set up the registry folder containing
521 //all the subfolders for the respective backends.
522 //Because all repositories support the same backends, we can just delegate this
523 //call to one of the repositories.
524 uno::Sequence< Reference<deploy::XPackageTypeInfo> >
525 ExtensionManager::getSupportedPackageTypes()
526 throw (uno::RuntimeException)
528 return getUserRepository()->getSupportedPackageTypes();
530 //Do some necessary checks and user interaction. This function does not
531 //aquire the extension manager mutex and that mutex must not be aquired
532 //when this function is called. doChecksForAddExtension does synchronous
533 //user interactions which may require aquiring the solar mutex.
534 //Returns true if the extension can be installed.
535 bool ExtensionManager::doChecksForAddExtension(
536 Reference<deploy::XPackageManager> const & xPackageMgr,
537 uno::Sequence<beans::NamedValue> const & properties,
538 css::uno::Reference<css::deployment::XPackage> const & xTmpExtension,
539 Reference<task::XAbortChannel> const & xAbortChannel,
540 Reference<ucb::XCommandEnvironment> const & xCmdEnv,
541 Reference<deploy::XPackage> & out_existingExtension )
542 throw (deploy::DeploymentException,
543 ucb::CommandFailedException,
544 ucb::CommandAbortedException,
545 lang::IllegalArgumentException,
546 uno::RuntimeException)
550 Reference<deploy::XPackage> xOldExtension;
551 const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
552 const OUString sFileName = xTmpExtension->getName();
553 const OUString sDisplayName = xTmpExtension->getDisplayName();
554 const OUString sVersion = xTmpExtension->getVersion();
558 xOldExtension = xPackageMgr->getDeployedPackage(
559 sIdentifier, sFileName, xCmdEnv);
560 out_existingExtension = xOldExtension;
562 catch (const lang::IllegalArgumentException &)
565 bool bCanInstall = false;
567 //This part is not guarded against other threads removing, adding, disabling ...
568 //etc. the same extension.
569 //checkInstall is safe because it notifies the user if the extension is not yet
570 //installed in the same repository. Because addExtension has its own guard
571 //(m_addMutex), another thread cannot add the extension in the meantime.
572 //checkUpdate is called if the same extension exists in the same
573 //repository. The user is asked if they want to replace it. Another
574 //thread
575 //could already remove the extension. So asking the user was not
576 //necessary. No harm is done. The other thread may also ask the user
577 //if he wants to remove the extension. This depends on the
578 //XCommandEnvironment which it passes to removeExtension.
579 if (xOldExtension.is())
581 //throws a CommandFailedException if the user cancels
582 //the action.
583 checkUpdate(sVersion, sDisplayName,xOldExtension, xCmdEnv);
585 else
587 //throws a CommandFailedException if the user cancels
588 //the action.
589 checkInstall(sDisplayName, xCmdEnv);
591 //Prevent showing the license if requested.
592 Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv);
593 ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>(), m_xContext);
595 dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL()));
596 const ::boost::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes =
597 info.getSimpleLicenseAttributes();
599 if (licenseAttributes && licenseAttributes->suppressIfRequired
600 && props.isSuppressedLicense())
601 _xCmdEnv = Reference<ucb::XCommandEnvironment>(
602 new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler()));
604 bCanInstall = xTmpExtension->checkPrerequisites(
605 xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0 ? true : false;
607 return bCanInstall;
609 catch ( const deploy::DeploymentException& ) {
610 throw;
611 } catch ( const ucb::CommandFailedException & ) {
612 throw;
613 } catch ( const ucb::CommandAbortedException & ) {
614 throw;
615 } catch (const lang::IllegalArgumentException &) {
616 throw;
617 } catch (const uno::RuntimeException &) {
618 throw;
619 } catch (const uno::Exception &) {
620 uno::Any excOccurred = ::cppu::getCaughtException();
621 deploy::DeploymentException exc(
622 "Extension Manager: exception in doChecksForAddExtension",
623 static_cast<OWeakObject*>(this), excOccurred);
624 throw exc;
625 } catch (...) {
626 throw uno::RuntimeException(
627 "Extension Manager: unexpected exception in doChecksForAddExtension",
628 static_cast<OWeakObject*>(this));
632 // Only add to shared and user repository
633 Reference<deploy::XPackage> ExtensionManager::addExtension(
634 OUString const & url, uno::Sequence<beans::NamedValue> const & properties,
635 OUString const & repository,
636 Reference<task::XAbortChannel> const & xAbortChannel,
637 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
638 throw (deploy::DeploymentException,
639 ucb::CommandFailedException,
640 ucb::CommandAbortedException,
641 lang::IllegalArgumentException,
642 uno::RuntimeException)
644 Reference<deploy::XPackage> xNewExtension;
645 //Determine the repository to use
646 Reference<deploy::XPackageManager> xPackageManager;
647 if (repository == "user")
648 xPackageManager = getUserRepository();
649 else if (repository == "shared")
650 xPackageManager = getSharedRepository();
651 else
652 throw lang::IllegalArgumentException(
653 "No valid repository name provided.",
654 static_cast<cppu::OWeakObject*>(this), 0);
655 //We must make sure that the xTmpExtension is not create twice, because this
656 //would remove the first one.
657 ::osl::MutexGuard addGuard(m_addMutex);
659 Reference<deploy::XPackageManager> xTmpRepository(getTmpRepository());
660 // make sure xTmpRepository is alive as long as xTmpExtension is; as
661 // the "tmp" manager is only held weakly by m_xPackageManagerFactory, it
662 // could otherwise be disposed early, which would in turn dispose
663 // xTmpExtension's PackageRegistryBackend behind its back
664 Reference<deploy::XPackage> xTmpExtension(
665 xTmpRepository->addPackage(
666 url, uno::Sequence<beans::NamedValue>(), OUString(), xAbortChannel,
667 new TmpRepositoryCommandEnv()));
668 if (!xTmpExtension.is()) {
669 throw deploy::DeploymentException(
670 ("Extension Manager: Failed to create temporary XPackage for url: "
671 + url),
672 static_cast<OWeakObject*>(this), uno::Any());
675 //Make sure the extension is removed from the tmp repository in case
676 //of an exception
677 ExtensionRemoveGuard tmpExtensionRemoveGuard(xTmpExtension, getTmpRepository());
678 ExtensionRemoveGuard bakExtensionRemoveGuard;
679 const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
680 const OUString sFileName = xTmpExtension->getName();
681 Reference<deploy::XPackage> xOldExtension;
682 Reference<deploy::XPackage> xExtensionBackup;
684 uno::Any excOccurred2;
685 bool bUserDisabled = false;
686 bool bCanInstall = doChecksForAddExtension(
687 xPackageManager,
688 properties,
689 xTmpExtension,
690 xAbortChannel,
691 xCmdEnv,
692 xOldExtension );
695 // In this garded section (getMutex) we must not use the argument xCmdEnv
696 // because it may bring up dialogs (XInteractionHandler::handle) this
697 //may potententially deadlock. See issue
698 //http://qa.openoffice.org/issues/show_bug.cgi?id=114933
699 //By not providing xCmdEnv the underlying APIs will throw an exception if
700 //the XInteractionRequest cannot be handled
701 ::osl::MutexGuard guard(getMutex());
703 if (bCanInstall)
707 bUserDisabled = isUserDisabled(sIdentifier, sFileName);
708 if (xOldExtension.is())
712 xOldExtension->revokePackage(
713 false, xAbortChannel, Reference<ucb::XCommandEnvironment>());
714 //save the old user extension in case the user aborts
715 xExtensionBackup = getBakRepository()->importExtension(
716 xOldExtension, Reference<task::XAbortChannel>(),
717 Reference<ucb::XCommandEnvironment>());
718 bakExtensionRemoveGuard.set(xExtensionBackup, getBakRepository());
720 catch (const lang::DisposedException &)
722 //Another thread might have removed the extension meanwhile
725 //check again dependencies but prevent user interaction,
726 //We can disregard the license, because the user must have already
727 //accepted it, when we called checkPrerequisites the first time
728 SilentCheckPrerequisitesCommandEnv * pSilentCommandEnv =
729 new SilentCheckPrerequisitesCommandEnv();
730 Reference<ucb::XCommandEnvironment> silentCommandEnv(pSilentCommandEnv);
732 sal_Int32 failedPrereq = xTmpExtension->checkPrerequisites(
733 xAbortChannel, silentCommandEnv, true);
734 if (failedPrereq == 0)
736 xNewExtension = xPackageManager->addPackage(
737 url, properties, OUString(), xAbortChannel,
738 Reference<ucb::XCommandEnvironment>());
739 //If we add a user extension and there is already one which was
740 //disabled by a user, then the newly installed one is enabled. If we
741 //add to another repository then the user extension remains
742 //disabled.
743 bool bUserDisabled2 = bUserDisabled;
744 if (repository == "user")
745 bUserDisabled2 = false;
747 // pass the two values via variables to workaround gcc-4.3.4 specific bug (bnc#655912)
748 OUString sNewExtensionIdentifier = dp_misc::getIdentifier(xNewExtension);
749 OUString sNewExtensionFileName = xNewExtension->getName();
751 activateExtension(
752 sNewExtensionIdentifier, sNewExtensionFileName,
753 bUserDisabled2, false, xAbortChannel,
754 Reference<ucb::XCommandEnvironment>());
756 else
758 if (pSilentCommandEnv->m_Exception.hasValue())
759 ::cppu::throwException(pSilentCommandEnv->m_Exception);
760 else if ( pSilentCommandEnv->m_UnknownException.hasValue())
761 ::cppu::throwException(pSilentCommandEnv->m_UnknownException);
762 else
763 throw deploy::DeploymentException (
764 "Extension Manager: exception during addExtension, ckeckPrerequisites failed",
765 static_cast<OWeakObject*>(this), uno::Any());
768 catch ( const deploy::DeploymentException& ) {
769 excOccurred2 = ::cppu::getCaughtException();
770 } catch ( const ucb::CommandFailedException & ) {
771 excOccurred2 = ::cppu::getCaughtException();
772 } catch ( const ucb::CommandAbortedException & ) {
773 excOccurred2 = ::cppu::getCaughtException();
774 } catch (const lang::IllegalArgumentException &) {
775 excOccurred2 = ::cppu::getCaughtException();
776 } catch (const uno::RuntimeException &) {
777 excOccurred2 = ::cppu::getCaughtException();
778 } catch (...) {
779 excOccurred2 = ::cppu::getCaughtException();
780 deploy::DeploymentException exc(
781 "Extension Manager: exception during addExtension, url: "
782 + url, static_cast<OWeakObject*>(this), excOccurred2);
783 excOccurred2 <<= exc;
787 if (excOccurred2.hasValue())
789 //It does not matter what exception is thrown. We try to
790 //recover the original status.
791 //If the user aborted installation then a ucb::CommandAbortedException
792 //is thrown.
793 //Use a private AbortChannel so the user cannot interrupt.
796 if (xExtensionBackup.is())
798 Reference<deploy::XPackage> xRestored =
799 xPackageManager->importExtension(
800 xExtensionBackup, Reference<task::XAbortChannel>(),
801 Reference<ucb::XCommandEnvironment>());
803 activateExtension(
804 sIdentifier, sFileName, bUserDisabled, false,
805 Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
807 catch (...)
810 ::cppu::throwException(excOccurred2);
812 } // leaving the garded section (getMutex())
816 fireModified();
818 }catch ( const deploy::DeploymentException& ) {
819 throw;
820 } catch ( const ucb::CommandFailedException & ) {
821 throw;
822 } catch ( const ucb::CommandAbortedException & ) {
823 throw;
824 } catch (const lang::IllegalArgumentException &) {
825 throw;
826 } catch (const uno::RuntimeException &) {
827 throw;
828 } catch (const uno::Exception &) {
829 uno::Any excOccurred = ::cppu::getCaughtException();
830 deploy::DeploymentException exc(
831 "Extension Manager: exception in doChecksForAddExtension",
832 static_cast<OWeakObject*>(this), excOccurred);
833 throw exc;
834 } catch (...) {
835 throw uno::RuntimeException(
836 "Extension Manager: unexpected exception in doChecksForAddExtension",
837 static_cast<OWeakObject*>(this));
840 return xNewExtension;
843 void ExtensionManager::removeExtension(
844 OUString const & identifier, OUString const & fileName,
845 OUString const & repository,
846 Reference<task::XAbortChannel> const & xAbortChannel,
847 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
848 throw (deploy::DeploymentException,
849 ucb::CommandFailedException,
850 ucb::CommandAbortedException,
851 lang::IllegalArgumentException,
852 uno::RuntimeException)
854 uno::Any excOccurred1;
855 Reference<deploy::XPackage> xExtensionBackup;
856 Reference<deploy::XPackageManager> xPackageManager;
857 bool bUserDisabled = false;
858 ::osl::MutexGuard guard(getMutex());
861 //Determine the repository to use
862 if (repository == "user")
863 xPackageManager = getUserRepository();
864 else if (repository == "shared")
865 xPackageManager = getSharedRepository();
866 else
867 throw lang::IllegalArgumentException(
868 "No valid repository name provided.",
869 static_cast<cppu::OWeakObject*>(this), 0);
871 bUserDisabled = isUserDisabled(identifier, fileName);
872 //Backup the extension, in case the user cancels the action
873 xExtensionBackup = backupExtension(
874 identifier, fileName, xPackageManager, xCmdEnv);
876 //revoke the extension if it is active
877 Reference<deploy::XPackage> xOldExtension =
878 xPackageManager->getDeployedPackage(
879 identifier, fileName, xCmdEnv);
880 xOldExtension->revokePackage(false, xAbortChannel, xCmdEnv);
882 xPackageManager->removePackage(
883 identifier, fileName, xAbortChannel, xCmdEnv);
884 activateExtension(identifier, fileName, bUserDisabled, false,
885 xAbortChannel, xCmdEnv);
886 fireModified();
888 catch ( const deploy::DeploymentException& ) {
889 excOccurred1 = ::cppu::getCaughtException();
890 } catch ( const ucb::CommandFailedException & ) {
891 excOccurred1 = ::cppu::getCaughtException();
892 } catch ( const ucb::CommandAbortedException & ) {
893 excOccurred1 = ::cppu::getCaughtException();
894 } catch (const lang::IllegalArgumentException &) {
895 excOccurred1 = ::cppu::getCaughtException();
896 } catch (const uno::RuntimeException &) {
897 excOccurred1 = ::cppu::getCaughtException();
898 } catch (...) {
899 excOccurred1 = ::cppu::getCaughtException();
900 deploy::DeploymentException exc(
901 "Extension Manager: exception during removeEtension",
902 static_cast<OWeakObject*>(this), excOccurred1);
903 excOccurred1 <<= exc;
906 if (excOccurred1.hasValue())
908 //User aborted installation, restore the previous situation.
909 //Use a private AbortChannel so the user cannot interrupt.
912 Reference<ucb::XCommandEnvironment> tmpCmdEnv(
913 new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler()));
914 if (xExtensionBackup.is())
916 Reference<deploy::XPackage> xRestored =
917 xPackageManager->importExtension(
918 xExtensionBackup, Reference<task::XAbortChannel>(),
919 tmpCmdEnv);
920 activateExtension(
921 identifier, fileName, bUserDisabled, false,
922 Reference<task::XAbortChannel>(),
923 tmpCmdEnv);
925 getTmpRepository()->removePackage(
926 dp_misc::getIdentifier(xExtensionBackup),
927 xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
928 fireModified();
931 catch (...)
934 ::cppu::throwException(excOccurred1);
937 if (xExtensionBackup.is())
938 getTmpRepository()->removePackage(
939 dp_misc::getIdentifier(xExtensionBackup),
940 xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
943 // Only enable extensions from shared and user repository
944 void ExtensionManager::enableExtension(
945 Reference<deploy::XPackage> const & extension,
946 Reference<task::XAbortChannel> const & xAbortChannel,
947 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
948 throw (deploy::DeploymentException,
949 ucb::CommandFailedException,
950 ucb::CommandAbortedException,
951 lang::IllegalArgumentException,
952 uno::RuntimeException)
954 ::osl::MutexGuard guard(getMutex());
955 bool bUserDisabled = false;
956 uno::Any excOccurred;
959 if (!extension.is())
960 return;
961 OUString repository = extension->getRepositoryName();
962 if (!(repository == "user"))
963 throw lang::IllegalArgumentException(
964 "No valid repository name provided.",
965 static_cast<cppu::OWeakObject*>(this), 0);
967 bUserDisabled = isUserDisabled(dp_misc::getIdentifier(extension),
968 extension->getName());
970 activateExtension(dp_misc::getIdentifier(extension),
971 extension->getName(), false, false,
972 xAbortChannel, xCmdEnv);
974 catch ( const deploy::DeploymentException& ) {
975 excOccurred = ::cppu::getCaughtException();
976 } catch ( const ucb::CommandFailedException & ) {
977 excOccurred = ::cppu::getCaughtException();
978 } catch ( const ucb::CommandAbortedException & ) {
979 excOccurred = ::cppu::getCaughtException();
980 } catch (const lang::IllegalArgumentException &) {
981 excOccurred = ::cppu::getCaughtException();
982 } catch (const uno::RuntimeException &) {
983 excOccurred = ::cppu::getCaughtException();
984 } catch (...) {
985 excOccurred = ::cppu::getCaughtException();
986 deploy::DeploymentException exc(
987 "Extension Manager: exception during enableExtension",
988 static_cast<OWeakObject*>(this), excOccurred);
989 excOccurred <<= exc;
992 if (excOccurred.hasValue())
996 activateExtension(dp_misc::getIdentifier(extension),
997 extension->getName(), bUserDisabled, false,
998 xAbortChannel, xCmdEnv);
1000 catch (...)
1003 ::cppu::throwException(excOccurred);
1009 sal_Int32 ExtensionManager::checkPrerequisitesAndEnable(
1010 Reference<deploy::XPackage> const & extension,
1011 Reference<task::XAbortChannel> const & xAbortChannel,
1012 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
1013 throw (deploy::DeploymentException,
1014 ucb::CommandFailedException,
1015 ucb::CommandAbortedException,
1016 lang::IllegalArgumentException,
1017 uno::RuntimeException)
1021 if (!extension.is())
1022 return 0;
1023 ::osl::MutexGuard guard(getMutex());
1024 sal_Int32 ret = 0;
1025 Reference<deploy::XPackageManager> mgr =
1026 getPackageManager(extension->getRepositoryName());
1027 ret = mgr->checkPrerequisites(extension, xAbortChannel, xCmdEnv);
1028 if (ret)
1030 //There are some unfulfilled prerequisites, try to revoke
1031 extension->revokePackage(false, xAbortChannel, xCmdEnv);
1033 const OUString id(dp_misc::getIdentifier(extension));
1034 activateExtension(id, extension->getName(),
1035 isUserDisabled(id, extension->getName()), false,
1036 xAbortChannel, xCmdEnv);
1037 return ret;
1039 catch ( const deploy::DeploymentException& ) {
1040 throw;
1041 } catch ( const ucb::CommandFailedException & ) {
1042 throw;
1043 } catch ( const ucb::CommandAbortedException & ) {
1044 throw;
1045 } catch (const lang::IllegalArgumentException &) {
1046 throw;
1047 } catch (const uno::RuntimeException &) {
1048 throw;
1049 } catch (...) {
1050 uno::Any excOccurred = ::cppu::getCaughtException();
1051 deploy::DeploymentException exc(
1052 "Extension Manager: exception during disableExtension",
1053 static_cast<OWeakObject*>(this), excOccurred);
1054 throw exc;
1058 void ExtensionManager::disableExtension(
1059 Reference<deploy::XPackage> const & extension,
1060 Reference<task::XAbortChannel> const & xAbortChannel,
1061 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1062 throw (deploy::DeploymentException,
1063 ucb::CommandFailedException,
1064 ucb::CommandAbortedException,
1065 lang::IllegalArgumentException,
1066 uno::RuntimeException)
1068 ::osl::MutexGuard guard(getMutex());
1069 uno::Any excOccurred;
1070 bool bUserDisabled = false;
1073 if (!extension.is())
1074 return;
1075 const OUString repository( extension->getRepositoryName());
1076 if (! (repository == "user"))
1077 throw lang::IllegalArgumentException(
1078 "No valid repository name provided.",
1079 static_cast<cppu::OWeakObject*>(this), 0);
1081 const OUString id(dp_misc::getIdentifier(extension));
1082 bUserDisabled = isUserDisabled(id, extension->getName());
1084 activateExtension(id, extension->getName(), true, false,
1085 xAbortChannel, xCmdEnv);
1087 catch ( const deploy::DeploymentException& ) {
1088 excOccurred = ::cppu::getCaughtException();
1089 } catch ( const ucb::CommandFailedException & ) {
1090 excOccurred = ::cppu::getCaughtException();
1091 } catch ( const ucb::CommandAbortedException & ) {
1092 excOccurred = ::cppu::getCaughtException();
1093 } catch (const lang::IllegalArgumentException &) {
1094 excOccurred = ::cppu::getCaughtException();
1095 } catch (const uno::RuntimeException &) {
1096 excOccurred = ::cppu::getCaughtException();
1097 } catch (...) {
1098 excOccurred = ::cppu::getCaughtException();
1099 deploy::DeploymentException exc(
1100 "Extension Manager: exception during disableExtension",
1101 static_cast<OWeakObject*>(this), excOccurred);
1102 excOccurred <<= exc;
1105 if (excOccurred.hasValue())
1109 activateExtension(dp_misc::getIdentifier(extension),
1110 extension->getName(), bUserDisabled, false,
1111 xAbortChannel, xCmdEnv);
1113 catch (...)
1116 ::cppu::throwException(excOccurred);
1120 uno::Sequence< Reference<deploy::XPackage> >
1121 ExtensionManager::getDeployedExtensions(
1122 OUString const & repository,
1123 Reference<task::XAbortChannel> const &xAbort,
1124 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1125 throw (deploy::DeploymentException,
1126 ucb::CommandFailedException,
1127 ucb::CommandAbortedException,
1128 lang::IllegalArgumentException,
1129 uno::RuntimeException)
1131 return getPackageManager(repository)->getDeployedPackages(
1132 xAbort, xCmdEnv);
1135 Reference<deploy::XPackage>
1136 ExtensionManager::getDeployedExtension(
1137 OUString const & repository,
1138 OUString const & identifier,
1139 OUString const & filename,
1140 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1141 throw (deploy::DeploymentException,
1142 ucb::CommandFailedException,
1143 lang::IllegalArgumentException,
1144 uno::RuntimeException)
1146 return getPackageManager(repository)->getDeployedPackage(
1147 identifier, filename, xCmdEnv);
1150 uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > >
1151 ExtensionManager::getAllExtensions(
1152 Reference<task::XAbortChannel> const & xAbort,
1153 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1154 throw (deploy::DeploymentException,
1155 ucb::CommandFailedException,
1156 ucb::CommandAbortedException,
1157 lang::IllegalArgumentException,
1158 uno::RuntimeException)
1162 id2extensions mapExt;
1164 uno::Sequence<Reference<deploy::XPackage> > userExt =
1165 getUserRepository()->getDeployedPackages(xAbort, xCmdEnv);
1166 addExtensionsToMap(mapExt, userExt, "user");
1167 uno::Sequence<Reference<deploy::XPackage> > sharedExt =
1168 getSharedRepository()->getDeployedPackages(xAbort, xCmdEnv);
1169 addExtensionsToMap(mapExt, sharedExt, "shared");
1170 uno::Sequence<Reference<deploy::XPackage> > bundledExt =
1171 getBundledRepository()->getDeployedPackages(xAbort, xCmdEnv);
1172 addExtensionsToMap(mapExt, bundledExt, "bundled");
1174 // Create the tmp repository to trigger its clean up (deletion
1175 // of old temporary data.)
1176 getTmpRepository();
1178 //copy the values of the map to a vector for sorting
1179 ::std::vector< ::std::vector<Reference<deploy::XPackage> > >
1180 vecExtensions;
1181 id2extensions::const_iterator mapIt = mapExt.begin();
1182 for (;mapIt != mapExt.end(); ++mapIt)
1183 vecExtensions.push_back(mapIt->second);
1185 //sort the element according to the identifier
1186 ::std::sort(vecExtensions.begin(), vecExtensions.end(), CompIdentifiers());
1188 ::std::vector< ::std::vector<Reference<deploy::XPackage> > >::const_iterator
1189 citVecVec = vecExtensions.begin();
1190 sal_Int32 j = 0;
1191 uno::Sequence< uno::Sequence<Reference<deploy::XPackage> > > seqSeq(vecExtensions.size());
1192 for (;citVecVec != vecExtensions.end(); ++citVecVec, j++)
1194 seqSeq[j] = comphelper::containerToSequence(*citVecVec);
1196 return seqSeq;
1198 } catch ( const deploy::DeploymentException& ) {
1199 throw;
1200 } catch ( const ucb::CommandFailedException & ) {
1201 throw;
1202 } catch ( const ucb::CommandAbortedException & ) {
1203 throw;
1204 } catch (const lang::IllegalArgumentException &) {
1205 throw;
1206 } catch (const uno::RuntimeException &) {
1207 throw;
1208 } catch (...) {
1209 uno::Any exc = ::cppu::getCaughtException();
1210 throw deploy::DeploymentException(
1211 "Extension Manager: exception during enableExtension",
1212 static_cast<OWeakObject*>(this), exc);
1216 // Only to be called from unopkg or soffice bootstrap (with force=true in the
1217 // latter case):
1218 void ExtensionManager::reinstallDeployedExtensions(
1219 sal_Bool force, OUString const & repository,
1220 Reference<task::XAbortChannel> const & xAbortChannel,
1221 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1222 throw (deploy::DeploymentException,
1223 ucb::CommandFailedException, ucb::CommandAbortedException,
1224 lang::IllegalArgumentException, uno::RuntimeException)
1228 Reference<deploy::XPackageManager>
1229 xPackageManager = getPackageManager(repository);
1231 std::set< OUString > disabledExts;
1233 const uno::Sequence< Reference<deploy::XPackage> > extensions(
1234 xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv));
1235 for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos )
1239 beans::Optional< beans::Ambiguous< sal_Bool > > registered(
1240 extensions[pos]->isRegistered(xAbortChannel, xCmdEnv));
1241 if (registered.IsPresent &&
1242 !(registered.Value.IsAmbiguous ||
1243 registered.Value.Value))
1245 const OUString id = dp_misc::getIdentifier(extensions[ pos ]);
1246 OSL_ASSERT(!id.isEmpty());
1247 disabledExts.insert(id);
1250 catch (const lang::DisposedException &)
1256 ::osl::MutexGuard guard(getMutex());
1257 xPackageManager->reinstallDeployedPackages(
1258 force, xAbortChannel, xCmdEnv);
1259 //We must sync here, otherwise we will get exceptions when extensions
1260 //are removed.
1261 dp_misc::syncRepositories(force, xCmdEnv);
1262 const uno::Sequence< Reference<deploy::XPackage> > extensions(
1263 xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv));
1265 for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos )
1269 const OUString id = dp_misc::getIdentifier(extensions[ pos ]);
1270 const OUString fileName = extensions[ pos ]->getName();
1271 OSL_ASSERT(!id.isEmpty());
1272 activateExtension(
1273 id, fileName, disabledExts.find(id) != disabledExts.end(),
1274 true, xAbortChannel, xCmdEnv );
1276 catch (const lang::DisposedException &)
1280 } catch ( const deploy::DeploymentException& ) {
1281 throw;
1282 } catch ( const ucb::CommandFailedException & ) {
1283 throw;
1284 } catch ( const ucb::CommandAbortedException & ) {
1285 throw;
1286 } catch (const lang::IllegalArgumentException &) {
1287 throw;
1288 } catch (const uno::RuntimeException &) {
1289 throw;
1290 } catch (...) {
1291 uno::Any exc = ::cppu::getCaughtException();
1292 throw deploy::DeploymentException(
1293 "Extension Manager: exception during enableExtension",
1294 static_cast<OWeakObject*>(this), exc);
1298 sal_Bool ExtensionManager::synchronize(
1299 Reference<task::XAbortChannel> const & xAbortChannel,
1300 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1301 throw (deploy::DeploymentException,
1302 ucb::CommandFailedException,
1303 ucb::CommandAbortedException,
1304 lang::IllegalArgumentException,
1305 uno::RuntimeException)
1309 ::osl::MutexGuard guard(getMutex());
1310 String sSynchronizingShared(StrSyncRepository::get());
1311 sSynchronizingShared.SearchAndReplaceAllAscii( "%NAME", OUString("shared"));
1312 dp_misc::ProgressLevel progressShared(xCmdEnv, sSynchronizingShared);
1313 sal_Bool bModified = getSharedRepository()->synchronize(xAbortChannel, xCmdEnv);
1314 progressShared.update("\n\n");
1316 String sSynchronizingBundled(StrSyncRepository::get());
1317 sSynchronizingBundled.SearchAndReplaceAllAscii( "%NAME", OUString("bundled"));
1318 dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled);
1319 bModified |= getBundledRepository()->synchronize(xAbortChannel, xCmdEnv);
1320 progressBundled.update("\n\n");
1322 //Always determine the active extension.
1323 //TODO: Is this still necessary? (It used to be necessary for the
1324 // first-start optimization: The setup created the registration data
1325 // for the bundled extensions (share/prereg/bundled) which was copied to
1326 // the user installation when a user started OOo for the first time
1327 // after running setup. All bundled extensions were registered at that
1328 // moment. However, extensions with the same identifier could be in the
1329 // shared or user repository, in which case the respective bundled
1330 // extensions had to be revoked.)
1333 const uno::Sequence<uno::Sequence<Reference<deploy::XPackage> > >
1334 seqSeqExt = getAllExtensions(xAbortChannel, xCmdEnv);
1335 for (sal_Int32 i = 0; i < seqSeqExt.getLength(); i++)
1337 uno::Sequence<Reference<deploy::XPackage> > const & seqExt =
1338 seqSeqExt[i];
1339 activateExtension(seqExt, isUserDisabled(seqExt), true,
1340 xAbortChannel, xCmdEnv);
1343 catch (...)
1345 //We catch the exception, so we can write the lastmodified file
1346 //so we will no repeat this everytime OOo starts.
1347 OSL_FAIL("Extensions Manager: synchronize");
1349 OUString lastSyncBundled("$BUNDLED_EXTENSIONS_USER/lastsynchronized");
1350 writeLastModified(lastSyncBundled, xCmdEnv, m_xContext);
1351 OUString lastSyncShared("$SHARED_EXTENSIONS_USER/lastsynchronized");
1352 writeLastModified(lastSyncShared, xCmdEnv, m_xContext);
1353 return bModified;
1354 } catch ( const deploy::DeploymentException& ) {
1355 throw;
1356 } catch ( const ucb::CommandFailedException & ) {
1357 throw;
1358 } catch ( const ucb::CommandAbortedException & ) {
1359 throw;
1360 } catch (const lang::IllegalArgumentException &) {
1361 throw;
1362 } catch (const uno::RuntimeException &) {
1363 throw;
1364 } catch (...) {
1365 uno::Any exc = ::cppu::getCaughtException();
1366 throw deploy::DeploymentException(
1367 "Extension Manager: exception in synchronize",
1368 static_cast<OWeakObject*>(this), exc);
1372 // Notify the user when a new extension is to be installed. This is only the
1373 // case when one uses the system integration to install an extension (double
1374 // clicking on .oxt file etc.)). The function must only be called if there is no
1375 // extension with the same identifier already deployed. Then the checkUpdate
1376 // function will inform the user that the extension is about to be installed In
1377 // case the user cancels the installation a CommandFailed exception is
1378 // thrown.
1379 void ExtensionManager::checkInstall(
1380 OUString const & displayName,
1381 Reference<ucb::XCommandEnvironment> const & cmdEnv)
1383 uno::Any request(
1384 deploy::InstallException(
1385 "Extension " + displayName +
1386 " is about to be installed.",
1387 static_cast<OWeakObject *>(this), displayName));
1388 bool approve = false, abort = false;
1389 if (! dp_misc::interactContinuation(
1390 request, task::XInteractionApprove::static_type(),
1391 cmdEnv, &approve, &abort ))
1393 OSL_ASSERT( !approve && !abort );
1394 throw deploy::DeploymentException(
1395 dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName,
1396 static_cast<OWeakObject *>(this), request );
1398 if (abort || !approve)
1399 throw ucb::CommandFailedException(
1400 dp_misc::getResourceString(RID_STR_ERROR_WHILE_ADDING) + displayName,
1401 static_cast<OWeakObject *>(this), request );
1404 /* The function will make the user interaction in case there is an extension
1405 installed with the same id. This function may only be called if there is already
1406 an extension.
1408 void ExtensionManager::checkUpdate(
1409 OUString const & newVersion,
1410 OUString const & newDisplayName,
1411 Reference<deploy::XPackage> const & oldExtension,
1412 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1414 // package already deployed, interact --force:
1415 uno::Any request(
1416 (deploy::VersionException(
1417 dp_misc::getResourceString(
1418 RID_STR_PACKAGE_ALREADY_ADDED ) + newDisplayName,
1419 static_cast<OWeakObject *>(this), newVersion, newDisplayName,
1420 oldExtension ) ) );
1421 bool replace = false, abort = false;
1422 if (! dp_misc::interactContinuation(
1423 request, task::XInteractionApprove::static_type(),
1424 xCmdEnv, &replace, &abort )) {
1425 OSL_ASSERT( !replace && !abort );
1426 throw deploy::DeploymentException(
1427 dp_misc::getResourceString(
1428 RID_STR_ERROR_WHILE_ADDING) + newDisplayName,
1429 static_cast<OWeakObject *>(this), request );
1431 if (abort || !replace)
1432 throw ucb::CommandFailedException(
1433 dp_misc::getResourceString(
1434 RID_STR_PACKAGE_ALREADY_ADDED) + newDisplayName,
1435 static_cast<OWeakObject *>(this), request );
1438 uno::Sequence<Reference<deploy::XPackage> > SAL_CALL
1439 ExtensionManager::getExtensionsWithUnacceptedLicenses(
1440 OUString const & repository,
1441 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
1442 throw (deploy::DeploymentException,
1443 uno::RuntimeException)
1445 Reference<deploy::XPackageManager>
1446 xPackageManager = getPackageManager(repository);
1447 ::osl::MutexGuard guard(getMutex());
1448 return xPackageManager->getExtensionsWithUnacceptedLicenses(xCmdEnv);
1451 sal_Bool ExtensionManager::isReadOnlyRepository(OUString const & repository)
1452 throw (uno::RuntimeException)
1454 return getPackageManager(repository)->isReadOnly();
1456 //------------------------------------------------------------------------------
1458 namespace sdecl = comphelper::service_decl;
1459 sdecl::class_<ExtensionManager> servicePIP;
1460 extern sdecl::ServiceDecl const serviceDecl(
1461 servicePIP,
1462 // a private one:
1463 "com.sun.star.comp.deployment.ExtensionManager",
1464 "com.sun.star.comp.deployment.ExtensionManager");
1466 // XModifyBroadcaster
1467 //______________________________________________________________________________
1468 void ExtensionManager::addModifyListener(
1469 Reference<util::XModifyListener> const & xListener )
1470 throw (uno::RuntimeException)
1472 check();
1473 rBHelper.addListener( ::getCppuType( &xListener ), xListener );
1476 //______________________________________________________________________________
1477 void ExtensionManager::removeModifyListener(
1478 Reference<util::XModifyListener> const & xListener )
1479 throw (uno::RuntimeException)
1481 check();
1482 rBHelper.removeListener( ::getCppuType( &xListener ), xListener );
1485 void ExtensionManager::check()
1487 ::osl::MutexGuard guard( getMutex() );
1488 if (rBHelper.bInDispose || rBHelper.bDisposed) {
1489 throw lang::DisposedException(
1490 "ExtensionManager instance has already been disposed!",
1491 static_cast<OWeakObject *>(this) );
1495 void ExtensionManager::fireModified()
1497 ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer(
1498 util::XModifyListener::static_type() );
1499 if (pContainer != 0) {
1500 pContainer->forEach<util::XModifyListener>(
1501 boost::bind(&util::XModifyListener::modified, _1,
1502 lang::EventObject(static_cast<OWeakObject *>(this))) );
1506 } // namespace dp_manager
1508 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */