1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <dp_interact.h>
24 #include <dp_registry.hxx>
25 #include <dp_shared.hxx>
26 #include <strings.hrc>
28 #include <dp_platform.hxx>
29 #include "dp_manager.h"
30 #include <dp_identifier.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/string.hxx>
33 #include <rtl/uri.hxx>
34 #include <rtl/bootstrap.hxx>
35 #include <sal/log.hxx>
36 #include <tools/urlobj.hxx>
37 #include <comphelper/diagnose_ex.hxx>
38 #include <osl/diagnose.h>
39 #include <osl/file.hxx>
40 #include <osl/security.hxx>
41 #include <cppuhelper/exc_hlp.hxx>
42 #include <comphelper/logging.hxx>
43 #include <comphelper/sequence.hxx>
45 #include <xmlscript/xml_helper.hxx>
46 #include <svl/inettype.hxx>
47 #include <com/sun/star/lang/IllegalArgumentException.hpp>
48 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
49 #include <com/sun/star/beans/UnknownPropertyException.hpp>
50 #include <com/sun/star/logging/LogLevel.hpp>
51 #include <com/sun/star/logging/FileHandler.hpp>
52 #include <com/sun/star/logging/SimpleTextFormatter.hpp>
53 #include <com/sun/star/logging/XLogger.hpp>
54 #include <com/sun/star/util/XUpdatable.hpp>
55 #include <com/sun/star/sdbc/XResultSet.hpp>
56 #include <com/sun/star/sdbc/XRow.hpp>
57 #include <com/sun/star/ucb/CommandAbortedException.hpp>
58 #include <com/sun/star/ucb/CommandFailedException.hpp>
59 #include <com/sun/star/ucb/ContentCreationException.hpp>
60 #include <com/sun/star/ucb/XContentAccess.hpp>
61 #include <com/sun/star/ucb/NameClash.hpp>
62 #include <com/sun/star/deployment/DeploymentException.hpp>
63 #include <com/sun/star/deployment/InvalidRemovedParameterException.hpp>
64 #include <com/sun/star/deployment/Prerequisites.hpp>
65 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
66 #include <unotools/tempfile.hxx>
68 #include <dp_descriptioninfoset.hxx>
69 #include "dp_commandenvironments.hxx"
70 #include "dp_properties.hxx"
75 using namespace ::dp_misc
;
76 using namespace ::com::sun::star
;
77 using namespace ::com::sun::star::uno
;
78 using namespace ::com::sun::star::ucb
;
79 using namespace ::com::sun::star::logging
;
82 namespace dp_manager
{
89 explicit MatchTempDir( OUString str
) : m_str(std::move( str
)) {}
90 bool operator () ( ActivePackages::Entries::value_type
const & v
) const {
91 return v
.second
.temporaryName
.equalsIgnoreAsciiCase( m_str
);
95 OUString
getExtensionFolder(OUString
const & parentFolder
,
96 Reference
<ucb::XCommandEnvironment
> const & xCmdEnv
,
97 Reference
<uno::XComponentContext
> const & xContext
)
99 ::ucbhelper::Content
tempFolder( parentFolder
, xCmdEnv
, xContext
);
100 Reference
<sdbc::XResultSet
> xResultSet(
101 StrTitle::createCursor (tempFolder
, ::ucbhelper::INCLUDE_FOLDERS_ONLY
) );
104 if (xResultSet
->next())
106 title
= Reference
<sdbc::XRow
>(
107 xResultSet
, UNO_QUERY_THROW
)->getString(1 /* Title */ ) ;
113 void PackageManagerImpl::initActivationLayer(
114 Reference
<XCommandEnvironment
> const & xCmdEnv
)
116 if (m_activePackages
.isEmpty())
118 OSL_ASSERT( m_registryCache
.isEmpty() );
119 // documents temp activation:
120 m_activePackagesDB
.reset( new ActivePackages
);
121 ::ucbhelper::Content ucbContent
;
122 if (create_ucb_content( &ucbContent
, m_context
, xCmdEnv
,
123 false /* no throw */ ))
125 // scan for all entries in m_packagesDir:
126 Reference
<sdbc::XResultSet
> xResultSet(
127 StrTitle::createCursor (ucbContent
, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS
) );
129 while (xResultSet
->next())
131 Reference
<sdbc::XRow
> xRow( xResultSet
, UNO_QUERY_THROW
);
132 OUString
title( xRow
->getString( 1 /* Title */ ) );
133 // xxx todo: remove workaround for tdoc
134 if ( title
== "this_is_a_dummy_stream_just_there_as_a_workaround_for_a_temporary_limitation_of_the_storage_api_implementation" )
136 if ( title
== "META-INF" )
139 ::ucbhelper::Content
sourceContent(
140 Reference
<XContentAccess
>(
141 xResultSet
, UNO_QUERY_THROW
)->queryContent(),
142 xCmdEnv
, m_xComponentContext
);
144 OUString
mediaType( detectMediaType( sourceContent
,
145 false /* no throw */) );
146 if (!mediaType
.isEmpty())
148 ActivePackages::Data dbData
;
149 insertToActivationLayer(
150 Sequence
<css::beans::NamedValue
>(),mediaType
, sourceContent
,
153 insertToActivationLayerDB( title
, dbData
);
154 //TODO #i73136#: insertToActivationLayerDB needs id not
155 // title, but the whole m_activePackages.getLength()==0
156 // case (i.e., document-relative deployment) currently
157 // does not work, anyway.
165 OSL_ASSERT( !m_activePackages
.isEmpty() );
166 m_activePackages_expanded
= expandUnoRcUrl( m_activePackages
);
167 m_registrationData_expanded
= expandUnoRcUrl(m_registrationData
);
169 create_folder( nullptr, m_activePackages_expanded
, xCmdEnv
);
172 if (m_context
== "user")
173 dbName
= m_activePackages_expanded
+ ".pmap";
176 // Create the extension data base in the user installation
177 create_folder( nullptr, m_registrationData_expanded
, xCmdEnv
);
178 dbName
= m_registrationData_expanded
+ "/extensions.pmap";
180 // The data base can always be written because it is always in the user installation
181 m_activePackagesDB
.reset( new ActivePackages( dbName
) );
183 if (! m_readOnly
&& m_context
!= "bundled")
185 // clean up activation layer, scan for zombie temp dirs:
186 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
188 ::ucbhelper::Content
tempFolder( m_activePackages_expanded
, xCmdEnv
, m_xComponentContext
);
189 Reference
<sdbc::XResultSet
> xResultSet(
190 StrTitle::createCursor (tempFolder
,
191 ::ucbhelper::INCLUDE_DOCUMENTS_ONLY
) );
193 // get all temp directories:
194 std::vector
<OUString
> tempEntries
;
195 std::vector
<OUString
> removedEntries
;
196 while (xResultSet
->next())
199 Reference
<sdbc::XRow
>(
200 xResultSet
, UNO_QUERY_THROW
)->getString(
202 if (title
.endsWith("removed", &title
))
204 //save the file name without the "removed" part
205 removedEntries
.push_back(::rtl::Uri::encode(
206 title
, rtl_UriCharClassPchar
,
207 rtl_UriEncodeIgnoreEscapes
,
208 RTL_TEXTENCODING_UTF8
) );
212 tempEntries
.push_back( ::rtl::Uri::encode(
213 title
, rtl_UriCharClassPchar
,
214 rtl_UriEncodeIgnoreEscapes
,
215 RTL_TEXTENCODING_UTF8
) );
219 bool bShared
= (m_context
== "shared");
220 for (const OUString
& tempEntry
: tempEntries
)
222 const MatchTempDir
match( tempEntry
);
223 if (std::none_of( id2temp
.begin(), id2temp
.end(), match
))
226 makeURL(m_activePackages_expanded
, tempEntry
) );
228 //In case of shared extensions, new entries are regarded as
229 //added extensions if there is no xxx.tmpremoved file.
232 if (std::find(removedEntries
.begin(), removedEntries
.end(), tempEntry
) ==
233 removedEntries
.end())
239 //Make sure only the same user removes the extension, who
240 //previously unregistered it. This is avoid races if multiple instances
241 //of OOo are running which all have write access to the shared installation.
242 //For example, a user removes the extension, but keeps OOo
243 //running. Parts of the extension may still be loaded and used by OOo.
244 //Therefore the extension is only deleted the next time the extension manager is
245 //run after restarting OOo. While OOo is still running, another user starts OOo
246 //which would deleted the extension files. If the same user starts another
247 //instance of OOo then the lock file will prevent this.
249 ::osl::Security aSecurity
;
250 aSecurity
.getUserName( aUserName
);
251 ucbhelper::Content
remFileContent(
252 url
+ "removed", Reference
<XCommandEnvironment
>(), m_xComponentContext
);
253 std::vector
<sal_Int8
> data
= dp_misc::readFile(remFileContent
);
254 std::string_view
osData(reinterpret_cast<const char*>(data
.data()),
256 OUString sData
= OStringToOUString(
257 osData
, RTL_TEXTENCODING_UTF8
);
258 if (sData
!= aUserName
)
262 // temp entry not needed anymore:
263 erase_path( url
+ "_",
264 Reference
<XCommandEnvironment
>(),
265 false /* no throw: ignore errors */ );
266 erase_path( url
, Reference
<XCommandEnvironment
>(),
267 false /* no throw: ignore errors */ );
268 //delete the xxx.tmpremoved file
269 erase_path(url
+ "removed",
270 Reference
<XCommandEnvironment
>(), false);
278 void PackageManagerImpl::initRegistryBackends()
280 if (!m_registryCache
.isEmpty())
281 create_folder( nullptr, m_registryCache
,
282 Reference
<XCommandEnvironment
>(), false);
283 m_xRegistry
.set( ::dp_registry::create(
284 m_context
, m_registryCache
,
285 m_xComponentContext
) );
290 osl::FileBase::RC
createDirectory(OUString
const & url
) {
291 auto e
= osl::Directory::create(url
);
292 if (e
!= osl::FileBase::E_NOENT
) {
295 INetURLObject
o(url
);
296 if (!o
.removeSegment()) {
297 return osl::FileBase::E_INVAL
; // anything but E_None/E_EXIST
299 e
= createDirectory(o
.GetMainURL(INetURLObject::DecodeMechanism::NONE
));
300 if (e
!= osl::FileBase::E_None
&& e
!= osl::FileBase::E_EXIST
) {
303 return osl::Directory::create(url
);
306 bool isMacroURLReadOnly( const OUString
&rMacro
)
308 OUString
aDirURL( rMacro
);
309 ::rtl::Bootstrap::expandMacros( aDirURL
);
311 ::osl::FileBase::RC aErr
= createDirectory( aDirURL
);
312 if ( aErr
== ::osl::FileBase::E_None
)
313 return false; // it will be writeable
314 if ( aErr
!= ::osl::FileBase::E_EXIST
)
315 return true; // some serious problem creating it
318 sal_uInt64 nWritten
= 0;
319 OUString
aFileURL( aDirURL
+ "/stamp.sys" );
320 ::osl::File
aFile( aFileURL
);
322 bError
= aFile
.open( osl_File_OpenFlag_Read
|
323 osl_File_OpenFlag_Write
|
324 osl_File_OpenFlag_Create
) != ::osl::FileBase::E_None
;
326 bError
= aFile
.write( "1", 1, nWritten
) != ::osl::FileBase::E_None
;
327 if (aFile
.close() != ::osl::FileBase::E_None
)
329 if (osl::File::remove( aFileURL
) != ::osl::FileBase::E_None
)
333 "desktop.deployment",
334 "local url '" << rMacro
<< "' -> '" << aFileURL
<< "' "
335 << (bError
? "is" : "is not") << " readonly\n");
341 Reference
<deployment::XPackageManager
> PackageManagerImpl::create(
342 Reference
<XComponentContext
> const & xComponentContext
,
343 OUString
const & context
)
345 rtl::Reference
<PackageManagerImpl
> that
= new PackageManagerImpl(
346 xComponentContext
, context
);
348 OUString logFile
, stamp
;
349 if ( context
== "user" ) {
350 that
->m_activePackages
= "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages";
351 that
->m_registrationData
= "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE";
352 that
->m_registryCache
= "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/registry";
353 logFile
= "$UNO_USER_PACKAGES_CACHE/log.txt";
354 //We use the extension .sys for the file because on Windows Vista a sys
355 //(as well as exe and dll) file
356 //will not be written in the VirtualStore. For example if the process has no
357 //admin right once cannot write to the %programfiles% folder. However, when
358 //virtualization is used, the file will be written into the VirtualStore and
359 //it appears as if one could write to %programfiles%. When we test for write
360 //access to the office/shared folder for shared extensions then this typically
361 //fails because a normal user typically cannot write to this folder. However,
362 //using virtualization it appears that he/she can. Then a shared extension can
363 //be installed but is only visible for the user (because the extension is in
364 //the virtual store).
365 stamp
= "$UNO_USER_PACKAGES_CACHE";
367 else if ( context
== "shared" ) {
368 that
->m_activePackages
= "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages";
369 that
->m_registrationData
= "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER";
370 that
->m_registryCache
= "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/registry";
371 logFile
= "$SHARED_EXTENSIONS_USER/log.txt";
372 #if !HAVE_FEATURE_READONLY_INSTALLSET
373 // The "shared" extensions are read-only when we have a
374 // read-only installset.
375 stamp
= "$UNO_SHARED_PACKAGES_CACHE";
378 else if ( context
== "bundled" ) {
379 that
->m_activePackages
= "vnd.sun.star.expand:$BUNDLED_EXTENSIONS";
380 that
->m_registrationData
= "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER";
381 that
->m_registryCache
= "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/registry";
382 logFile
= "$BUNDLED_EXTENSIONS_USER/log.txt";
383 //No stamp file. We assume that bundled is always readonly. It must not be
384 //modified from ExtensionManager but only by the installer
386 else if ( context
== "tmp" ) {
387 that
->m_activePackages
= "vnd.sun.star.expand:$TMP_EXTENSIONS/extensions";
388 that
->m_registrationData
= "vnd.sun.star.expand:$TMP_EXTENSIONS";
389 that
->m_registryCache
= "vnd.sun.star.expand:$TMP_EXTENSIONS/registry";
390 stamp
= "$TMP_EXTENSIONS";
392 else if (context
== "bak") {
393 that
->m_activePackages
= "vnd.sun.star.expand:$BAK_EXTENSIONS/extensions";
394 that
->m_registrationData
= "vnd.sun.star.expand:$BAK_EXTENSIONS";
395 that
->m_registryCache
= "vnd.sun.star.expand:$BAK_EXTENSIONS/registry";
396 stamp
= "$BAK_EXTENSIONS";
399 else if (! context
.match("vnd.sun.star.tdoc:/")) {
400 throw lang::IllegalArgumentException(
401 "invalid context given: " + context
,
402 Reference
<XInterface
>(), static_cast<sal_Int16
>(-1) );
405 Reference
<XCommandEnvironment
> xCmdEnv
;
408 // There is no stamp for the bundled folder:
409 if (!stamp
.isEmpty())
410 that
->m_readOnly
= isMacroURLReadOnly( stamp
);
412 if (!that
->m_readOnly
&& !logFile
.isEmpty())
414 // Initialize logger which will be used in ProgressLogImpl (created below)
415 rtl::Bootstrap::expandMacros(logFile
);
416 comphelper::EventLogger
logger(xComponentContext
, "unopkg");
417 const Reference
<XLogger
> xLogger(logger
.getLogger());
418 Reference
<XLogFormatter
> xLogFormatter(SimpleTextFormatter::create(xComponentContext
));
419 Sequence
< beans::NamedValue
> aSeq2
{ { "Formatter", Any(xLogFormatter
) }, {"FileURL", Any(logFile
)} };
420 Reference
<XLogHandler
> xFileHandler(css::logging::FileHandler::createWithSettings(xComponentContext
, aSeq2
));
421 xFileHandler
->setLevel(LogLevel::WARNING
);
422 xLogger
->addLogHandler(xFileHandler
);
424 that
->m_xLogFile
.set(
425 that
->m_xComponentContext
->getServiceManager()
426 ->createInstanceWithArgumentsAndContext(
427 "com.sun.star.comp.deployment.ProgressLog",
429 that
->m_xComponentContext
),
431 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv
, that
->m_xLogFile
) );
434 that
->initRegistryBackends();
435 that
->initActivationLayer( xCmdEnv
);
440 catch (const RuntimeException
&) {
443 catch (const Exception
& e
) {
444 Any
exc( ::cppu::getCaughtException() );
445 throw lang::WrappedTargetRuntimeException(
446 ("[context=\"" + context
+ "\"] caught unexpected "
447 + exc
.getValueType().getTypeName() + ": " + e
.Message
),
448 Reference
<XInterface
>(), exc
);
453 PackageManagerImpl::~PackageManagerImpl()
458 void PackageManagerImpl::fireModified()
460 ::cppu::OInterfaceContainerHelper
* pContainer
= rBHelper
.getContainer(
461 cppu::UnoType
<util::XModifyListener
>::get() );
462 if (pContainer
!= nullptr) {
463 pContainer
->forEach
<util::XModifyListener
>(
464 [this] (uno::Reference
<util::XModifyListener
> const& xListener
)
465 { return xListener
->modified(lang::EventObject(static_cast<OWeakObject
*>(this))); });
470 void PackageManagerImpl::disposing()
473 // // xxx todo: guarding?
474 // ::osl::MutexGuard guard( getMutex() );
475 try_dispose( m_xLogFile
);
477 try_dispose( m_xRegistry
);
479 m_activePackagesDB
.reset();
480 m_xComponentContext
.clear();
482 t_pm_helper::disposing();
485 catch (const RuntimeException
&) {
488 catch (const Exception
&) {
489 Any
exc( ::cppu::getCaughtException() );
490 throw lang::WrappedTargetRuntimeException(
491 "caught unexpected exception while disposing...",
492 static_cast<OWeakObject
*>(this), exc
);
498 void PackageManagerImpl::dispose()
500 //Do not call check here. We must not throw an exception here if the object
501 //is being disposed or is already disposed. See com.sun.star.lang.XComponent
502 WeakComponentImplHelperBase::dispose();
506 void PackageManagerImpl::addEventListener(
507 Reference
<lang::XEventListener
> const & xListener
)
509 //Do not call check here. We must not throw an exception here if the object
510 //is being disposed or is already disposed. See com.sun.star.lang.XComponent
511 WeakComponentImplHelperBase::addEventListener( xListener
);
515 void PackageManagerImpl::removeEventListener(
516 Reference
<lang::XEventListener
> const & xListener
)
518 //Do not call check here. We must not throw an exception here if the object
519 //is being disposed or is already disposed. See com.sun.star.lang.XComponent
520 WeakComponentImplHelperBase::removeEventListener( xListener
);
525 OUString
PackageManagerImpl::getContext()
532 Sequence
< Reference
<deployment::XPackageTypeInfo
> >
533 PackageManagerImpl::getSupportedPackageTypes()
535 OSL_ASSERT( m_xRegistry
.is() );
536 return m_xRegistry
->getSupportedPackageTypes();
540 Reference
<task::XAbortChannel
> PackageManagerImpl::createAbortChannel()
543 return new AbortChannel
;
546 // XModifyBroadcaster
548 void PackageManagerImpl::addModifyListener(
549 Reference
<util::XModifyListener
> const & xListener
)
552 rBHelper
.addListener( cppu::UnoType
<decltype(xListener
)>::get(), xListener
);
556 void PackageManagerImpl::removeModifyListener(
557 Reference
<util::XModifyListener
> const & xListener
)
560 rBHelper
.removeListener( cppu::UnoType
<decltype(xListener
)>::get(), xListener
);
564 OUString
PackageManagerImpl::detectMediaType(
565 ::ucbhelper::Content
const & ucbContent_
, bool throw_exc
)
567 ::ucbhelper::Content
ucbContent(ucbContent_
);
568 OUString
url( ucbContent
.getURL() );
570 if (url
.match( "vnd.sun.star.tdoc:" ) || url
.match( "vnd.sun.star.pkg:" ))
573 ucbContent
.getPropertyValue( "MediaType" ) >>= mediaType
;
575 catch (const beans::UnknownPropertyException
&) {
577 OSL_ENSURE( !mediaType
.isEmpty(), "### no media-type?!" );
579 if (mediaType
.isEmpty())
582 Reference
<deployment::XPackage
> xPackage(
583 m_xRegistry
->bindPackage(
584 url
, OUString(), false, OUString(), ucbContent
.getCommandEnvironment() ) );
585 const Reference
<deployment::XPackageTypeInfo
> xPackageType(
586 xPackage
->getPackageType() );
587 OSL_ASSERT( xPackageType
.is() );
588 if (xPackageType
.is())
589 mediaType
= xPackageType
->getMediaType();
591 catch (const lang::IllegalArgumentException
&) {
594 css::uno::Any
ex( cppu::getCaughtException() );
595 SAL_WARN( "desktop", exceptionToString(ex
) );
602 OUString
PackageManagerImpl::insertToActivationLayer(
603 Sequence
<beans::NamedValue
> const & properties
,
604 OUString
const & mediaType
, ::ucbhelper::Content
const & sourceContent_
,
605 OUString
const & title
, ActivePackages::Data
* dbData
)
607 ::ucbhelper::Content
sourceContent(sourceContent_
);
608 Reference
<XCommandEnvironment
> xCmdEnv(
609 sourceContent
.getCommandEnvironment() );
611 OUString tempEntry
= ::utl::CreateTempURL(&m_activePackages_expanded
, false);
612 tempEntry
= tempEntry
.copy(tempEntry
.lastIndexOf('/') + 1);
613 OUString destFolder
= makeURL( m_activePackages
, tempEntry
) + "_";
615 // prepare activation folder:
616 ::ucbhelper::Content destFolderContent
;
617 create_folder( &destFolderContent
, destFolder
, xCmdEnv
);
619 // copy content into activation temp dir:
620 if (mediaType
.matchIgnoreAsciiCase("application/vnd.sun.star.package-bundle") ||
621 // xxx todo: more sophisticated parsing
622 mediaType
.matchIgnoreAsciiCase("application/vnd.sun.star.legacy-package-bundle"))
626 if (!sourceContent
.isFolder())
628 buf
.append( "vnd.sun.star.zip://" );
629 buf
.append( ::rtl::Uri::encode( sourceContent
.getURL(),
630 rtl_UriCharClassRegName
,
631 rtl_UriEncodeIgnoreEscapes
,
632 RTL_TEXTENCODING_UTF8
) );
636 //Folder. No need to unzip, just copy
637 buf
.append(sourceContent
.getURL());
640 sourceContent
= ::ucbhelper::Content(
641 buf
.makeStringAndClear(), xCmdEnv
, m_xComponentContext
);
643 destFolderContent
.transferContent(
644 sourceContent
, ::ucbhelper::InsertOperation::Copy
,
645 title
, NameClash::OVERWRITE
);
649 //bundled extensions should only be added by the synchronizeAddedExtensions
650 //functions. Moreover, there is no "temporary folder" for bundled extensions.
651 OSL_ASSERT(!(m_context
== "bundled"));
652 OUString sFolderUrl
= makeURLAppendSysPathSegment(destFolderContent
.getURL(), title
);
653 DescriptionInfoset info
=
654 dp_misc::getDescriptionInfoset(sFolderUrl
);
655 dbData
->temporaryName
= tempEntry
;
656 dbData
->fileName
= title
;
657 dbData
->mediaType
= mediaType
;
658 dbData
->version
= info
.getVersion();
660 //No write the properties file next to the extension
661 ExtensionProperties
props(sFolderUrl
, properties
, xCmdEnv
, m_xComponentContext
);
667 void PackageManagerImpl::insertToActivationLayerDB(
668 OUString
const & id
, ActivePackages::Data
const & dbData
)
670 //access to the database must be guarded. See removePackage
671 const ::osl::MutexGuard
guard( m_aMutex
);
672 m_activePackagesDB
->put( id
, dbData
);
676 /* The function returns true if there is an extension with the same id already
677 installed which needs to be uninstalled, before the new extension can be installed.
679 bool PackageManagerImpl::isInstalled(
680 Reference
<deployment::XPackage
> const & package
)
682 OUString
id(dp_misc::getIdentifier(package
));
683 OUString
fn(package
->getName());
684 bool bInstalled
= false;
685 if (m_activePackagesDB
->has( id
, fn
))
694 Reference
<deployment::XPackage
> PackageManagerImpl::importExtension(
695 Reference
<deployment::XPackage
> const & extension
,
696 Reference
<task::XAbortChannel
> const & xAbortChannel
,
697 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
699 return addPackage(extension
->getURL(), Sequence
<beans::NamedValue
>(),
700 OUString(), xAbortChannel
, xCmdEnv_
);
703 /* The function adds an extension but does not register it!!!
704 It may not do any user interaction. This is done in XExtensionManager::addExtension
706 Reference
<deployment::XPackage
> PackageManagerImpl::addPackage(
707 OUString
const & url
,
708 css::uno::Sequence
<css::beans::NamedValue
> const & properties
,
709 OUString
const & mediaType_
,
710 Reference
<task::XAbortChannel
> const & xAbortChannel
,
711 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
717 if (m_context
== "shared")
718 message
= "You need write permissions to install a shared extension!";
720 message
= "You need write permissions to install this extension!";
721 throw deployment::DeploymentException(
722 message
, static_cast<OWeakObject
*>(this), Any() );
724 Reference
<XCommandEnvironment
> xCmdEnv
;
726 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
728 xCmdEnv
.set( xCmdEnv_
);
731 ::ucbhelper::Content sourceContent
;
732 (void)create_ucb_content( &sourceContent
, url
, xCmdEnv
); // throws exc
733 const OUString
title( StrTitle::getTitle( sourceContent
) );
734 const OUString
title_enc( ::rtl::Uri::encode(
735 title
, rtl_UriCharClassPchar
,
736 rtl_UriEncodeIgnoreEscapes
,
737 RTL_TEXTENCODING_UTF8
) );
740 OUString
mediaType(mediaType_
);
741 if (mediaType
.isEmpty())
742 mediaType
= detectMediaType( sourceContent
);
744 Reference
<deployment::XPackage
> xPackage
;
747 DpResId(RID_STR_COPYING_PACKAGE
) + title
, xCmdEnv
);
748 if (m_activePackages
.isEmpty())
750 ::ucbhelper::Content docFolderContent
;
751 create_folder( &docFolderContent
, m_context
, xCmdEnv
);
752 // copy into document, first:
753 docFolderContent
.transferContent(
754 sourceContent
, ::ucbhelper::InsertOperation::Copy
,
756 NameClash::ASK
/* xxx todo: ASK not needed? */);
758 ::ucbhelper::Content
docContent(
759 makeURL( m_context
, title_enc
), xCmdEnv
, m_xComponentContext
);
760 //TODO #i73136#: using title instead of id can lead to
761 // clashes, but the whole m_activePackages.getLength()==0
762 // case (i.e., document-relative deployment) currently does
764 docContent
.setPropertyValue("MediaType", Any(mediaType
) );
766 // xxx todo: obsolete in the future
768 docFolderContent
.executeCommand( "flush", Any() );
770 catch (const UnsupportedCommandException
&) {
773 ActivePackages::Data dbData
;
774 destFolder
= insertToActivationLayer(
775 properties
, mediaType
, sourceContent
, title
, &dbData
);
778 // bind activation package:
779 //Because every shared/user extension will be unpacked in a folder,
780 //which was created with a unique name we will always have two different
781 //XPackage objects, even if the second extension is the same.
782 //Therefore bindPackage does not need a guard here.
783 xPackage
= m_xRegistry
->bindPackage(
784 makeURL( destFolder
, title_enc
), mediaType
, false, OUString(), xCmdEnv
);
786 OSL_ASSERT( xPackage
.is() );
789 bool install
= false;
792 OUString
const id
= dp_misc::getIdentifier( xPackage
);
794 std::unique_lock
g(m_addMutex
);
795 if (isInstalled(xPackage
))
797 //Do not guard the complete function with the getMutex
798 removePackage(id
, xPackage
->getName(), xAbortChannel
,
802 insertToActivationLayerDB(id
, dbData
);
806 deletePackageFromCache( xPackage
, destFolder
);
811 deletePackageFromCache( xPackage
, destFolder
);
813 //ToDo: We should notify only if the extension is registered
818 catch (const RuntimeException
&) {
821 catch (const CommandFailedException
& exc
) {
822 logIntern( Any(exc
) );
825 catch (const CommandAbortedException
& exc
) {
826 logIntern( Any(exc
) );
829 catch (const deployment::DeploymentException
& exc
) {
830 logIntern( Any(exc
) );
833 catch (const Exception
&) {
834 Any
exc( ::cppu::getCaughtException() );
836 throw deployment::DeploymentException(
837 DpResId(RID_STR_ERROR_WHILE_ADDING
) + url
,
838 static_cast<OWeakObject
*>(this), exc
);
841 void PackageManagerImpl::deletePackageFromCache(
842 Reference
<deployment::XPackage
> const & xPackage
,
843 OUString
const & destFolder
)
845 try_dispose( xPackage
);
847 //we remove the package from the uno cache
848 //no service from the package may be loaded at this time!!!
849 erase_path( destFolder
, Reference
<XCommandEnvironment
>(),
850 false /* no throw: ignore errors */ );
851 //rm last character '_'
852 OUString url
= destFolder
.copy(0, destFolder
.getLength() - 1);
853 erase_path( url
, Reference
<XCommandEnvironment
>(),
854 false /* no throw: ignore errors */ );
858 void PackageManagerImpl::removePackage(
859 OUString
const & id
, OUString
const & fileName
,
860 Reference
<task::XAbortChannel
> const & /*xAbortChannel*/,
861 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
865 Reference
<XCommandEnvironment
> xCmdEnv
;
867 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
869 xCmdEnv
.set( xCmdEnv_
);
872 Reference
<deployment::XPackage
> xPackage
;
874 const ::osl::MutexGuard
guard(m_aMutex
);
875 //Check if this extension exist and throw an IllegalArgumentException
877 //If the files of the extension are already removed, or there is a
878 //different extension at the same place, for example after updating the
879 //extension, then the returned object is that which uses the database data.
880 xPackage
= getDeployedPackage_(id
, fileName
, xCmdEnv
);
883 //Because the extension is only removed the next time the extension
884 //manager runs after restarting OOo, we need to indicate that a
885 //shared extension was "deleted". When a user starts OOo, then it
886 //will check if something changed in the shared repository. Based on
887 //the flag file it will then recognize, that the extension was
888 //deleted and can then update the extension database of the shared
889 //extensions in the user installation.
890 if ( xPackage
.is() && !m_readOnly
&& !xPackage
->isRemoved() && (m_context
== "shared"))
892 ActivePackages::Data val
;
893 m_activePackagesDB
->get( & val
, id
, fileName
);
894 OSL_ASSERT(!val
.temporaryName
.isEmpty());
895 OUString
url(makeURL(m_activePackages_expanded
,
896 val
.temporaryName
+ "removed"));
897 ::ucbhelper::Content
contentRemoved(url
, xCmdEnv
, m_xComponentContext
);
899 ::osl::Security aSecurity
;
900 aSecurity
.getUserName( aUserName
);
902 OString stamp
= OUStringToOString(aUserName
, RTL_TEXTENCODING_UTF8
);
903 Reference
<css::io::XInputStream
> xData(
904 ::xmlscript::createInputStream(
905 reinterpret_cast<sal_Int8
const *>(stamp
.getStr()),
906 stamp
.getLength() ) );
907 contentRemoved
.writeStream( xData
, true /* replace existing */ );
909 m_activePackagesDB
->erase( id
, fileName
); // to be removed upon next start
910 //remove any cached data hold by the backend
911 m_xRegistry
->packageRemoved(xPackage
->getURL(), xPackage
->getPackageType()->getMediaType());
913 try_dispose( xPackage
);
917 catch (const RuntimeException
&) {
920 catch (const CommandFailedException
& exc
) {
921 logIntern( Any(exc
) );
924 catch (const CommandAbortedException
& exc
) {
925 logIntern( Any(exc
) );
928 catch (const deployment::DeploymentException
& exc
) {
929 logIntern( Any(exc
) );
932 catch (const Exception
&) {
933 Any
exc( ::cppu::getCaughtException() );
935 throw deployment::DeploymentException(
936 DpResId(RID_STR_ERROR_WHILE_REMOVING
) + id
,
937 static_cast<OWeakObject
*>(this), exc
);
942 OUString
PackageManagerImpl::getDeployPath( ActivePackages::Data
const & data
)
944 OUStringBuffer
buf( data
.temporaryName
);
945 //The bundled extensions are not contained in an additional folder
946 //with a unique name. data.temporaryName contains already the
947 //UTF8 encoded folder name. See PackageManagerImpl::synchronize
948 if (m_context
!= "bundled")
951 + ::rtl::Uri::encode( data
.fileName
, rtl_UriCharClassPchar
,
952 rtl_UriEncodeIgnoreEscapes
,
953 RTL_TEXTENCODING_UTF8
) );
955 return makeURL( m_activePackages
, buf
.makeStringAndClear() );
959 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage_(
960 OUString
const & id
, OUString
const & fileName
,
961 Reference
<XCommandEnvironment
> const & xCmdEnv
)
963 ActivePackages::Data val
;
964 if (m_activePackagesDB
->get( &val
, id
, fileName
))
966 return getDeployedPackage_( id
, val
, xCmdEnv
);
968 throw lang::IllegalArgumentException(
969 DpResId(RID_STR_NO_SUCH_PACKAGE
) + id
,
970 static_cast<OWeakObject
*>(this), static_cast<sal_Int16
>(-1) );
974 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage_(
975 std::u16string_view id
, ActivePackages::Data
const & data
,
976 Reference
<XCommandEnvironment
> const & xCmdEnv
, bool ignoreAlienPlatforms
)
978 if (ignoreAlienPlatforms
)
980 OUString type
, subType
;
981 INetContentTypeParameterList params
;
982 if (INetContentTypes::parse( data
.mediaType
, type
, subType
, ¶ms
))
984 auto const iter
= params
.find(OString("platform"));
985 if (iter
!= params
.end() && !platform_fits(iter
->second
.m_sValue
))
986 throw lang::IllegalArgumentException(
987 DpResId(RID_STR_NO_SUCH_PACKAGE
) + id
,
988 static_cast<OWeakObject
*>(this),
989 static_cast<sal_Int16
>(-1) );
992 Reference
<deployment::XPackage
> xExtension
;
995 //Ignore extensions where XPackage::checkPrerequisites failed.
996 //They must not be usable for this user.
997 if (data
.failedPrerequisites
== "0")
999 xExtension
= m_xRegistry
->bindPackage(
1000 getDeployPath( data
), data
.mediaType
, false, OUString(), xCmdEnv
);
1003 catch (const deployment::InvalidRemovedParameterException
& e
)
1005 xExtension
= e
.Extension
;
1011 Sequence
< Reference
<deployment::XPackage
> >
1012 PackageManagerImpl::getDeployedPackages_(
1013 Reference
<XCommandEnvironment
> const & xCmdEnv
)
1015 std::vector
< Reference
<deployment::XPackage
> > packages
;
1016 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1017 for (auto const& elem
: id2temp
)
1019 if (elem
.second
.failedPrerequisites
!= "0")
1023 getDeployedPackage_(
1024 elem
.first
, elem
.second
, xCmdEnv
,
1025 true /* xxx todo: think of GUI:
1026 ignore other platforms than the current one */ ) );
1028 catch (const lang::IllegalArgumentException
&) {
1030 TOOLS_WARN_EXCEPTION( "desktop", "" );
1032 catch (const deployment::DeploymentException
&) {
1034 TOOLS_WARN_EXCEPTION( "desktop", "" );
1037 return comphelper::containerToSequence(packages
);
1041 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage(
1042 OUString
const & id
, OUString
const & fileName
,
1043 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1046 Reference
<XCommandEnvironment
> xCmdEnv
;
1047 if (m_xLogFile
.is())
1048 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1050 xCmdEnv
.set( xCmdEnv_
);
1053 const ::osl::MutexGuard
guard( m_aMutex
);
1054 return getDeployedPackage_( id
, fileName
, xCmdEnv
);
1056 catch (const RuntimeException
&) {
1059 catch (const CommandFailedException
& exc
) {
1060 logIntern( Any(exc
) );
1063 catch (const deployment::DeploymentException
& exc
) {
1064 logIntern( Any(exc
) );
1067 catch (const Exception
&) {
1068 Any
exc( ::cppu::getCaughtException() );
1070 throw deployment::DeploymentException(
1071 // ought never occur...
1072 "error while accessing deployed package: " + id
,
1073 static_cast<OWeakObject
*>(this), exc
);
1078 Sequence
< Reference
<deployment::XPackage
> >
1079 PackageManagerImpl::getDeployedPackages(
1080 Reference
<task::XAbortChannel
> const &,
1081 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1084 Reference
<XCommandEnvironment
> xCmdEnv
;
1085 if (m_xLogFile
.is())
1086 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1088 xCmdEnv
.set( xCmdEnv_
);
1091 const ::osl::MutexGuard
guard( m_aMutex
);
1092 return getDeployedPackages_( xCmdEnv
);
1094 catch (const RuntimeException
&) {
1097 catch (const CommandFailedException
& exc
) {
1098 logIntern( Any(exc
) );
1101 catch (const CommandAbortedException
& exc
) {
1102 logIntern( Any(exc
) );
1105 catch (const deployment::DeploymentException
& exc
) {
1106 logIntern( Any(exc
) );
1109 catch (const Exception
&) {
1110 Any
exc( ::cppu::getCaughtException() );
1112 throw deployment::DeploymentException(
1113 // ought never occur...
1114 "error while getting all deployed packages: " + m_context
,
1115 static_cast<OWeakObject
*>(this), exc
);
1120 //ToDo: the function must not call registerPackage, do this in
1121 //XExtensionManager.reinstallDeployedExtensions
1122 void PackageManagerImpl::reinstallDeployedPackages(
1123 sal_Bool force
, Reference
<task::XAbortChannel
> const & /*xAbortChannel*/,
1124 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1127 if (!force
&& office_is_running())
1128 throw RuntimeException(
1129 "You must close any running Office process before reinstalling packages!",
1130 static_cast<OWeakObject
*>(this) );
1132 Reference
<XCommandEnvironment
> xCmdEnv
;
1133 if (m_xLogFile
.is())
1134 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1136 xCmdEnv
.set( xCmdEnv_
);
1139 ProgressLevel
progress(
1140 xCmdEnv
, "Reinstalling all deployed packages..." );
1142 try_dispose( m_xRegistry
);
1143 m_xRegistry
.clear();
1144 if (!m_registryCache
.isEmpty())
1145 erase_path( m_registryCache
, xCmdEnv
);
1146 initRegistryBackends();
1147 Reference
<util::XUpdatable
> xUpdatable( m_xRegistry
, UNO_QUERY
);
1148 if (xUpdatable
.is())
1149 xUpdatable
->update();
1151 //registering is done by the ExtensionManager service.
1153 catch (const RuntimeException
&) {
1156 catch (const CommandFailedException
& exc
) {
1157 logIntern( Any(exc
) );
1160 catch (const CommandAbortedException
& exc
) {
1161 logIntern( Any(exc
) );
1164 catch (const deployment::DeploymentException
& exc
) {
1165 logIntern( Any(exc
) );
1168 catch (const Exception
&) {
1169 Any
exc( ::cppu::getCaughtException() );
1171 throw deployment::DeploymentException(
1172 "Error while reinstalling all previously deployed packages of context " + m_context
,
1173 static_cast<OWeakObject
*>(this), exc
);
1178 sal_Bool SAL_CALL
PackageManagerImpl::isReadOnly( )
1182 bool PackageManagerImpl::synchronizeRemovedExtensions(
1183 Reference
<task::XAbortChannel
> const & xAbortChannel
,
1184 Reference
<css::ucb::XCommandEnvironment
> const & xCmdEnv
)
1187 //find all which are in the extension data base but which
1188 //are removed already.
1189 OSL_ASSERT(!(m_context
== "user"));
1190 bool bModified
= false;
1191 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1193 bool bShared
= (m_context
== "shared");
1195 for (auto const& elem
: id2temp
)
1199 //Get the URL to the extensions folder, first make the url for the
1200 //shared repository including the temporary name
1201 OUString url
= makeURL(m_activePackages
, elem
.second
.temporaryName
);
1203 url
= makeURLAppendSysPathSegment( Concat2View(url
+ "_"), elem
.second
.fileName
);
1205 bool bRemoved
= false;
1206 //Check if the URL to the extension is still the same
1207 ::ucbhelper::Content contentExtension
;
1209 if (!create_ucb_content(
1210 &contentExtension
, url
,
1211 Reference
<XCommandEnvironment
>(), false))
1216 //The folder is in the extension database, but it can still be deleted.
1217 //look for the xxx.tmpremoved file
1218 //There can also be the case that a different extension was installed
1219 //in a "temp" folder with name that is already used.
1220 if (!bRemoved
&& bShared
)
1222 ::ucbhelper::Content contentRemoved
;
1224 if (create_ucb_content(
1226 m_activePackages_expanded
+ "/" +
1227 elem
.second
.temporaryName
+ "removed",
1228 Reference
<XCommandEnvironment
>(), false))
1236 //There may be another extensions at the same place
1237 dp_misc::DescriptionInfoset infoset
=
1238 dp_misc::getDescriptionInfoset(url
);
1239 OSL_ENSURE(infoset
.hasDescription() && infoset
.getIdentifier(),
1240 "Extension Manager: bundled and shared extensions "
1241 "must have an identifier and a version");
1242 if (infoset
.hasDescription() &&
1243 infoset
.getIdentifier() &&
1244 ( elem
.first
!= *(infoset
.getIdentifier())
1245 || elem
.second
.version
!= infoset
.getVersion()))
1253 Reference
<deployment::XPackage
> xPackage
= m_xRegistry
->bindPackage(
1254 url
, elem
.second
.mediaType
, true, elem
.first
, xCmdEnv
);
1255 OSL_ASSERT(xPackage
.is()); //Even if the files are removed, we must get the object.
1256 xPackage
->revokePackage(true, xAbortChannel
, xCmdEnv
);
1257 removePackage(xPackage
->getIdentifier().Value
, xPackage
->getName(),
1258 xAbortChannel
, xCmdEnv
);
1262 catch( const uno::Exception
& )
1264 TOOLS_WARN_EXCEPTION("desktop.deployment", "");
1271 bool PackageManagerImpl::synchronizeAddedExtensions(
1272 Reference
<task::XAbortChannel
> const & xAbortChannel
,
1273 Reference
<css::ucb::XCommandEnvironment
> const & xCmdEnv
)
1275 bool bModified
= false;
1276 OSL_ASSERT(!(m_context
== "user"));
1278 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1279 //check if the folder exist at all. The shared extension folder
1280 //may not exist for a normal user.
1284 bOk
= create_ucb_content(
1285 nullptr, m_activePackages_expanded
, Reference
<css::ucb::XCommandEnvironment
>(), false);
1287 catch (const css::ucb::ContentCreationException
&)
1295 ::ucbhelper::Content
tempFolder( m_activePackages_expanded
, xCmdEnv
, m_xComponentContext
);
1296 Reference
<sdbc::XResultSet
> xResultSet(
1297 StrTitle::createCursor( tempFolder
,
1298 ::ucbhelper::INCLUDE_FOLDERS_ONLY
) );
1300 while (xResultSet
->next())
1305 Reference
<sdbc::XRow
>(
1306 xResultSet
, UNO_QUERY_THROW
)->getString(
1308 //The temporary folders of user and shared have an '_' at then end.
1309 //But the name in ActivePackages.temporaryName is saved without.
1310 OUString title2
= title
;
1311 bool bShared
= (m_context
== "shared");
1314 OSL_ASSERT(title2
.endsWith("_"));
1315 title2
= title2
.copy(0, title2
.getLength() -1);
1317 OUString titleEncoded
= ::rtl::Uri::encode(
1318 title2
, rtl_UriCharClassPchar
,
1319 rtl_UriEncodeIgnoreEscapes
,
1320 RTL_TEXTENCODING_UTF8
);
1322 //It is sufficient to check for the folder name, because when the administrator
1323 //installed the extension it was already checked if there is one with the
1325 const MatchTempDir
match(titleEncoded
);
1326 if (std::none_of( id2temp
.begin(), id2temp
.end(), match
))
1329 // The folder was not found in the data base, so it must be
1330 // an added extension
1331 OUString
url(m_activePackages_expanded
+ "/" + titleEncoded
);
1332 OUString sExtFolder
;
1333 if (bShared
) //that is, shared
1335 //Check if the extension was not "deleted" already which is indicated
1336 //by a xxx.tmpremoved file
1337 ::ucbhelper::Content contentRemoved
;
1338 if (create_ucb_content(&contentRemoved
, url
+ "removed",
1339 Reference
<XCommandEnvironment
>(), false))
1341 sExtFolder
= getExtensionFolder(
1342 m_activePackages_expanded
+ "/" + titleEncoded
+ "_",
1343 xCmdEnv
, m_xComponentContext
);
1344 url
= makeURLAppendSysPathSegment(m_activePackages_expanded
, title
);
1345 url
= makeURLAppendSysPathSegment(url
, sExtFolder
);
1347 Reference
<deployment::XPackage
> xPackage
= m_xRegistry
->bindPackage(
1348 url
, OUString(), false, OUString(), xCmdEnv
);
1351 OUString id
= dp_misc::getIdentifier( xPackage
);
1353 //Prepare the database entry
1354 ActivePackages::Data dbData
;
1356 dbData
.temporaryName
= titleEncoded
;
1358 dbData
.fileName
= sExtFolder
;
1360 dbData
.fileName
= title
;
1361 dbData
.mediaType
= xPackage
->getPackageType()->getMediaType();
1362 dbData
.version
= xPackage
->getVersion();
1364 dbData
.version
.isEmpty(), "desktop.deployment",
1365 "bundled/shared extension " << id
<< " at <" << url
1366 << "> has no explicit version");
1368 //We provide a special command environment that will prevent
1369 //showing a license if simple-license/@accept-by = "admin"
1370 //It will also prevent showing the license for bundled extensions
1371 //which is not supported.
1372 OSL_ASSERT(!(m_context
== "user"));
1374 // shall the license be suppressed?
1375 DescriptionInfoset info
=
1376 dp_misc::getDescriptionInfoset(url
);
1377 ::std::optional
<dp_misc::SimpleLicenseAttributes
>
1378 attr
= info
.getSimpleLicenseAttributes();
1379 ExtensionProperties
props(url
, xCmdEnv
, m_xComponentContext
);
1380 bool bNoLicense
= false;
1381 if (attr
&& attr
->suppressIfRequired
&& props
.isSuppressedLicense())
1384 Reference
<ucb::XCommandEnvironment
> licCmdEnv(
1385 new LicenseCommandEnv(xCmdEnv
->getInteractionHandler(),
1386 bNoLicense
, m_context
));
1387 sal_Int32 failedPrereq
= xPackage
->checkPrerequisites(
1388 xAbortChannel
, licCmdEnv
, false);
1389 //Remember that this failed. For example, the user
1390 //could have declined the license. Then the next time the
1391 //extension folder is investigated we do not want to
1392 //try to install the extension again.
1393 dbData
.failedPrerequisites
= OUString::number(failedPrereq
);
1394 insertToActivationLayerDB(id
, dbData
);
1399 catch (const uno::Exception
&)
1401 // Looks like exceptions being caught here is not an uncommon case.
1402 TOOLS_WARN_EXCEPTION("desktop.deployment", "");
1408 sal_Bool
PackageManagerImpl::synchronize(
1409 Reference
<task::XAbortChannel
> const & xAbortChannel
,
1410 Reference
<css::ucb::XCommandEnvironment
> const & xCmdEnv
)
1413 bool bModified
= false;
1414 if (m_context
== "user")
1417 synchronizeRemovedExtensions(xAbortChannel
, xCmdEnv
);
1418 bModified
|= synchronizeAddedExtensions(xAbortChannel
, xCmdEnv
);
1423 Sequence
< Reference
<deployment::XPackage
> > PackageManagerImpl::getExtensionsWithUnacceptedLicenses(
1424 Reference
<ucb::XCommandEnvironment
> const & xCmdEnv
)
1426 std::vector
<Reference
<deployment::XPackage
> > vec
;
1430 const ::osl::MutexGuard
guard( m_aMutex
);
1431 // clean up activation layer, scan for zombie temp dirs:
1432 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1434 bool bShared
= (m_context
== "shared");
1436 for (auto const& elem
: id2temp
)
1438 //Get the database entry
1439 ActivePackages::Data
const & dbData
= elem
.second
;
1440 sal_Int32 failedPrereq
= dbData
.failedPrerequisites
.toInt32();
1441 //If the installation failed for other reason then the license then we
1443 if (failedPrereq
^ deployment::Prerequisites::LICENSE
)
1446 //Prepare the URL to the extension
1447 OUString url
= makeURL(m_activePackages
, elem
.second
.temporaryName
);
1449 url
= makeURLAppendSysPathSegment( Concat2View(url
+ "_"), elem
.second
.fileName
);
1451 Reference
<deployment::XPackage
> p
= m_xRegistry
->bindPackage(
1452 url
, OUString(), false, OUString(), xCmdEnv
);
1458 return ::comphelper::containerToSequence(vec
);
1460 catch (const deployment::DeploymentException
&)
1464 catch (const RuntimeException
&)
1470 Any exc
= ::cppu::getCaughtException();
1471 deployment::DeploymentException
de(
1472 "PackageManagerImpl::getExtensionsWithUnacceptedLicenses",
1473 static_cast<OWeakObject
*>(this), exc
);
1475 ::cppu::throwException(exc
);
1478 return ::comphelper::containerToSequence(vec
);
1481 sal_Int32
PackageManagerImpl::checkPrerequisites(
1482 css::uno::Reference
<css::deployment::XPackage
> const & extension
,
1483 css::uno::Reference
<css::task::XAbortChannel
> const & xAbortChannel
,
1484 css::uno::Reference
<css::ucb::XCommandEnvironment
> const & xCmdEnv
)
1488 if (!extension
.is())
1490 if (m_context
!= extension
->getRepositoryName())
1491 throw lang::IllegalArgumentException(
1492 "PackageManagerImpl::checkPrerequisites: extension is not from this repository.",
1495 ActivePackages::Data dbData
;
1496 OUString id
= dp_misc::getIdentifier(extension
);
1497 if (!m_activePackagesDB
->get( &dbData
, id
, OUString()))
1499 throw lang::IllegalArgumentException(
1500 "PackageManagerImpl::checkPrerequisites: unknown extension",
1504 //If the license was already displayed, then do not show it again
1505 Reference
<ucb::XCommandEnvironment
> _xCmdEnv
= xCmdEnv
;
1506 sal_Int32 prereq
= dbData
.failedPrerequisites
.toInt32();
1507 if ( !(prereq
& deployment::Prerequisites::LICENSE
))
1508 _xCmdEnv
= new NoLicenseCommandEnv(xCmdEnv
->getInteractionHandler());
1510 sal_Int32 failedPrereq
= extension
->checkPrerequisites(
1511 xAbortChannel
, _xCmdEnv
, false);
1512 dbData
.failedPrerequisites
= OUString::number(failedPrereq
);
1513 insertToActivationLayerDB(id
, dbData
);
1516 catch ( const deployment::DeploymentException
& ) {
1518 } catch ( const ucb::CommandFailedException
& ) {
1520 } catch ( const ucb::CommandAbortedException
& ) {
1522 } catch (const lang::IllegalArgumentException
&) {
1524 } catch (const uno::RuntimeException
&) {
1527 uno::Any excOccurred
= ::cppu::getCaughtException();
1528 deployment::DeploymentException
exc(
1529 "PackageManagerImpl::checkPrerequisites: exception ",
1530 static_cast<OWeakObject
*>(this), excOccurred
);
1536 PackageManagerImpl::CmdEnvWrapperImpl::~CmdEnvWrapperImpl()
1541 PackageManagerImpl::CmdEnvWrapperImpl::CmdEnvWrapperImpl(
1542 Reference
<XCommandEnvironment
> const & xUserCmdEnv
,
1543 Reference
<XProgressHandler
> const & xLogFile
)
1544 : m_xLogFile( xLogFile
)
1546 if (xUserCmdEnv
.is()) {
1547 m_xUserProgress
.set( xUserCmdEnv
->getProgressHandler() );
1548 m_xUserInteractionHandler
.set( xUserCmdEnv
->getInteractionHandler() );
1552 // XCommandEnvironment
1554 Reference
<task::XInteractionHandler
>
1555 PackageManagerImpl::CmdEnvWrapperImpl::getInteractionHandler()
1557 return m_xUserInteractionHandler
;
1561 Reference
<XProgressHandler
>
1562 PackageManagerImpl::CmdEnvWrapperImpl::getProgressHandler()
1569 void PackageManagerImpl::CmdEnvWrapperImpl::push( Any
const & Status
)
1571 if (m_xLogFile
.is())
1572 m_xLogFile
->push( Status
);
1573 if (m_xUserProgress
.is())
1574 m_xUserProgress
->push( Status
);
1578 void PackageManagerImpl::CmdEnvWrapperImpl::update( Any
const & Status
)
1580 if (m_xLogFile
.is())
1581 m_xLogFile
->update( Status
);
1582 if (m_xUserProgress
.is())
1583 m_xUserProgress
->update( Status
);
1587 void PackageManagerImpl::CmdEnvWrapperImpl::pop()
1589 if (m_xLogFile
.is())
1591 if (m_xUserProgress
.is())
1592 m_xUserProgress
->pop();
1595 } // namespace dp_manager
1597 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */