Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / desktop / source / deployment / manager / dp_extensionmanager.cxx
blobfae8afe53e623e4507a2e5f27c95d2df52ba12de
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/compbase.hxx>
23 #include <comphelper/servicedecl.hxx>
24 #include <cppuhelper/exc_hlp.hxx>
25 #include <rtl/bootstrap.hxx>
26 #include <com/sun/star/deployment/DeploymentException.hpp>
27 #include <com/sun/star/deployment/ExtensionManager.hpp>
28 #include <com/sun/star/deployment/XExtensionManager.hpp>
29 #include <com/sun/star/deployment/thePackageManagerFactory.hpp>
30 #include <com/sun/star/deployment/XPackageManager.hpp>
31 #include <com/sun/star/deployment/XPackageManagerFactory.hpp>
32 #include <com/sun/star/deployment/XPackage.hpp>
33 #include <com/sun/star/deployment/InstallException.hpp>
34 #include <com/sun/star/deployment/VersionException.hpp>
35 #include <com/sun/star/deployment/LicenseException.hpp>
36 #include <com/sun/star/lang/IllegalArgumentException.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/registry/XRegistryKey.hpp>
39 #include <com/sun/star/beans/Optional.hpp>
40 #include <com/sun/star/task/XInteractionApprove.hpp>
41 #include <com/sun/star/beans/Ambiguous.hpp>
42 #include <com/sun/star/ucb/CommandAbortedException.hpp>
43 #include <com/sun/star/ucb/CommandFailedException.hpp>
44 #include <com/sun/star/uno/XComponentContext.hpp>
45 #include <com/sun/star/io/XInputStream.hpp>
46 #include <com/sun/star/util/XModifyBroadcaster.hpp>
47 #include <comphelper/sequence.hxx>
48 #include <xmlscript/xml_helper.hxx>
49 #include <osl/diagnose.h>
50 #include <vcl/svapp.hxx>
51 #include <dp_interact.h>
52 #include <dp_resource.h>
53 #include <dp_services.hxx>
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"
61 #include <vector>
62 #include <algorithm>
63 #include <set>
65 namespace lang = com::sun::star::lang;
66 namespace task = com::sun::star::task;
67 namespace ucb = com::sun::star::ucb;
68 namespace uno = com::sun::star::uno;
69 namespace beans = com::sun::star::beans;
70 namespace util = com::sun::star::util;
72 using ::com::sun::star::uno::Reference;
74 namespace {
76 struct CompIdentifiers
78 bool operator() (std::vector<Reference<css::deployment::XPackage> > const & a,
79 std::vector<Reference<css::deployment::XPackage> > const & b)
81 return getName(a).compareTo(getName(b)) < 0;
84 static OUString getName(std::vector<Reference<css::deployment::XPackage> > const & a);
87 OUString CompIdentifiers::getName(std::vector<Reference<css::deployment::XPackage> > const & a)
89 OSL_ASSERT(a.size() == 3);
90 //get the first non-null reference
91 Reference<css::deployment::XPackage> extension;
92 for (auto const& elem : a)
94 if (elem.is())
96 extension = elem;
97 break;
100 OSL_ASSERT(extension.is());
101 return extension->getDisplayName();
104 void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const & xCmdEnv, Reference< uno::XComponentContext > const & xContext)
106 //Write the lastmodified file
107 try {
108 ::rtl::Bootstrap::expandMacros(url);
109 ::ucbhelper::Content ucbStamp(url, xCmdEnv, xContext);
110 dp_misc::erase_path( url, xCmdEnv );
111 OString stamp("1" );
112 Reference<css::io::XInputStream> xData(
113 ::xmlscript::createInputStream(
114 reinterpret_cast<sal_Int8 const *>(stamp.getStr()),
115 stamp.getLength() ) );
116 ucbStamp.writeStream( xData, true /* replace existing */ );
118 catch(...)
120 uno::Any exc(::cppu::getCaughtException());
121 throw css::deployment::DeploymentException("Failed to update" + url, nullptr, exc);
125 class ExtensionRemoveGuard
127 css::uno::Reference<css::deployment::XPackage> m_extension;
128 css::uno::Reference<css::deployment::XPackageManager> m_xPackageManager;
130 public:
131 ExtensionRemoveGuard(){};
132 ExtensionRemoveGuard(
133 css::uno::Reference<css::deployment::XPackage> const & extension,
134 css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager):
135 m_extension(extension), m_xPackageManager(xPackageManager) {}
136 ~ExtensionRemoveGuard();
138 void set(css::uno::Reference<css::deployment::XPackage> const & extension,
139 css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager) {
140 m_extension = extension;
141 m_xPackageManager = xPackageManager;
145 ExtensionRemoveGuard::~ExtensionRemoveGuard()
147 try {
148 OSL_ASSERT(!(m_extension.is() && !m_xPackageManager.is()));
149 if (m_xPackageManager.is() && m_extension.is())
150 m_xPackageManager->removePackage(
151 dp_misc::getIdentifier(m_extension), OUString(),
152 css::uno::Reference<css::task::XAbortChannel>(),
153 css::uno::Reference<css::ucb::XCommandEnvironment>());
154 } catch (...) {
155 OSL_ASSERT(false);
161 namespace dp_manager {
163 //ToDo: bundled extension
164 ExtensionManager::ExtensionManager( Reference< uno::XComponentContext > const& xContext) :
165 ::cppu::WeakComponentImplHelper< css::deployment::XExtensionManager >(getMutex())
166 , m_xContext(xContext)
168 m_xPackageManagerFactory = css::deployment::thePackageManagerFactory::get(m_xContext);
169 OSL_ASSERT(m_xPackageManagerFactory.is());
171 m_repositoryNames.emplace_back("user");
172 m_repositoryNames.emplace_back("shared");
173 m_repositoryNames.emplace_back("bundled");
176 ExtensionManager::~ExtensionManager()
180 Reference<css::deployment::XPackageManager> ExtensionManager::getUserRepository()
182 return m_xPackageManagerFactory->getPackageManager("user");
184 Reference<css::deployment::XPackageManager> ExtensionManager::getSharedRepository()
186 return m_xPackageManagerFactory->getPackageManager("shared");
188 Reference<css::deployment::XPackageManager> ExtensionManager::getBundledRepository()
190 return m_xPackageManagerFactory->getPackageManager("bundled");
192 Reference<css::deployment::XPackageManager> ExtensionManager::getTmpRepository()
194 return m_xPackageManagerFactory->getPackageManager("tmp");
196 Reference<css::deployment::XPackageManager> ExtensionManager::getBakRepository()
198 return m_xPackageManagerFactory->getPackageManager("bak");
201 Reference<task::XAbortChannel> ExtensionManager::createAbortChannel()
203 return new dp_misc::AbortChannel;
206 css::uno::Reference<css::deployment::XPackageManager>
207 ExtensionManager::getPackageManager(OUString const & repository)
209 Reference<css::deployment::XPackageManager> xPackageManager;
210 if (repository == "user")
211 xPackageManager = getUserRepository();
212 else if (repository == "shared")
213 xPackageManager = getSharedRepository();
214 else if (repository == "bundled")
215 xPackageManager = getBundledRepository();
216 else if (repository == "tmp")
217 xPackageManager = getTmpRepository();
218 else if (repository == "bak")
219 xPackageManager = getBakRepository();
220 else
221 throw lang::IllegalArgumentException(
222 "No valid repository name provided.",
223 static_cast<cppu::OWeakObject*>(this), 0);
224 return xPackageManager;
228 Enters the XPackage objects into a map. They must be all from the
229 same repository. The value type of the map is a vector, where each vector
230 represents an extension with a particular identifier. The first member
231 represents the user extension, the second the shared extension and the
232 third the bundled extension.
234 void ExtensionManager::addExtensionsToMap(
235 id2extensions & mapExt,
236 uno::Sequence<Reference<css::deployment::XPackage> > const & seqExt,
237 OUString const & repository)
239 //Determine the index in the vector where these extensions are to be
240 //added.
241 int index = 0;
242 for (auto const& repositoryName : m_repositoryNames)
244 if (repositoryName == repository)
245 break;
246 ++index;
249 for (int i = 0; i < seqExt.getLength(); ++i)
251 Reference<css::deployment::XPackage> const & xExtension = seqExt[i];
252 OUString id = dp_misc::getIdentifier(xExtension);
253 id2extensions::iterator ivec = mapExt.find(id);
254 if (ivec == mapExt.end())
256 std::vector<Reference<css::deployment::XPackage> > vec(3);
257 vec[index] = xExtension;
258 mapExt[id] = vec;
260 else
262 ivec->second[index] = xExtension;
268 returns a list containing extensions with the same identifier from
269 all repositories (user, shared, bundled). If one repository does not
270 have this extension, then the list contains an empty Reference. The list
271 is ordered according to the priority of the repositories:
272 1. user
273 2. shared
274 3. bundled
276 The number of elements is always three, unless the number of repository
277 changes.
279 std::vector<Reference<css::deployment::XPackage> >
280 ExtensionManager::getExtensionsWithSameId(
281 OUString const & identifier, OUString const & fileName)
284 std::vector<Reference<css::deployment::XPackage> > extensionList;
285 Reference<css::deployment::XPackageManager> lRepos[] = {
286 getUserRepository(), getSharedRepository(), getBundledRepository() };
287 for (int i(0); i != SAL_N_ELEMENTS(lRepos); ++i)
289 Reference<css::deployment::XPackage> xPackage;
292 xPackage = lRepos[i]->getDeployedPackage(
293 identifier, fileName, Reference<ucb::XCommandEnvironment>());
295 catch(const lang::IllegalArgumentException &)
297 // thrown if the extension does not exist in this repository
299 extensionList.push_back(xPackage);
301 OSL_ASSERT(extensionList.size() == 3);
302 return extensionList;
305 uno::Sequence<Reference<css::deployment::XPackage> >
306 ExtensionManager::getExtensionsWithSameIdentifier(
307 OUString const & identifier,
308 OUString const & fileName,
309 Reference< ucb::XCommandEnvironment> const & /*xCmdEnv*/ )
313 std::vector<Reference<css::deployment::XPackage> > listExtensions =
314 getExtensionsWithSameId(identifier, fileName);
315 bool bHasExtension = false;
317 //throw an IllegalArgumentException if there is no extension at all.
318 for (auto const& extension : listExtensions)
319 bHasExtension |= extension.is();
320 if (!bHasExtension)
321 throw lang::IllegalArgumentException(
322 "Could not find extension: " + identifier + ", " + fileName,
323 static_cast<cppu::OWeakObject*>(this), -1);
325 return comphelper::containerToSequence(listExtensions);
327 catch ( const css::deployment::DeploymentException & )
329 throw;
331 catch ( const ucb::CommandFailedException & )
333 throw;
335 catch (css::uno::RuntimeException &)
337 throw;
339 catch (...)
341 uno::Any exc = ::cppu::getCaughtException();
342 throw css::deployment::DeploymentException(
343 "Extension Manager: exception during getExtensionsWithSameIdentifier",
344 static_cast<OWeakObject*>(this), exc);
348 bool ExtensionManager::isUserDisabled(
349 OUString const & identifier, OUString const & fileName)
351 std::vector<Reference<css::deployment::XPackage> > listExtensions;
353 try {
354 listExtensions = getExtensionsWithSameId(identifier, fileName);
355 } catch ( const lang::IllegalArgumentException & ) {
357 OSL_ASSERT(listExtensions.size() == 3);
359 return isUserDisabled( ::comphelper::containerToSequence(listExtensions) );
362 bool ExtensionManager::isUserDisabled(
363 uno::Sequence<Reference<css::deployment::XPackage> > const & seqExtSameId)
365 OSL_ASSERT(seqExtSameId.getLength() == 3);
366 Reference<css::deployment::XPackage> const & userExtension = seqExtSameId[0];
367 if (userExtension.is())
369 beans::Optional<beans::Ambiguous<sal_Bool> > reg =
370 userExtension->isRegistered(Reference<task::XAbortChannel>(),
371 Reference<ucb::XCommandEnvironment>());
372 //If the value is ambiguous, then we assume that the extension
373 //is enabled, but something went wrong during enabling. We do not
374 //automatically disable user extensions.
375 if (reg.IsPresent &&
376 ! reg.Value.IsAmbiguous && ! reg.Value.Value)
377 return true;
379 return false;
383 This method determines the active extension (XPackage.registerPackage) with a
384 particular identifier.
386 The parameter bUserDisabled determines if the user extension is disabled.
388 When the user repository contains an extension with the given identifier and
389 it is not disabled by the user, then it is always registered. Otherwise an
390 extension is only registered when there is no registered extension in one of
391 the repositories with a higher priority. That is, if the extension is from
392 the shared repository and an active extension with the same identifier is in
393 the user repository, then the extension is not registered. Similarly a
394 bundled extension is not registered if there is an active extension with the
395 same identifier in the shared or user repository.
397 void ExtensionManager::activateExtension(
398 OUString const & identifier, OUString const & fileName,
399 bool bUserDisabled,
400 bool bStartup,
401 Reference<task::XAbortChannel> const & xAbortChannel,
402 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
404 std::vector<Reference<css::deployment::XPackage> > listExtensions;
405 try {
406 listExtensions = getExtensionsWithSameId(identifier, fileName);
407 } catch (const lang::IllegalArgumentException &) {
409 OSL_ASSERT(listExtensions.size() == 3);
411 activateExtension(
412 ::comphelper::containerToSequence(listExtensions),
413 bUserDisabled, bStartup, xAbortChannel, xCmdEnv);
415 fireModified();
418 void ExtensionManager::activateExtension(
419 uno::Sequence<Reference<css::deployment::XPackage> > const & seqExt,
420 bool bUserDisabled,
421 bool bStartup,
422 Reference<task::XAbortChannel> const & xAbortChannel,
423 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
425 bool bActive = false;
426 sal_Int32 len = seqExt.getLength();
427 for (sal_Int32 i = 0; i < len; i++)
429 Reference<css::deployment::XPackage> const & aExt = seqExt[i];
430 if (aExt.is())
432 //get the registration value of the current iteration
433 beans::Optional<beans::Ambiguous<sal_Bool> > optReg =
434 aExt->isRegistered(xAbortChannel, xCmdEnv);
435 //If nothing can be registered then break
436 if (!optReg.IsPresent)
437 break;
439 //Check if this is a disabled user extension,
440 if (i == 0 && bUserDisabled)
442 aExt->revokePackage(bStartup, xAbortChannel, xCmdEnv);
443 continue;
446 //If we have already determined an active extension then we must
447 //make sure to unregister all extensions with the same id in
448 //repositories with a lower priority
449 if (bActive)
451 aExt->revokePackage(bStartup, xAbortChannel, xCmdEnv);
453 else
455 //This is the first extension in the ordered list, which becomes
456 //the active extension
457 bActive = true;
458 //Register if not already done.
459 //reregister if the value is ambiguous, which indicates that
460 //something went wrong during last registration.
461 aExt->registerPackage(bStartup, xAbortChannel, xCmdEnv);
467 Reference<css::deployment::XPackage> ExtensionManager::backupExtension(
468 OUString const & identifier, OUString const & fileName,
469 Reference<css::deployment::XPackageManager> const & xPackageManager,
470 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
472 Reference<css::deployment::XPackage> xBackup;
473 Reference<ucb::XCommandEnvironment> tmpCmdEnv(
474 new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler()));
475 Reference<css::deployment::XPackage> xOldExtension = xPackageManager->getDeployedPackage(
476 identifier, fileName, tmpCmdEnv);
478 if (xOldExtension.is())
480 xBackup = getTmpRepository()->addPackage(
481 xOldExtension->getURL(), uno::Sequence<beans::NamedValue>(),
482 OUString(), Reference<task::XAbortChannel>(), tmpCmdEnv);
484 OSL_ENSURE(xBackup.is(), "Failed to backup extension");
486 return xBackup;
489 //The supported package types are actually determined by the registry. However
490 //creating a registry
491 //(desktop/source/deployment/registry/dp_registry.cxx:PackageRegistryImpl) will
492 //create all the backends, so that the registry can obtain from them the package
493 //types. Creating the registry will also set up the registry folder containing
494 //all the subfolders for the respective backends.
495 //Because all repositories support the same backends, we can just delegate this
496 //call to one of the repositories.
497 uno::Sequence< Reference<css::deployment::XPackageTypeInfo> >
498 ExtensionManager::getSupportedPackageTypes()
500 return getUserRepository()->getSupportedPackageTypes();
502 //Do some necessary checks and user interaction. This function does not
503 //acquire the extension manager mutex and that mutex must not be acquired
504 //when this function is called. doChecksForAddExtension does synchronous
505 //user interactions which may require acquiring the solar mutex.
506 //Returns true if the extension can be installed.
507 bool ExtensionManager::doChecksForAddExtension(
508 Reference<css::deployment::XPackageManager> const & xPackageMgr,
509 uno::Sequence<beans::NamedValue> const & properties,
510 css::uno::Reference<css::deployment::XPackage> const & xTmpExtension,
511 Reference<task::XAbortChannel> const & xAbortChannel,
512 Reference<ucb::XCommandEnvironment> const & xCmdEnv,
513 Reference<css::deployment::XPackage> & out_existingExtension )
517 Reference<css::deployment::XPackage> xOldExtension;
518 const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
519 const OUString sFileName = xTmpExtension->getName();
520 const OUString sDisplayName = xTmpExtension->getDisplayName();
521 const OUString sVersion = xTmpExtension->getVersion();
525 xOldExtension = xPackageMgr->getDeployedPackage(
526 sIdentifier, sFileName, xCmdEnv);
527 out_existingExtension = xOldExtension;
529 catch (const lang::IllegalArgumentException &)
532 bool bCanInstall = false;
534 //This part is not guarded against other threads removing, adding, disabling ...
535 //etc. the same extension.
536 //checkInstall is safe because it notifies the user if the extension is not yet
537 //installed in the same repository. Because addExtension has its own guard
538 //(m_addMutex), another thread cannot add the extension in the meantime.
539 //checkUpdate is called if the same extension exists in the same
540 //repository. The user is asked if they want to replace it. Another
541 //thread
542 //could already remove the extension. So asking the user was not
543 //necessary. No harm is done. The other thread may also ask the user
544 //if he wants to remove the extension. This depends on the
545 //XCommandEnvironment which it passes to removeExtension.
546 if (xOldExtension.is())
548 //throws a CommandFailedException if the user cancels
549 //the action.
550 checkUpdate(sVersion, sDisplayName,xOldExtension, xCmdEnv);
552 else
554 //throws a CommandFailedException if the user cancels
555 //the action.
556 checkInstall(sDisplayName, xCmdEnv);
558 //Prevent showing the license if requested.
559 Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv);
560 ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>(), m_xContext);
562 dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL()));
563 const ::boost::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes =
564 info.getSimpleLicenseAttributes();
566 if (licenseAttributes && licenseAttributes->suppressIfRequired
567 && props.isSuppressedLicense())
568 _xCmdEnv.set(new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler()));
570 bCanInstall = xTmpExtension->checkPrerequisites(
571 xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0;
573 return bCanInstall;
575 catch ( const css::deployment::DeploymentException& ) {
576 throw;
577 } catch ( const ucb::CommandFailedException & ) {
578 throw;
579 } catch ( const ucb::CommandAbortedException & ) {
580 throw;
581 } catch (const lang::IllegalArgumentException &) {
582 throw;
583 } catch (const uno::RuntimeException &) {
584 throw;
585 } catch (const uno::Exception &) {
586 uno::Any excOccurred = ::cppu::getCaughtException();
587 css::deployment::DeploymentException exc(
588 "Extension Manager: exception in doChecksForAddExtension",
589 static_cast<OWeakObject*>(this), excOccurred);
590 throw exc;
591 } catch (...) {
592 throw uno::RuntimeException(
593 "Extension Manager: unexpected exception in doChecksForAddExtension",
594 static_cast<OWeakObject*>(this));
598 // Only add to shared and user repository
599 Reference<css::deployment::XPackage> ExtensionManager::addExtension(
600 OUString const & url, uno::Sequence<beans::NamedValue> const & properties,
601 OUString const & repository,
602 Reference<task::XAbortChannel> const & xAbortChannel,
603 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
605 Reference<css::deployment::XPackage> xNewExtension;
606 //Determine the repository to use
607 Reference<css::deployment::XPackageManager> xPackageManager;
608 if (repository == "user")
609 xPackageManager = getUserRepository();
610 else if (repository == "shared")
611 xPackageManager = getSharedRepository();
612 else
613 throw lang::IllegalArgumentException(
614 "No valid repository name provided.",
615 static_cast<cppu::OWeakObject*>(this), 0);
616 //We must make sure that the xTmpExtension is not create twice, because this
617 //would remove the first one.
618 ::osl::MutexGuard addGuard(m_addMutex);
620 Reference<css::deployment::XPackageManager> xTmpRepository(getTmpRepository());
621 // make sure xTmpRepository is alive as long as xTmpExtension is; as
622 // the "tmp" manager is only held weakly by m_xPackageManagerFactory, it
623 // could otherwise be disposed early, which would in turn dispose
624 // xTmpExtension's PackageRegistryBackend behind its back
625 Reference<css::deployment::XPackage> xTmpExtension(
626 xTmpRepository->addPackage(
627 url, uno::Sequence<beans::NamedValue>(), OUString(), xAbortChannel,
628 new TmpRepositoryCommandEnv()));
629 if (!xTmpExtension.is()) {
630 throw css::deployment::DeploymentException(
631 ("Extension Manager: Failed to create temporary XPackage for url: "
632 + url),
633 static_cast<OWeakObject*>(this), uno::Any());
636 //Make sure the extension is removed from the tmp repository in case
637 //of an exception
638 ExtensionRemoveGuard tmpExtensionRemoveGuard(xTmpExtension, getTmpRepository());
639 ExtensionRemoveGuard bakExtensionRemoveGuard;
640 const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
641 const OUString sFileName = xTmpExtension->getName();
642 Reference<css::deployment::XPackage> xOldExtension;
643 Reference<css::deployment::XPackage> xExtensionBackup;
645 uno::Any excOccurred2;
646 bool bCanInstall = doChecksForAddExtension(
647 xPackageManager,
648 properties,
649 xTmpExtension,
650 xAbortChannel,
651 xCmdEnv,
652 xOldExtension );
655 bool bUserDisabled = false;
656 // In this guarded section (getMutex) we must not use the argument xCmdEnv
657 // because it may bring up dialogs (XInteractionHandler::handle) this
658 // may potentially deadlock. See issue
659 // http://qa.openoffice.org/issues/show_bug.cgi?id=114933
660 // By not providing xCmdEnv the underlying APIs will throw an exception if
661 // the XInteractionRequest cannot be handled.
662 ::osl::MutexGuard guard(getMutex());
664 if (bCanInstall)
668 bUserDisabled = isUserDisabled(sIdentifier, sFileName);
669 if (xOldExtension.is())
673 xOldExtension->revokePackage(
674 false, xAbortChannel, Reference<ucb::XCommandEnvironment>());
675 //save the old user extension in case the user aborts
676 xExtensionBackup = getBakRepository()->importExtension(
677 xOldExtension, Reference<task::XAbortChannel>(),
678 Reference<ucb::XCommandEnvironment>());
679 bakExtensionRemoveGuard.set(xExtensionBackup, getBakRepository());
681 catch (const lang::DisposedException &)
683 //Another thread might have removed the extension meanwhile
686 //check again dependencies but prevent user interaction,
687 //We can disregard the license, because the user must have already
688 //accepted it, when we called checkPrerequisites the first time
689 SilentCheckPrerequisitesCommandEnv * pSilentCommandEnv =
690 new SilentCheckPrerequisitesCommandEnv();
691 Reference<ucb::XCommandEnvironment> silentCommandEnv(pSilentCommandEnv);
693 sal_Int32 failedPrereq = xTmpExtension->checkPrerequisites(
694 xAbortChannel, silentCommandEnv, true);
695 if (failedPrereq == 0)
697 xNewExtension = xPackageManager->addPackage(
698 url, properties, OUString(), xAbortChannel,
699 Reference<ucb::XCommandEnvironment>());
700 //If we add a user extension and there is already one which was
701 //disabled by a user, then the newly installed one is enabled. If we
702 //add to another repository then the user extension remains
703 //disabled.
704 bool bUserDisabled2 = bUserDisabled;
705 if (repository == "user")
706 bUserDisabled2 = false;
708 // pass the two values via variables to workaround gcc-4.3.4 specific bug (bnc#655912)
709 OUString sNewExtensionIdentifier = dp_misc::getIdentifier(xNewExtension);
710 OUString sNewExtensionFileName = xNewExtension->getName();
712 activateExtension(
713 sNewExtensionIdentifier, sNewExtensionFileName,
714 bUserDisabled2, false, xAbortChannel,
715 Reference<ucb::XCommandEnvironment>());
717 else
719 if (pSilentCommandEnv->m_Exception.hasValue())
720 ::cppu::throwException(pSilentCommandEnv->m_Exception);
721 else if ( pSilentCommandEnv->m_UnknownException.hasValue())
722 ::cppu::throwException(pSilentCommandEnv->m_UnknownException);
723 else
724 throw css::deployment::DeploymentException (
725 "Extension Manager: exception during addExtension, ckeckPrerequisites failed",
726 static_cast<OWeakObject*>(this), uno::Any());
729 catch ( const css::deployment::DeploymentException& ) {
730 excOccurred2 = ::cppu::getCaughtException();
731 } catch ( const ucb::CommandFailedException & ) {
732 excOccurred2 = ::cppu::getCaughtException();
733 } catch ( const ucb::CommandAbortedException & ) {
734 excOccurred2 = ::cppu::getCaughtException();
735 } catch (const lang::IllegalArgumentException &) {
736 excOccurred2 = ::cppu::getCaughtException();
737 } catch (const uno::RuntimeException &) {
738 excOccurred2 = ::cppu::getCaughtException();
739 } catch (...) {
740 excOccurred2 = ::cppu::getCaughtException();
741 css::deployment::DeploymentException exc(
742 "Extension Manager: exception during addExtension, url: "
743 + url, static_cast<OWeakObject*>(this), excOccurred2);
744 excOccurred2 <<= exc;
748 if (excOccurred2.hasValue())
750 //It does not matter what exception is thrown. We try to
751 //recover the original status.
752 //If the user aborted installation then a ucb::CommandAbortedException
753 //is thrown.
754 //Use a private AbortChannel so the user cannot interrupt.
757 if (xExtensionBackup.is())
759 xPackageManager->importExtension(
760 xExtensionBackup, Reference<task::XAbortChannel>(),
761 Reference<ucb::XCommandEnvironment>());
763 activateExtension(
764 sIdentifier, sFileName, bUserDisabled, false,
765 Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
767 catch (...)
770 ::cppu::throwException(excOccurred2);
772 } // leaving the guarded section (getMutex())
776 fireModified();
778 }catch ( const css::deployment::DeploymentException& ) {
779 throw;
780 } catch ( const ucb::CommandFailedException & ) {
781 throw;
782 } catch ( const ucb::CommandAbortedException & ) {
783 throw;
784 } catch (const lang::IllegalArgumentException &) {
785 throw;
786 } catch (const uno::RuntimeException &) {
787 throw;
788 } catch (const uno::Exception &) {
789 uno::Any excOccurred = ::cppu::getCaughtException();
790 css::deployment::DeploymentException exc(
791 "Extension Manager: exception in doChecksForAddExtension",
792 static_cast<OWeakObject*>(this), excOccurred);
793 throw exc;
794 } catch (...) {
795 throw uno::RuntimeException(
796 "Extension Manager: unexpected exception in doChecksForAddExtension",
797 static_cast<OWeakObject*>(this));
800 return xNewExtension;
803 void ExtensionManager::removeExtension(
804 OUString const & identifier, OUString const & fileName,
805 OUString const & repository,
806 Reference<task::XAbortChannel> const & xAbortChannel,
807 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
809 uno::Any excOccurred1;
810 Reference<css::deployment::XPackage> xExtensionBackup;
811 Reference<css::deployment::XPackageManager> xPackageManager;
812 bool bUserDisabled = false;
813 ::osl::MutexGuard guard(getMutex());
816 //Determine the repository to use
817 if (repository == "user")
818 xPackageManager = getUserRepository();
819 else if (repository == "shared")
820 xPackageManager = getSharedRepository();
821 else
822 throw lang::IllegalArgumentException(
823 "No valid repository name provided.",
824 static_cast<cppu::OWeakObject*>(this), 0);
826 bUserDisabled = isUserDisabled(identifier, fileName);
827 //Backup the extension, in case the user cancels the action
828 xExtensionBackup = backupExtension(
829 identifier, fileName, xPackageManager, xCmdEnv);
831 //revoke the extension if it is active
832 Reference<css::deployment::XPackage> xOldExtension =
833 xPackageManager->getDeployedPackage(
834 identifier, fileName, xCmdEnv);
835 xOldExtension->revokePackage(false, xAbortChannel, xCmdEnv);
837 xPackageManager->removePackage(
838 identifier, fileName, xAbortChannel, xCmdEnv);
839 activateExtension(identifier, fileName, bUserDisabled, false,
840 xAbortChannel, xCmdEnv);
841 fireModified();
843 catch ( const css::deployment::DeploymentException& ) {
844 excOccurred1 = ::cppu::getCaughtException();
845 } catch ( const ucb::CommandFailedException & ) {
846 excOccurred1 = ::cppu::getCaughtException();
847 } catch ( const ucb::CommandAbortedException & ) {
848 excOccurred1 = ::cppu::getCaughtException();
849 } catch (const lang::IllegalArgumentException &) {
850 excOccurred1 = ::cppu::getCaughtException();
851 } catch (const uno::RuntimeException &) {
852 excOccurred1 = ::cppu::getCaughtException();
853 } catch (...) {
854 excOccurred1 = ::cppu::getCaughtException();
855 css::deployment::DeploymentException exc(
856 "Extension Manager: exception during removeEtension",
857 static_cast<OWeakObject*>(this), excOccurred1);
858 excOccurred1 <<= exc;
861 if (excOccurred1.hasValue())
863 //User aborted installation, restore the previous situation.
864 //Use a private AbortChannel so the user cannot interrupt.
867 Reference<ucb::XCommandEnvironment> tmpCmdEnv(
868 new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler()));
869 if (xExtensionBackup.is())
871 Reference<css::deployment::XPackage> xRestored =
872 xPackageManager->importExtension(
873 xExtensionBackup, Reference<task::XAbortChannel>(),
874 tmpCmdEnv);
875 activateExtension(
876 identifier, fileName, bUserDisabled, false,
877 Reference<task::XAbortChannel>(),
878 tmpCmdEnv);
880 getTmpRepository()->removePackage(
881 dp_misc::getIdentifier(xExtensionBackup),
882 xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
883 fireModified();
886 catch (...)
889 ::cppu::throwException(excOccurred1);
892 if (xExtensionBackup.is())
893 getTmpRepository()->removePackage(
894 dp_misc::getIdentifier(xExtensionBackup),
895 xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
898 // Only enable extensions from shared and user repository
899 void ExtensionManager::enableExtension(
900 Reference<css::deployment::XPackage> const & extension,
901 Reference<task::XAbortChannel> const & xAbortChannel,
902 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
904 ::osl::MutexGuard guard(getMutex());
905 bool bUserDisabled = false;
906 uno::Any excOccurred;
909 if (!extension.is())
910 return;
911 OUString repository = extension->getRepositoryName();
912 if (repository != "user")
913 throw lang::IllegalArgumentException(
914 "No valid repository name provided.",
915 static_cast<cppu::OWeakObject*>(this), 0);
917 bUserDisabled = isUserDisabled(dp_misc::getIdentifier(extension),
918 extension->getName());
920 activateExtension(dp_misc::getIdentifier(extension),
921 extension->getName(), false, false,
922 xAbortChannel, xCmdEnv);
924 catch ( const css::deployment::DeploymentException& ) {
925 excOccurred = ::cppu::getCaughtException();
926 } catch ( const ucb::CommandFailedException & ) {
927 excOccurred = ::cppu::getCaughtException();
928 } catch ( const ucb::CommandAbortedException & ) {
929 excOccurred = ::cppu::getCaughtException();
930 } catch (const lang::IllegalArgumentException &) {
931 excOccurred = ::cppu::getCaughtException();
932 } catch (const uno::RuntimeException &) {
933 excOccurred = ::cppu::getCaughtException();
934 } catch (...) {
935 excOccurred = ::cppu::getCaughtException();
936 css::deployment::DeploymentException exc(
937 "Extension Manager: exception during enableExtension",
938 static_cast<OWeakObject*>(this), excOccurred);
939 excOccurred <<= exc;
942 if (excOccurred.hasValue())
946 activateExtension(dp_misc::getIdentifier(extension),
947 extension->getName(), bUserDisabled, false,
948 xAbortChannel, xCmdEnv);
950 catch (...)
953 ::cppu::throwException(excOccurred);
957 sal_Int32 ExtensionManager::checkPrerequisitesAndEnable(
958 Reference<css::deployment::XPackage> const & extension,
959 Reference<task::XAbortChannel> const & xAbortChannel,
960 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
964 if (!extension.is())
965 return 0;
966 ::osl::MutexGuard guard(getMutex());
967 sal_Int32 ret = 0;
968 Reference<css::deployment::XPackageManager> mgr =
969 getPackageManager(extension->getRepositoryName());
970 ret = mgr->checkPrerequisites(extension, xAbortChannel, xCmdEnv);
971 if (ret)
973 //There are some unfulfilled prerequisites, try to revoke
974 extension->revokePackage(false, xAbortChannel, xCmdEnv);
976 const OUString id(dp_misc::getIdentifier(extension));
977 activateExtension(id, extension->getName(),
978 isUserDisabled(id, extension->getName()), false,
979 xAbortChannel, xCmdEnv);
980 return ret;
982 catch ( const css::deployment::DeploymentException& ) {
983 throw;
984 } catch ( const ucb::CommandFailedException & ) {
985 throw;
986 } catch ( const ucb::CommandAbortedException & ) {
987 throw;
988 } catch (const lang::IllegalArgumentException &) {
989 throw;
990 } catch (const uno::RuntimeException &) {
991 throw;
992 } catch (...) {
993 uno::Any excOccurred = ::cppu::getCaughtException();
994 css::deployment::DeploymentException exc(
995 "Extension Manager: exception during disableExtension",
996 static_cast<OWeakObject*>(this), excOccurred);
997 throw exc;
1001 void ExtensionManager::disableExtension(
1002 Reference<css::deployment::XPackage> const & extension,
1003 Reference<task::XAbortChannel> const & xAbortChannel,
1004 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1006 ::osl::MutexGuard guard(getMutex());
1007 uno::Any excOccurred;
1008 bool bUserDisabled = false;
1011 if (!extension.is())
1012 return;
1013 const OUString repository( extension->getRepositoryName());
1014 if (repository != "user")
1015 throw lang::IllegalArgumentException(
1016 "No valid repository name provided.",
1017 static_cast<cppu::OWeakObject*>(this), 0);
1019 const OUString id(dp_misc::getIdentifier(extension));
1020 bUserDisabled = isUserDisabled(id, extension->getName());
1022 activateExtension(id, extension->getName(), true, false,
1023 xAbortChannel, xCmdEnv);
1025 catch ( const css::deployment::DeploymentException& ) {
1026 excOccurred = ::cppu::getCaughtException();
1027 } catch ( const ucb::CommandFailedException & ) {
1028 excOccurred = ::cppu::getCaughtException();
1029 } catch ( const ucb::CommandAbortedException & ) {
1030 excOccurred = ::cppu::getCaughtException();
1031 } catch (const lang::IllegalArgumentException &) {
1032 excOccurred = ::cppu::getCaughtException();
1033 } catch (const uno::RuntimeException &) {
1034 excOccurred = ::cppu::getCaughtException();
1035 } catch (...) {
1036 excOccurred = ::cppu::getCaughtException();
1037 css::deployment::DeploymentException exc(
1038 "Extension Manager: exception during disableExtension",
1039 static_cast<OWeakObject*>(this), excOccurred);
1040 excOccurred <<= exc;
1043 if (excOccurred.hasValue())
1047 activateExtension(dp_misc::getIdentifier(extension),
1048 extension->getName(), bUserDisabled, false,
1049 xAbortChannel, xCmdEnv);
1051 catch (...)
1054 ::cppu::throwException(excOccurred);
1058 uno::Sequence< Reference<css::deployment::XPackage> >
1059 ExtensionManager::getDeployedExtensions(
1060 OUString const & repository,
1061 Reference<task::XAbortChannel> const &xAbort,
1062 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1064 return getPackageManager(repository)->getDeployedPackages(
1065 xAbort, xCmdEnv);
1068 Reference<css::deployment::XPackage>
1069 ExtensionManager::getDeployedExtension(
1070 OUString const & repository,
1071 OUString const & identifier,
1072 OUString const & filename,
1073 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1075 return getPackageManager(repository)->getDeployedPackage(
1076 identifier, filename, xCmdEnv);
1079 uno::Sequence< uno::Sequence<Reference<css::deployment::XPackage> > >
1080 ExtensionManager::getAllExtensions(
1081 Reference<task::XAbortChannel> const & xAbort,
1082 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1086 id2extensions mapExt;
1088 uno::Sequence<Reference<css::deployment::XPackage> > userExt =
1089 getUserRepository()->getDeployedPackages(xAbort, xCmdEnv);
1090 addExtensionsToMap(mapExt, userExt, "user");
1091 uno::Sequence<Reference<css::deployment::XPackage> > sharedExt =
1092 getSharedRepository()->getDeployedPackages(xAbort, xCmdEnv);
1093 addExtensionsToMap(mapExt, sharedExt, "shared");
1094 uno::Sequence<Reference<css::deployment::XPackage> > bundledExt =
1095 getBundledRepository()->getDeployedPackages(xAbort, xCmdEnv);
1096 addExtensionsToMap(mapExt, bundledExt, "bundled");
1098 // Create the tmp repository to trigger its clean up (deletion
1099 // of old temporary data.)
1100 getTmpRepository();
1102 //copy the values of the map to a vector for sorting
1103 std::vector< std::vector<Reference<css::deployment::XPackage> > >
1104 vecExtensions;
1105 for (auto const& elem : mapExt)
1106 vecExtensions.push_back(elem.second);
1108 //sort the element according to the identifier
1109 std::sort(vecExtensions.begin(), vecExtensions.end(), CompIdentifiers());
1111 sal_Int32 j = 0;
1112 uno::Sequence< uno::Sequence<Reference<css::deployment::XPackage> > > seqSeq(vecExtensions.size());
1113 for (auto const& elem : vecExtensions)
1115 seqSeq[j++] = comphelper::containerToSequence(elem);
1117 return seqSeq;
1119 } catch ( const css::deployment::DeploymentException& ) {
1120 throw;
1121 } catch ( const ucb::CommandFailedException & ) {
1122 throw;
1123 } catch ( const ucb::CommandAbortedException & ) {
1124 throw;
1125 } catch (const lang::IllegalArgumentException &) {
1126 throw;
1127 } catch (const uno::RuntimeException &) {
1128 throw;
1129 } catch (...) {
1130 uno::Any exc = ::cppu::getCaughtException();
1131 throw css::deployment::DeploymentException(
1132 "Extension Manager: exception during enableExtension",
1133 static_cast<OWeakObject*>(this), exc);
1137 // Only to be called from unopkg or soffice bootstrap (with force=true in the
1138 // latter case):
1139 void ExtensionManager::reinstallDeployedExtensions(
1140 sal_Bool force, OUString const & repository,
1141 Reference<task::XAbortChannel> const & xAbortChannel,
1142 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1146 Reference<css::deployment::XPackageManager>
1147 xPackageManager = getPackageManager(repository);
1149 std::set< OUString > disabledExts;
1151 const uno::Sequence< Reference<css::deployment::XPackage> > extensions(
1152 xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv));
1153 for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos )
1157 beans::Optional< beans::Ambiguous< sal_Bool > > registered(
1158 extensions[pos]->isRegistered(xAbortChannel, xCmdEnv));
1159 if (registered.IsPresent &&
1160 !(registered.Value.IsAmbiguous ||
1161 registered.Value.Value))
1163 const OUString id = dp_misc::getIdentifier(extensions[ pos ]);
1164 OSL_ASSERT(!id.isEmpty());
1165 disabledExts.insert(id);
1168 catch (const lang::DisposedException &)
1174 ::osl::MutexGuard guard(getMutex());
1175 xPackageManager->reinstallDeployedPackages(
1176 force, xAbortChannel, xCmdEnv);
1177 //We must sync here, otherwise we will get exceptions when extensions
1178 //are removed.
1179 dp_misc::syncRepositories(force, xCmdEnv);
1180 const uno::Sequence< Reference<css::deployment::XPackage> > extensions(
1181 xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv));
1183 for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos )
1187 const OUString id = dp_misc::getIdentifier(extensions[ pos ]);
1188 const OUString fileName = extensions[ pos ]->getName();
1189 OSL_ASSERT(!id.isEmpty());
1190 activateExtension(
1191 id, fileName, disabledExts.find(id) != disabledExts.end(),
1192 true, xAbortChannel, xCmdEnv );
1194 catch (const lang::DisposedException &)
1198 } catch ( const css::deployment::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 css::deployment::DeploymentException(
1211 "Extension Manager: exception during enableExtension",
1212 static_cast<OWeakObject*>(this), exc);
1216 sal_Bool ExtensionManager::synchronize(
1217 Reference<task::XAbortChannel> const & xAbortChannel,
1218 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1222 ::osl::MutexGuard guard(getMutex());
1223 OUString sSynchronizingShared(StrSyncRepository());
1224 sSynchronizingShared = sSynchronizingShared.replaceAll("%NAME", "shared");
1225 dp_misc::ProgressLevel progressShared(xCmdEnv, sSynchronizingShared);
1226 bool bModified = getSharedRepository()->synchronize(xAbortChannel, xCmdEnv);
1227 progressShared.update("\n\n");
1229 OUString sSynchronizingBundled(StrSyncRepository());
1230 sSynchronizingBundled = sSynchronizingBundled.replaceAll("%NAME", "bundled");
1231 dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled);
1232 bModified |= static_cast<bool>(getBundledRepository()->synchronize(xAbortChannel, xCmdEnv));
1233 progressBundled.update("\n\n");
1235 //Always determine the active extension.
1236 //TODO: Is this still necessary? (It used to be necessary for the
1237 // first-start optimization: The setup created the registration data
1238 // for the bundled extensions (share/prereg/bundled) which was copied to
1239 // the user installation when a user started OOo for the first time
1240 // after running setup. All bundled extensions were registered at that
1241 // moment. However, extensions with the same identifier could be in the
1242 // shared or user repository, in which case the respective bundled
1243 // extensions had to be revoked.)
1246 const uno::Sequence<uno::Sequence<Reference<css::deployment::XPackage> > >
1247 seqSeqExt = getAllExtensions(xAbortChannel, xCmdEnv);
1248 for (sal_Int32 i = 0; i < seqSeqExt.getLength(); i++)
1250 uno::Sequence<Reference<css::deployment::XPackage> > const & seqExt =
1251 seqSeqExt[i];
1252 activateExtension(seqExt, isUserDisabled(seqExt), true,
1253 xAbortChannel, xCmdEnv);
1256 catch (...)
1258 //We catch the exception, so we can write the lastmodified file
1259 //so we will no repeat this every time OOo starts.
1260 OSL_FAIL("Extensions Manager: synchronize");
1262 OUString lastSyncBundled("$BUNDLED_EXTENSIONS_USER/lastsynchronized");
1263 writeLastModified(lastSyncBundled, xCmdEnv, m_xContext);
1264 OUString lastSyncShared("$SHARED_EXTENSIONS_USER/lastsynchronized");
1265 writeLastModified(lastSyncShared, xCmdEnv, m_xContext);
1266 return bModified;
1267 } catch ( const css::deployment::DeploymentException& ) {
1268 throw;
1269 } catch ( const ucb::CommandFailedException & ) {
1270 throw;
1271 } catch ( const ucb::CommandAbortedException & ) {
1272 throw;
1273 } catch (const lang::IllegalArgumentException &) {
1274 throw;
1275 } catch (const uno::RuntimeException &) {
1276 throw;
1277 } catch (...) {
1278 uno::Any exc = ::cppu::getCaughtException();
1279 throw css::deployment::DeploymentException(
1280 "Extension Manager: exception in synchronize",
1281 static_cast<OWeakObject*>(this), exc);
1285 // Notify the user when a new extension is to be installed. This is only the
1286 // case when one uses the system integration to install an extension (double
1287 // clicking on .oxt file etc.)). The function must only be called if there is no
1288 // extension with the same identifier already deployed. Then the checkUpdate
1289 // function will inform the user that the extension is about to be installed In
1290 // case the user cancels the installation a CommandFailed exception is
1291 // thrown.
1292 void ExtensionManager::checkInstall(
1293 OUString const & displayName,
1294 Reference<ucb::XCommandEnvironment> const & cmdEnv)
1296 uno::Any request(
1297 css::deployment::InstallException(
1298 "Extension " + displayName +
1299 " is about to be installed.",
1300 static_cast<OWeakObject *>(this), displayName));
1301 bool approve = false, abort = false;
1302 if (! dp_misc::interactContinuation(
1303 request, cppu::UnoType<task::XInteractionApprove>::get(),
1304 cmdEnv, &approve, &abort ))
1306 OSL_ASSERT( !approve && !abort );
1307 throw css::deployment::DeploymentException(
1308 DpResId(RID_STR_ERROR_WHILE_ADDING) + displayName,
1309 static_cast<OWeakObject *>(this), request );
1311 if (abort || !approve)
1312 throw ucb::CommandFailedException(
1313 DpResId(RID_STR_ERROR_WHILE_ADDING) + displayName,
1314 static_cast<OWeakObject *>(this), request );
1317 /* The function will make the user interaction in case there is an extension
1318 installed with the same id. This function may only be called if there is already
1319 an extension.
1321 void ExtensionManager::checkUpdate(
1322 OUString const & newVersion,
1323 OUString const & newDisplayName,
1324 Reference<css::deployment::XPackage> const & oldExtension,
1325 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1327 // package already deployed, interact --force:
1328 uno::Any request(
1329 (css::deployment::VersionException(
1330 DpResId(
1331 RID_STR_PACKAGE_ALREADY_ADDED ) + newDisplayName,
1332 static_cast<OWeakObject *>(this), newVersion, newDisplayName,
1333 oldExtension ) ) );
1334 bool replace = false, abort = false;
1335 if (! dp_misc::interactContinuation(
1336 request, cppu::UnoType<task::XInteractionApprove>::get(),
1337 xCmdEnv, &replace, &abort )) {
1338 OSL_ASSERT( !replace && !abort );
1339 throw css::deployment::DeploymentException(
1340 DpResId(
1341 RID_STR_ERROR_WHILE_ADDING) + newDisplayName,
1342 static_cast<OWeakObject *>(this), request );
1344 if (abort || !replace)
1345 throw ucb::CommandFailedException(
1346 DpResId(
1347 RID_STR_PACKAGE_ALREADY_ADDED) + newDisplayName,
1348 static_cast<OWeakObject *>(this), request );
1351 uno::Sequence<Reference<css::deployment::XPackage> > SAL_CALL
1352 ExtensionManager::getExtensionsWithUnacceptedLicenses(
1353 OUString const & repository,
1354 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
1356 Reference<css::deployment::XPackageManager>
1357 xPackageManager = getPackageManager(repository);
1358 ::osl::MutexGuard guard(getMutex());
1359 return xPackageManager->getExtensionsWithUnacceptedLicenses(xCmdEnv);
1362 sal_Bool ExtensionManager::isReadOnlyRepository(OUString const & repository)
1364 return getPackageManager(repository)->isReadOnly();
1368 namespace sdecl = comphelper::service_decl;
1369 sdecl::class_<ExtensionManager> const servicePIP;
1370 sdecl::ServiceDecl const serviceDecl(
1371 servicePIP,
1372 // a private one:
1373 "com.sun.star.comp.deployment.ExtensionManager",
1374 "com.sun.star.comp.deployment.ExtensionManager");
1376 // XModifyBroadcaster
1378 void ExtensionManager::addModifyListener(
1379 Reference<util::XModifyListener> const & xListener )
1381 check();
1382 rBHelper.addListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
1386 void ExtensionManager::removeModifyListener(
1387 Reference<util::XModifyListener> const & xListener )
1389 check();
1390 rBHelper.removeListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
1393 void ExtensionManager::check()
1395 ::osl::MutexGuard guard( getMutex() );
1396 if (rBHelper.bInDispose || rBHelper.bDisposed) {
1397 throw lang::DisposedException(
1398 "ExtensionManager instance has already been disposed!",
1399 static_cast<OWeakObject *>(this) );
1403 void ExtensionManager::fireModified()
1405 ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer(
1406 cppu::UnoType<util::XModifyListener>::get() );
1407 if (pContainer != nullptr) {
1408 pContainer->forEach<util::XModifyListener>(
1409 [this] (uno::Reference<util::XModifyListener> const& xListener)
1410 { return xListener->modified(lang::EventObject(static_cast<OWeakObject *>(this))); });
1414 } // namespace dp_manager
1416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */