LibreOffice Module desktop (master)  1
dp_extensionmanager.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 
21 #include <cppuhelper/compbase.hxx>
22 
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>
57 #include "dp_extensionmanager.hxx"
59 #include "dp_properties.hxx"
60 
61 #include <vector>
62 #include <algorithm>
63 #include <set>
64 
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;
71 
72 using ::com::sun::star::uno::Reference;
73 
74 namespace {
75 
76 struct CompIdentifiers
77 {
78  bool operator() (std::vector<Reference<css::deployment::XPackage> > const & a,
79  std::vector<Reference<css::deployment::XPackage> > const & b)
80  {
81  return getName(a).compareTo(getName(b)) < 0;
82  }
83 
84  static OUString getName(std::vector<Reference<css::deployment::XPackage> > const & a);
85 };
86 
87 OUString CompIdentifiers::getName(std::vector<Reference<css::deployment::XPackage> > const & a)
88 {
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)
93  {
94  if (elem.is())
95  {
96  extension = elem;
97  break;
98  }
99  }
100  OSL_ASSERT(extension.is());
101  return extension->getDisplayName();
102 }
103 
104 void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const & xCmdEnv, Reference< uno::XComponentContext > const & xContext)
105 {
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(
114  reinterpret_cast<sal_Int8 const *>(stamp.getStr()),
115  stamp.getLength() ) );
116  ucbStamp.writeStream( xData, true /* replace existing */ );
117  }
118  catch(...)
119  {
121  throw css::deployment::DeploymentException("Failed to update" + url, nullptr, exc);
122  }
123 }
124 
125 class ExtensionRemoveGuard
126 {
127  css::uno::Reference<css::deployment::XPackage> m_extension;
128  css::uno::Reference<css::deployment::XPackageManager> m_xPackageManager;
129 
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();
137 
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;
142  }
143 };
144 
145 ExtensionRemoveGuard::~ExtensionRemoveGuard()
146 {
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);
156  }
157 }
158 
159 }
160 
161 namespace dp_manager {
162 
163 //ToDo: bundled extension
165  ::cppu::WeakComponentImplHelper< css::deployment::XExtensionManager >(getMutex())
166  , m_xContext(xContext)
167 {
168  m_xPackageManagerFactory = css::deployment::thePackageManagerFactory::get(m_xContext);
169  OSL_ASSERT(m_xPackageManagerFactory.is());
170 
171  m_repositoryNames.emplace_back("user");
172  m_repositoryNames.emplace_back("shared");
173  m_repositoryNames.emplace_back("bundled");
174 }
175 
177 {
178 }
179 
180 Reference<css::deployment::XPackageManager> ExtensionManager::getUserRepository()
181 {
182  return m_xPackageManagerFactory->getPackageManager("user");
183 }
184 Reference<css::deployment::XPackageManager> ExtensionManager::getSharedRepository()
185 {
186  return m_xPackageManagerFactory->getPackageManager("shared");
187 }
188 Reference<css::deployment::XPackageManager> ExtensionManager::getBundledRepository()
189 {
190  return m_xPackageManagerFactory->getPackageManager("bundled");
191 }
192 Reference<css::deployment::XPackageManager> ExtensionManager::getTmpRepository()
193 {
194  return m_xPackageManagerFactory->getPackageManager("tmp");
195 }
196 Reference<css::deployment::XPackageManager> ExtensionManager::getBakRepository()
197 {
198  return m_xPackageManagerFactory->getPackageManager("bak");
199 }
200 
201 Reference<task::XAbortChannel> ExtensionManager::createAbortChannel()
202 {
203  return new dp_misc::AbortChannel;
204 }
205 
206 css::uno::Reference<css::deployment::XPackageManager>
207 ExtensionManager::getPackageManager(OUString const & repository)
208 {
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;
225 }
226 
227 /*
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.
233  */
235  id2extensions & mapExt,
236  uno::Sequence<Reference<css::deployment::XPackage> > const & seqExt,
237  OUString const & repository)
238 {
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)
243  {
244  if (repositoryName == repository)
245  break;
246  ++index;
247  }
248 
249  for (int i = 0; i < seqExt.getLength(); ++i)
250  {
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())
255  {
256  std::vector<Reference<css::deployment::XPackage> > vec(3);
257  vec[index] = xExtension;
258  mapExt[id] = vec;
259  }
260  else
261  {
262  ivec->second[index] = xExtension;
263  }
264  }
265 }
266 
267 /*
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
275 
276  The number of elements is always three, unless the number of repository
277  changes.
278  */
279 std::vector<Reference<css::deployment::XPackage> >
281  OUString const & identifier, OUString const & fileName)
282 
283 {
284  std::vector<Reference<css::deployment::XPackage> > extensionList;
285  Reference<css::deployment::XPackageManager> lRepos[] = {
287  for (int i(0); i != SAL_N_ELEMENTS(lRepos); ++i)
288  {
289  Reference<css::deployment::XPackage> xPackage;
290  try
291  {
292  xPackage = lRepos[i]->getDeployedPackage(
293  identifier, fileName, Reference<ucb::XCommandEnvironment>());
294  }
295  catch(const lang::IllegalArgumentException &)
296  {
297  // thrown if the extension does not exist in this repository
298  }
299  extensionList.push_back(xPackage);
300  }
301  OSL_ASSERT(extensionList.size() == 3);
302  return extensionList;
303 }
304 
305 uno::Sequence<Reference<css::deployment::XPackage> >
307  OUString const & identifier,
308  OUString const & fileName,
309  Reference< ucb::XCommandEnvironment> const & /*xCmdEnv*/ )
310 {
311  try
312  {
313  std::vector<Reference<css::deployment::XPackage> > listExtensions =
314  getExtensionsWithSameId(identifier, fileName);
315  bool bHasExtension = false;
316 
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);
324 
325  return comphelper::containerToSequence(listExtensions);
326  }
327  catch ( const css::deployment::DeploymentException & )
328  {
329  throw;
330  }
331  catch ( const ucb::CommandFailedException & )
332  {
333  throw;
334  }
335  catch (css::uno::RuntimeException &)
336  {
337  throw;
338  }
339  catch (...)
340  {
341  uno::Any exc = ::cppu::getCaughtException();
342  throw css::deployment::DeploymentException(
343  "Extension Manager: exception during getExtensionsWithSameIdentifier",
344  static_cast<OWeakObject*>(this), exc);
345  }
346 }
347 
349  OUString const & identifier, OUString const & fileName)
350 {
351  std::vector<Reference<css::deployment::XPackage> > listExtensions;
352 
353  try {
354  listExtensions = getExtensionsWithSameId(identifier, fileName);
355  } catch ( const lang::IllegalArgumentException & ) {
356  }
357  OSL_ASSERT(listExtensions.size() == 3);
358 
359  return isUserDisabled( ::comphelper::containerToSequence(listExtensions) );
360 }
361 
363  uno::Sequence<Reference<css::deployment::XPackage> > const & seqExtSameId)
364 {
365  OSL_ASSERT(seqExtSameId.getLength() == 3);
366  Reference<css::deployment::XPackage> const & userExtension = seqExtSameId[0];
367  if (userExtension.is())
368  {
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;
378  }
379  return false;
380 }
381 
382 /*
383  This method determines the active extension (XPackage.registerPackage) with a
384  particular identifier.
385 
386  The parameter bUserDisabled determines if the user extension is disabled.
387 
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.
396 */
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 )
403 {
404  std::vector<Reference<css::deployment::XPackage> > listExtensions;
405  try {
406  listExtensions = getExtensionsWithSameId(identifier, fileName);
407  } catch (const lang::IllegalArgumentException &) {
408  }
409  OSL_ASSERT(listExtensions.size() == 3);
410 
412  ::comphelper::containerToSequence(listExtensions),
413  bUserDisabled, bStartup, xAbortChannel, xCmdEnv);
414 
415  fireModified();
416 }
417 
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 )
424 {
425  bool bActive = false;
426  sal_Int32 len = seqExt.getLength();
427  for (sal_Int32 i = 0; i < len; i++)
428  {
429  Reference<css::deployment::XPackage> const & aExt = seqExt[i];
430  if (aExt.is())
431  {
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;
438 
439  //Check if this is a disabled user extension,
440  if (i == 0 && bUserDisabled)
441  {
442  aExt->revokePackage(bStartup, xAbortChannel, xCmdEnv);
443  continue;
444  }
445 
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)
450  {
451  aExt->revokePackage(bStartup, xAbortChannel, xCmdEnv);
452  }
453  else
454  {
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);
462  }
463  }
464  }
465 }
466 
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 )
471 {
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);
477 
478  if (xOldExtension.is())
479  {
480  xBackup = getTmpRepository()->addPackage(
481  xOldExtension->getURL(), uno::Sequence<beans::NamedValue>(),
482  OUString(), Reference<task::XAbortChannel>(), tmpCmdEnv);
483 
484  OSL_ENSURE(xBackup.is(), "Failed to backup extension");
485  }
486  return xBackup;
487 }
488 
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> >
499 {
500  return getUserRepository()->getSupportedPackageTypes();
501 }
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.
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 )
514 {
515  try
516  {
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();
522 
523  try
524  {
525  xOldExtension = xPackageMgr->getDeployedPackage(
526  sIdentifier, sFileName, xCmdEnv);
527  out_existingExtension = xOldExtension;
528  }
529  catch (const lang::IllegalArgumentException &)
530  {
531  }
532  bool bCanInstall = false;
533 
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())
547  {
548  //throws a CommandFailedException if the user cancels
549  //the action.
550  checkUpdate(sVersion, sDisplayName,xOldExtension, xCmdEnv);
551  }
552  else
553  {
554  //throws a CommandFailedException if the user cancels
555  //the action.
556  checkInstall(sDisplayName, xCmdEnv);
557  }
558  //Prevent showing the license if requested.
559  Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv);
560  ExtensionProperties props(OUString(), properties, Reference<ucb::XCommandEnvironment>(), m_xContext);
561 
562  dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL()));
563  const ::boost::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes =
565 
566  if (licenseAttributes && licenseAttributes->suppressIfRequired
567  && props.isSuppressedLicense())
568  _xCmdEnv.set(new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler()));
569 
570  bCanInstall = xTmpExtension->checkPrerequisites(
571  xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0;
572 
573  return bCanInstall;
574  }
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));
595  }
596 }
597 
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 )
604 {
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);
619 
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());
634  }
635 
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;
644 
645  uno::Any excOccurred2;
646  bool bCanInstall = doChecksForAddExtension(
647  xPackageManager,
648  properties,
649  xTmpExtension,
650  xAbortChannel,
651  xCmdEnv,
652  xOldExtension );
653 
654  {
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());
663 
664  if (bCanInstall)
665  {
666  try
667  {
668  bUserDisabled = isUserDisabled(sIdentifier, sFileName);
669  if (xOldExtension.is())
670  {
671  try
672  {
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());
680  }
681  catch (const lang::DisposedException &)
682  {
683  //Another thread might have removed the extension meanwhile
684  }
685  }
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 =
691  Reference<ucb::XCommandEnvironment> silentCommandEnv(pSilentCommandEnv);
692 
693  sal_Int32 failedPrereq = xTmpExtension->checkPrerequisites(
694  xAbortChannel, silentCommandEnv, true);
695  if (failedPrereq == 0)
696  {
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;
707 
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();
711 
713  sNewExtensionIdentifier, sNewExtensionFileName,
714  bUserDisabled2, false, xAbortChannel,
715  Reference<ucb::XCommandEnvironment>());
716  }
717  else
718  {
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());
727  }
728  }
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;
745  }
746  }
747 
748  if (excOccurred2.hasValue())
749  {
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.
755  try
756  {
757  if (xExtensionBackup.is())
758  {
759  xPackageManager->importExtension(
760  xExtensionBackup, Reference<task::XAbortChannel>(),
761  Reference<ucb::XCommandEnvironment>());
762  }
764  sIdentifier, sFileName, bUserDisabled, false,
765  Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
766  }
767  catch (...)
768  {
769  }
770  ::cppu::throwException(excOccurred2);
771  }
772  } // leaving the guarded section (getMutex())
773 
774  try
775  {
776  fireModified();
777 
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));
798  }
799 
800  return xNewExtension;
801 }
802 
804  OUString const & identifier, OUString const & fileName,
805  OUString const & repository,
806  Reference<task::XAbortChannel> const & xAbortChannel,
807  Reference<ucb::XCommandEnvironment> const & xCmdEnv )
808 {
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());
814  try
815  {
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);
825 
826  bUserDisabled = isUserDisabled(identifier, fileName);
827  //Backup the extension, in case the user cancels the action
828  xExtensionBackup = backupExtension(
829  identifier, fileName, xPackageManager, xCmdEnv);
830 
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);
836 
837  xPackageManager->removePackage(
838  identifier, fileName, xAbortChannel, xCmdEnv);
839  activateExtension(identifier, fileName, bUserDisabled, false,
840  xAbortChannel, xCmdEnv);
841  fireModified();
842  }
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;
859  }
860 
861  if (excOccurred1.hasValue())
862  {
863  //User aborted installation, restore the previous situation.
864  //Use a private AbortChannel so the user cannot interrupt.
865  try
866  {
867  Reference<ucb::XCommandEnvironment> tmpCmdEnv(
868  new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler()));
869  if (xExtensionBackup.is())
870  {
871  Reference<css::deployment::XPackage> xRestored =
872  xPackageManager->importExtension(
873  xExtensionBackup, Reference<task::XAbortChannel>(),
874  tmpCmdEnv);
876  identifier, fileName, bUserDisabled, false,
877  Reference<task::XAbortChannel>(),
878  tmpCmdEnv);
879 
880  getTmpRepository()->removePackage(
881  dp_misc::getIdentifier(xExtensionBackup),
882  xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
883  fireModified();
884  }
885  }
886  catch (...)
887  {
888  }
889  ::cppu::throwException(excOccurred1);
890  }
891 
892  if (xExtensionBackup.is())
893  getTmpRepository()->removePackage(
894  dp_misc::getIdentifier(xExtensionBackup),
895  xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
896 }
897 
898 // Only enable extensions from shared and user repository
900  Reference<css::deployment::XPackage> const & extension,
901  Reference<task::XAbortChannel> const & xAbortChannel,
902  Reference<ucb::XCommandEnvironment> const & xCmdEnv)
903 {
904  ::osl::MutexGuard guard(getMutex());
905  bool bUserDisabled = false;
906  uno::Any excOccurred;
907  try
908  {
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);
916 
917  bUserDisabled = isUserDisabled(dp_misc::getIdentifier(extension),
918  extension->getName());
919 
921  extension->getName(), false, false,
922  xAbortChannel, xCmdEnv);
923  }
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;
940  }
941 
942  if (excOccurred.hasValue())
943  {
944  try
945  {
947  extension->getName(), bUserDisabled, false,
948  xAbortChannel, xCmdEnv);
949  }
950  catch (...)
951  {
952  }
953  ::cppu::throwException(excOccurred);
954  }
955 }
956 
958  Reference<css::deployment::XPackage> const & extension,
959  Reference<task::XAbortChannel> const & xAbortChannel,
960  Reference<ucb::XCommandEnvironment> const & xCmdEnv)
961 {
962  try
963  {
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)
972  {
973  //There are some unfulfilled prerequisites, try to revoke
974  extension->revokePackage(false, xAbortChannel, xCmdEnv);
975  }
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;
981  }
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;
998  }
999 }
1000 
1002  Reference<css::deployment::XPackage> const & extension,
1003  Reference<task::XAbortChannel> const & xAbortChannel,
1004  Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1005 {
1006  ::osl::MutexGuard guard(getMutex());
1007  uno::Any excOccurred;
1008  bool bUserDisabled = false;
1009  try
1010  {
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);
1018 
1019  const OUString id(dp_misc::getIdentifier(extension));
1020  bUserDisabled = isUserDisabled(id, extension->getName());
1021 
1022  activateExtension(id, extension->getName(), true, false,
1023  xAbortChannel, xCmdEnv);
1024  }
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;
1041  }
1042 
1043  if (excOccurred.hasValue())
1044  {
1045  try
1046  {
1048  extension->getName(), bUserDisabled, false,
1049  xAbortChannel, xCmdEnv);
1050  }
1051  catch (...)
1052  {
1053  }
1054  ::cppu::throwException(excOccurred);
1055  }
1056 }
1057 
1058 uno::Sequence< Reference<css::deployment::XPackage> >
1060  OUString const & repository,
1061  Reference<task::XAbortChannel> const &xAbort,
1062  Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1063 {
1064  return getPackageManager(repository)->getDeployedPackages(
1065  xAbort, xCmdEnv);
1066 }
1067 
1068 Reference<css::deployment::XPackage>
1070  OUString const & repository,
1071  OUString const & identifier,
1072  OUString const & filename,
1073  Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1074 {
1075  return getPackageManager(repository)->getDeployedPackage(
1076  identifier, filename, xCmdEnv);
1077 }
1078 
1079 uno::Sequence< uno::Sequence<Reference<css::deployment::XPackage> > >
1081  Reference<task::XAbortChannel> const & xAbort,
1082  Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1083 {
1084  try
1085  {
1086  id2extensions mapExt;
1087 
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");
1097 
1098  // Create the tmp repository to trigger its clean up (deletion
1099  // of old temporary data.)
1100  getTmpRepository();
1101 
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);
1107 
1108  //sort the element according to the identifier
1109  std::sort(vecExtensions.begin(), vecExtensions.end(), CompIdentifiers());
1110 
1111  sal_Int32 j = 0;
1112  uno::Sequence< uno::Sequence<Reference<css::deployment::XPackage> > > seqSeq(vecExtensions.size());
1113  for (auto const& elem : vecExtensions)
1114  {
1115  seqSeq[j++] = comphelper::containerToSequence(elem);
1116  }
1117  return seqSeq;
1118 
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);
1134  }
1135 }
1136 
1137 // Only to be called from unopkg or soffice bootstrap (with force=true in the
1138 // latter case):
1140  sal_Bool force, OUString const & repository,
1141  Reference<task::XAbortChannel> const & xAbortChannel,
1142  Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1143 {
1144  try
1145  {
1146  Reference<css::deployment::XPackageManager>
1147  xPackageManager = getPackageManager(repository);
1148 
1149  std::set< OUString > disabledExts;
1150  {
1151  const uno::Sequence< Reference<css::deployment::XPackage> > extensions(
1152  xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv));
1153  for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos )
1154  {
1155  try
1156  {
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))
1162  {
1163  const OUString id = dp_misc::getIdentifier(extensions[ pos ]);
1164  OSL_ASSERT(!id.isEmpty());
1165  disabledExts.insert(id);
1166  }
1167  }
1168  catch (const lang::DisposedException &)
1169  {
1170  }
1171  }
1172  }
1173 
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));
1182 
1183  for ( sal_Int32 pos = 0; pos < extensions.getLength(); ++pos )
1184  {
1185  try
1186  {
1187  const OUString id = dp_misc::getIdentifier(extensions[ pos ]);
1188  const OUString fileName = extensions[ pos ]->getName();
1189  OSL_ASSERT(!id.isEmpty());
1191  id, fileName, disabledExts.find(id) != disabledExts.end(),
1192  true, xAbortChannel, xCmdEnv );
1193  }
1194  catch (const lang::DisposedException &)
1195  {
1196  }
1197  }
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);
1213  }
1214 }
1215 
1217  Reference<task::XAbortChannel> const & xAbortChannel,
1218  Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1219 {
1220  try
1221  {
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");
1228 
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");
1234 
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.)
1244  try
1245  {
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++)
1249  {
1250  uno::Sequence<Reference<css::deployment::XPackage> > const & seqExt =
1251  seqSeqExt[i];
1252  activateExtension(seqExt, isUserDisabled(seqExt), true,
1253  xAbortChannel, xCmdEnv);
1254  }
1255  }
1256  catch (...)
1257  {
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");
1261  }
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);
1282  }
1283 }
1284 
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.
1293  OUString const & displayName,
1294  Reference<ucb::XCommandEnvironment> const & cmdEnv)
1295 {
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;
1304  cmdEnv, &approve, &abort ))
1305  {
1306  OSL_ASSERT( !approve && !abort );
1307  throw css::deployment::DeploymentException(
1308  DpResId(RID_STR_ERROR_WHILE_ADDING) + displayName,
1309  static_cast<OWeakObject *>(this), request );
1310  }
1311  if (abort || !approve)
1312  throw ucb::CommandFailedException(
1313  DpResId(RID_STR_ERROR_WHILE_ADDING) + displayName,
1314  static_cast<OWeakObject *>(this), request );
1315 }
1316 
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.
1320 */
1322  OUString const & newVersion,
1323  OUString const & newDisplayName,
1324  Reference<css::deployment::XPackage> const & oldExtension,
1325  Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1326 {
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;
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 );
1343  }
1344  if (abort || !replace)
1345  throw ucb::CommandFailedException(
1346  DpResId(
1347  RID_STR_PACKAGE_ALREADY_ADDED) + newDisplayName,
1348  static_cast<OWeakObject *>(this), request );
1349 }
1350 
1351 uno::Sequence<Reference<css::deployment::XPackage> > SAL_CALL
1353  OUString const & repository,
1354  Reference<ucb::XCommandEnvironment> const & xCmdEnv)
1355 {
1356  Reference<css::deployment::XPackageManager>
1357  xPackageManager = getPackageManager(repository);
1358  ::osl::MutexGuard guard(getMutex());
1359  return xPackageManager->getExtensionsWithUnacceptedLicenses(xCmdEnv);
1360 }
1361 
1363 {
1364  return getPackageManager(repository)->isReadOnly();
1365 }
1366 
1367 
1368 namespace sdecl = comphelper::service_decl;
1371  servicePIP,
1372  // a private one:
1373  "com.sun.star.comp.deployment.ExtensionManager",
1374  "com.sun.star.comp.deployment.ExtensionManager");
1375 
1376 // XModifyBroadcaster
1377 
1379  Reference<util::XModifyListener> const & xListener )
1380 {
1381  check();
1382  rBHelper.addListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
1383 }
1384 
1385 
1387  Reference<util::XModifyListener> const & xListener )
1388 {
1389  check();
1390  rBHelper.removeListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
1391 }
1392 
1394 {
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) );
1400  }
1401 }
1402 
1404 {
1405  ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer(
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))); });
1411  }
1412 }
1413 
1414 } // namespace dp_manager
1415 
1416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unordered_map< OUString, std::vector< css::uno::Reference< css::deployment::XPackage > > > id2extensions
virtual css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > SAL_CALL getExtensionsWithUnacceptedLicenses(OUString const &repository, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual void SAL_CALL reinstallDeployedExtensions(sal_Bool force, OUString const &repository, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
::osl::Mutex & getMutex() const
Definition: dp_misc.h:45
virtual sal_Int32 SAL_CALL checkPrerequisitesAndEnable(css::uno::Reference< css::deployment::XPackage > const &extension, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
css::uno::Reference< css::deployment::XPackageManager > getPackageManager(OUString const &repository)
bool hasValue()
virtual void SAL_CALL removeModifyListener(css::uno::Reference< css::util::XModifyListener > const &xListener) override
css::uno::Reference< css::deployment::XPackageManager > getBakRepository()
virtual css::uno::Sequence< css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > > SAL_CALL getAllExtensions(css::uno::Reference< css::task::XAbortChannel > const &, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual css::uno::Reference< css::deployment::XPackage > SAL_CALL addExtension(OUString const &url, css::uno::Sequence< css::beans::NamedValue > const &properties, OUString const &repository, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
void SAL_CALL throwException(Any const &exc)
virtual void SAL_CALL removeExtension(OUString const &identifier, OUString const &filename, OUString const &repository, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
css::uno::Reference< css::deployment::XPackageManager > getTmpRepository()
ExtensionManager(css::uno::Reference< css::uno::XComponentContext >const &xContext)
void syncRepositories(bool force, Reference< ucb::XCommandEnvironment > const &xCmdEnv)
Definition: dp_misc.cxx:532
void update(OUString const &status) const
Definition: dp_interact.h:80
void activateExtension(OUString const &identifier, OUString const &fileName, bool bUserDisabled, bool bStartup, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv)
std::vector< OUString > m_repositoryNames
Any SAL_CALL getCaughtException()
virtual css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > SAL_CALL getDeployedExtensions(OUString const &repository, css::uno::Reference< css::task::XAbortChannel > const &, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > SAL_CALL getExtensionsWithSameIdentifier(OUString const &identifier, OUString const &filename, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
bool doChecksForAddExtension(css::uno::Reference< css::deployment::XPackageManager > const &xPackageMgr, css::uno::Sequence< css::beans::NamedValue > const &properties, css::uno::Reference< css::deployment::XPackage > const &xTmpExtension, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, css::uno::Reference< css::deployment::XPackage > &out_existingExtension)
virtual sal_Bool SAL_CALL isReadOnlyRepository(OUString const &repository) override
#define SAL_N_ELEMENTS(arr)
css::uno::Reference< css::deployment::XPackageManager > getUserRepository()
virtual css::uno::Reference< css::deployment::XPackage > SAL_CALL getDeployedExtension(OUString const &repository, OUString const &identifier, OUString const &filename, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
Reference< io::XInputStream > createInputStream(std::vector< sal_Int8 > const &rInData)
::boost::optional< SimpleLicenseAttributes > getSimpleLicenseAttributes() const
returns the attributes of the simple-license element
comphelper::service_decl::ServiceDecl const serviceDecl
Definition: dp_services.hxx:22
css::uno::Reference< css::deployment::XPackageManagerFactory > m_xPackageManagerFactory
css::uno::Reference< css::uno::XComponentContext > m_xContext
css::uno::Reference< css::deployment::XPackage > backupExtension(OUString const &identifier, OUString const &fileName, css::uno::Reference< css::deployment::XPackageManager > const &xPackageManager, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv)
int i
unsigned char sal_Bool
const uno::Reference< deployment::XPackage > m_extension
virtual sal_Bool SAL_CALL synchronize(css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
sdecl::class_< ExtensionManager > const servicePIP
tuple index
virtual void SAL_CALL disableExtension(css::uno::Reference< css::deployment::XPackage > const &extension, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
css::uno::Reference< css::deployment::XPackageManager > getSharedRepository()
void addExtensionsToMap(id2extensions &mapExt, css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > const &seqExt, OUString const &repository)
this class is for use in XPackageManager::checkPrerequisites
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DescriptionInfoset getDescriptionInfoset(OUString const &sExtensionFolderURL)
creates a DescriptionInfoset object.
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:1604
std::vector< css::uno::Reference< css::deployment::XPackage > > getExtensionsWithSameId(OUString const &identifier, OUString const &fileName)
css::uno::Reference< css::deployment::XPackageManager > getBundledRepository()
bool isUserDisabled(OUString const &identifier, OUString const &filename)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
virtual css::uno::Reference< css::task::XAbortChannel > SAL_CALL createAbortChannel() override
void checkUpdate(OUString const &newVersion, OUString const &newDisplayName, css::uno::Reference< css::deployment::XPackage > const &oldExtension, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv)
virtual css::uno::Sequence< css::uno::Reference< css::deployment::XPackageTypeInfo > > SAL_CALL getSupportedPackageTypes() override
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool erase_path(OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
virtual void SAL_CALL enableExtension(css::uno::Reference< css::deployment::XPackage > const &extension, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
void checkInstall(OUString const &displayName, css::uno::Reference< css::ucb::XCommandEnvironment > const &cmdEnv)
OUString DpResId(const char *pId)
Definition: dp_shared.hxx:38
void forEach(FuncT const &func)
virtual void SAL_CALL addModifyListener(css::uno::Reference< css::util::XModifyListener > const &xListener) override
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool interactContinuation(css::uno::Any const &request, css::uno::Type const &continuation, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool *pcont, bool *pabort)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getIdentifier(css::uno::Reference< css::deployment::XPackage > const &package)
Gets the identifier of a package.
void set(css::uno::UnoInterfaceReference const &value)
const uno::Reference< uno::XComponentContext > m_xContext
OUString sDisplayName
Access to the content of an XML description element.
::osl::Mutex & getMutex()