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