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