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 .
22 #include "dp_resource.h"
23 #include "dp_platform.hxx"
24 #include "dp_manager.h"
25 #include "dp_identifier.hxx"
26 #include "rtl/ustrbuf.hxx"
27 #include "rtl/string.hxx"
28 #include "rtl/uri.hxx"
29 #include "rtl/bootstrap.hxx"
30 #include "osl/diagnose.h"
31 #include "osl/file.hxx"
32 #include "osl/security.hxx"
33 #include "cppuhelper/weakref.hxx"
34 #include "cppuhelper/exc_hlp.hxx"
35 #include "cppuhelper/implbase1.hxx"
36 #include "cppuhelper/interfacecontainer.hxx"
37 #include "comphelper/servicedecl.hxx"
38 #include "comphelper/sequence.hxx"
39 #include "xmlscript/xml_helper.hxx"
40 #include "svl/inettype.hxx"
41 #include "com/sun/star/lang/DisposedException.hpp"
42 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
43 #include "com/sun/star/beans/UnknownPropertyException.hpp"
44 #include "com/sun/star/util/XUpdatable.hpp"
45 #include "com/sun/star/sdbc/XResultSet.hpp"
46 #include "com/sun/star/sdbc/XRow.hpp"
47 #include "com/sun/star/ucb/XContentAccess.hpp"
48 #include "com/sun/star/ucb/NameClash.hpp"
49 #include "com/sun/star/deployment/VersionException.hpp"
50 #include "com/sun/star/deployment/InstallException.hpp"
51 #include "com/sun/star/deployment/Prerequisites.hpp"
52 #include "com/sun/star/task/XInteractionApprove.hpp"
53 #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
54 #include "boost/bind.hpp"
55 #include "unotools/tempfile.hxx"
59 #include "dp_descriptioninfoset.hxx"
60 #include "dp_commandenvironments.hxx"
61 #include "dp_properties.hxx"
63 using namespace ::dp_misc
;
64 using namespace ::com::sun::star
;
65 using namespace ::com::sun::star::uno
;
66 using namespace ::com::sun::star::ucb
;
69 extern comphelper::service_decl::ServiceDecl
const serviceDecl
;
72 namespace dp_registry
{
73 Reference
<deployment::XPackageRegistry
> create(
74 OUString
const & context
,
75 OUString
const & cachePath
, bool readOnly
,
76 Reference
<XComponentContext
> const & xComponentContext
);
79 namespace dp_manager
{
84 MatchTempDir( OUString
const & str
) : m_str( str
) {}
85 bool operator () ( ActivePackages::Entries::value_type
const & v
) const {
86 return v
.second
.temporaryName
.equalsIgnoreAsciiCase( m_str
);
92 OUString
getExtensionFolder(OUString
const & parentFolder
,
93 Reference
<ucb::XCommandEnvironment
> const & xCmdEnv
,
94 Reference
<uno::XComponentContext
> const & xContext
)
96 ::ucbhelper::Content
tempFolder( parentFolder
, xCmdEnv
, xContext
);
97 Reference
<sdbc::XResultSet
> xResultSet(
98 StrTitle::createCursor (tempFolder
, ::ucbhelper::INCLUDE_FOLDERS_ONLY
) );
101 while (xResultSet
->next())
103 title
= Reference
<sdbc::XRow
>(
104 xResultSet
, UNO_QUERY_THROW
)->getString(1 /* Title */ ) ;
110 //______________________________________________________________________________
111 void PackageManagerImpl::initActivationLayer(
112 Reference
<XCommandEnvironment
> const & xCmdEnv
)
114 if (m_activePackages
.isEmpty())
116 OSL_ASSERT( m_registryCache
.isEmpty() );
117 // documents temp activation:
118 m_activePackagesDB
.reset( new ActivePackages
);
119 ::ucbhelper::Content ucbContent
;
120 if (create_ucb_content( &ucbContent
, m_context
, xCmdEnv
,
121 false /* no throw */ ))
123 // scan for all entries in m_packagesDir:
124 Reference
<sdbc::XResultSet
> xResultSet(
125 StrTitle::createCursor (ucbContent
, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS
) );
127 while (xResultSet
->next())
129 Reference
<sdbc::XRow
> xRow( xResultSet
, UNO_QUERY_THROW
);
130 OUString
title( xRow
->getString( 1 /* Title */ ) );
131 // xxx todo: remove workaround for tdoc
132 if ( title
== "this_is_a_dummy_stream_just_there_as_a_workaround_for_a_temporary_limitation_of_the_storage_api_implementation" )
134 if ( title
== "META-INF" )
137 ::ucbhelper::Content
sourceContent(
138 Reference
<XContentAccess
>(
139 xResultSet
, UNO_QUERY_THROW
)->queryContent(),
140 xCmdEnv
, m_xComponentContext
);
142 OUString
mediaType( detectMediaType( sourceContent
,
143 false /* no throw */) );
144 if (!mediaType
.isEmpty())
146 ActivePackages::Data dbData
;
147 insertToActivationLayer(
148 Sequence
<css::beans::NamedValue
>(),mediaType
, sourceContent
,
151 insertToActivationLayerDB( title
, dbData
);
152 //TODO #i73136#: insertToActivationLayerDB needs id not
153 // title, but the whole m_activePackages.getLength()==0
154 // case (i.e., document-relative deployment) currently
155 // does not work, anyway.
163 OSL_ASSERT( !m_activePackages
.isEmpty() );
164 m_activePackages_expanded
= expandUnoRcUrl( m_activePackages
);
165 m_registrationData_expanded
= expandUnoRcUrl(m_registrationData
);
167 create_folder( 0, m_activePackages_expanded
, xCmdEnv
, true);
170 if (m_context
== "user")
171 dbName
= m_activePackages_expanded
+ ".pmap";
174 // Create the extension data base in the user installation
175 create_folder( 0, m_registrationData_expanded
, xCmdEnv
, true);
176 dbName
= m_registrationData_expanded
+ "/extensions.pmap";
178 // The data base can always be written because it it always in the user installation
179 m_activePackagesDB
.reset( new ActivePackages( dbName
, false ) );
181 if (! m_readOnly
&& ! (m_context
== "bundled"))
183 // clean up activation layer, scan for zombie temp dirs:
184 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
186 ::ucbhelper::Content
tempFolder( m_activePackages_expanded
, xCmdEnv
, m_xComponentContext
);
187 Reference
<sdbc::XResultSet
> xResultSet(
188 StrTitle::createCursor (tempFolder
,
189 ::ucbhelper::INCLUDE_DOCUMENTS_ONLY
) );
191 // get all temp directories:
192 ::std::vector
<OUString
> tempEntries
;
193 ::std::vector
<OUString
> removedEntries
;
194 while (xResultSet
->next())
197 Reference
<sdbc::XRow
>(
198 xResultSet
, UNO_QUERY_THROW
)->getString(
201 const char extensionRemoved
[] = "removed";
202 if (title
.endsWith( extensionRemoved
))
204 //save the file name withouth the "removed" part
205 sal_Int32 index
= title
.lastIndexOfAsciiL(
206 extensionRemoved
, sizeof(extensionRemoved
) - 1);
207 OUString remFile
= title
.copy(0, index
);
208 removedEntries
.push_back(::rtl::Uri::encode(
209 remFile
, rtl_UriCharClassPchar
,
210 rtl_UriEncodeIgnoreEscapes
,
211 RTL_TEXTENCODING_UTF8
) );
215 tempEntries
.push_back( ::rtl::Uri::encode(
216 title
, rtl_UriCharClassPchar
,
217 rtl_UriEncodeIgnoreEscapes
,
218 RTL_TEXTENCODING_UTF8
) );
222 bool bShared
= (m_context
== "shared") ? true : false;
223 for ( ::std::size_t pos
= 0; pos
< tempEntries
.size(); ++pos
)
225 OUString
const & tempEntry
= tempEntries
[ pos
];
226 const MatchTempDir
match( tempEntry
);
227 if (::std::find_if( id2temp
.begin(), id2temp
.end(), match
) ==
231 makeURL(m_activePackages_expanded
, tempEntry
) );
233 //In case of shared extensions, new entries are regarded as
234 //added extensions if there is no xxx.tmpremoved file.
237 if (::std::find(removedEntries
.begin(), removedEntries
.end(), tempEntry
) ==
238 removedEntries
.end())
244 //Make sure only the same user removes the extension, who
245 //previously unregistered it. This is avoid races if multiple instances
246 //of OOo are running which all have write access to the shared installation.
247 //For example, a user removes the extension, but keeps OOo
248 //running. Parts of the extension may still be loaded and used by OOo.
249 //Therefore the extension is only deleted the next time the extension manager is
250 //run after restarting OOo. While OOo is still running, another user starts OOo
251 //which would deleted the extension files. If the same user starts another
252 //instance of OOo then the lock file will prevent this.
254 ::osl::Security aSecurity
;
255 aSecurity
.getUserName( aUserName
);
256 ucbhelper::Content
remFileContent(
257 url
+ "removed", Reference
<XCommandEnvironment
>(), m_xComponentContext
);
258 ::rtl::ByteSequence data
= dp_misc::readFile(remFileContent
);
259 OString
osData(reinterpret_cast<const sal_Char
*>(data
.getConstArray()),
261 OUString sData
= OStringToOUString(
262 osData
, RTL_TEXTENCODING_UTF8
);
263 if (!sData
.equals(aUserName
))
267 // temp entry not needed anymore:
268 erase_path( url
+ "_",
269 Reference
<XCommandEnvironment
>(),
270 false /* no throw: ignore errors */ );
271 erase_path( url
, Reference
<XCommandEnvironment
>(),
272 false /* no throw: ignore errors */ );
273 //delete the xxx.tmpremoved file
274 erase_path(url
+ "removed",
275 Reference
<XCommandEnvironment
>(), false);
282 //______________________________________________________________________________
283 void PackageManagerImpl::initRegistryBackends()
285 if (!m_registryCache
.isEmpty())
286 create_folder( 0, m_registryCache
,
287 Reference
<XCommandEnvironment
>(), false);
288 m_xRegistry
.set( ::dp_registry::create(
289 m_context
, m_registryCache
, false,
290 m_xComponentContext
) );
293 // this overcomes previous rumours that the sal API is misleading
294 // as to whether a directory is truly read-only or not
295 static bool isMacroURLReadOnly( const OUString
&rMacro
)
297 OUString
aDirURL( rMacro
);
298 ::rtl::Bootstrap::expandMacros( aDirURL
);
300 ::osl::FileBase::RC aErr
= ::osl::Directory::create( aDirURL
);
301 if ( aErr
== ::osl::FileBase::E_None
)
302 return false; // it will be writeable
303 if ( aErr
!= ::osl::FileBase::E_EXIST
)
304 return true; // some serious problem creating it
307 sal_uInt64 nWritten
= 0;
308 OUString
aFileURL( aDirURL
+ "/stamp.sys" );
309 ::osl::File
aFile( aFileURL
);
311 bError
= aFile
.open( osl_File_OpenFlag_Read
|
312 osl_File_OpenFlag_Write
|
313 osl_File_OpenFlag_Create
) != ::osl::FileBase::E_None
;
315 bError
= aFile
.write( "1", 1, nWritten
) != ::osl::FileBase::E_None
;
316 if (aFile
.close() != ::osl::FileBase::E_None
)
318 if (osl::File::remove( aFileURL
) != ::osl::FileBase::E_None
)
322 "desktop.deployment",
323 "local url '" << rMacro
<< "' -> '" << aFileURL
<< "' "
324 << (bError
? "is" : "is not") << " readonly\n");
328 //______________________________________________________________________________
329 Reference
<deployment::XPackageManager
> PackageManagerImpl::create(
330 Reference
<XComponentContext
> const & xComponentContext
,
331 OUString
const & context
)
333 PackageManagerImpl
* that
= new PackageManagerImpl(
334 xComponentContext
, context
);
335 Reference
<deployment::XPackageManager
> xPackageManager( that
);
337 OUString logFile
, stamp
;
338 if ( context
== "user" ) {
339 that
->m_activePackages
= "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages";
340 that
->m_registrationData
= "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE";
341 that
->m_registryCache
= "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/registry";
342 logFile
= "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/log.txt";
343 //We use the extension .sys for the file because on Windows Vista a sys
344 //(as well as exe and dll) file
345 //will not be written in the VirtualStore. For example if the process has no
346 //admin right once cannot write to the %programfiles% folder. However, when
347 //virtualization is used, the file will be written into the VirtualStore and
348 //it appears as if one could write to %programfiles%. When we test for write
349 //access to the office/shared folder for shared extensions then this typically
350 //fails because a normal user typically cannot write to this folder. However,
351 //using virtualization it appears that he/she can. Then a shared extension can
352 //be installed but is only visible for the user (because the extension is in
353 //the virtual store).
354 stamp
= "$UNO_USER_PACKAGES_CACHE";
356 else if ( context
== "shared" ) {
357 that
->m_activePackages
= "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages";
358 that
->m_registrationData
= "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER";
359 that
->m_registryCache
= "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/registry";
360 logFile
= "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/log.txt";
361 stamp
= "$UNO_SHARED_PACKAGES_CACHE";
363 else if ( context
== "bundled" ) {
364 that
->m_activePackages
= "vnd.sun.star.expand:$BUNDLED_EXTENSIONS";
365 that
->m_registrationData
= "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER";
366 that
->m_registryCache
= "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/registry";
367 logFile
= "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/log.txt";
368 //No stamp file. We assume that bundled is always readonly. It must not be
369 //modified from ExtensionManager but only by the installer
371 else if ( context
== "tmp" ) {
372 that
->m_activePackages
= "vnd.sun.star.expand:$TMP_EXTENSIONS/extensions";
373 that
->m_registrationData
= "vnd.sun.star.expand:$TMP_EXTENSIONS";
374 that
->m_registryCache
= "vnd.sun.star.expand:$TMP_EXTENSIONS/registry";
375 stamp
= "$TMP_EXTENSIONS";
377 else if (context
== "bak") {
378 that
->m_activePackages
= "vnd.sun.star.expand:$BAK_EXTENSIONS/extensions";
379 that
->m_registrationData
= "vnd.sun.star.expand:$BAK_EXTENSIONS";
380 that
->m_registryCache
= "vnd.sun.star.expand:$BAK_EXTENSIONS/registry";
381 stamp
= "$BAK_EXTENSIONS";
384 else if (! context
.match("vnd.sun.star.tdoc:/")) {
385 throw lang::IllegalArgumentException(
386 "invalid context given: " + context
,
387 Reference
<XInterface
>(), static_cast<sal_Int16
>(-1) );
390 Reference
<XCommandEnvironment
> xCmdEnv
;
393 // There is no stamp for the bundled folder:
394 if (!stamp
.isEmpty())
395 that
->m_readOnly
= isMacroURLReadOnly( stamp
);
397 if (!that
->m_readOnly
&& !logFile
.isEmpty())
399 const Any
any_logFile(logFile
);
400 that
->m_xLogFile
.set(
401 that
->m_xComponentContext
->getServiceManager()
402 ->createInstanceWithArgumentsAndContext(
403 dp_log::serviceDecl
.getSupportedServiceNames()[0],
404 Sequence
<Any
>( &any_logFile
, 1 ),
405 that
->m_xComponentContext
),
407 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv
, that
->m_xLogFile
) );
410 that
->initRegistryBackends();
411 that
->initActivationLayer( xCmdEnv
);
413 return xPackageManager
;
416 catch (const RuntimeException
&) {
419 catch (const Exception
& e
) {
420 Any
exc( ::cppu::getCaughtException() );
421 throw lang::WrappedTargetRuntimeException(
422 ("[context=\"" + context
+ "\"] caught unexpected "
423 + exc
.getValueType().getTypeName() + ": " + e
.Message
),
424 Reference
<XInterface
>(), exc
);
428 //______________________________________________________________________________
429 PackageManagerImpl::~PackageManagerImpl()
433 //______________________________________________________________________________
434 void PackageManagerImpl::fireModified()
436 ::cppu::OInterfaceContainerHelper
* pContainer
= rBHelper
.getContainer(
437 util::XModifyListener::static_type() );
438 if (pContainer
!= 0) {
439 pContainer
->forEach
<util::XModifyListener
>(
440 boost::bind(&util::XModifyListener::modified
, _1
,
441 lang::EventObject(static_cast<OWeakObject
*>(this))) );
445 //______________________________________________________________________________
446 void PackageManagerImpl::disposing()
449 // // xxx todo: guarding?
450 // ::osl::MutexGuard guard( getMutex() );
451 try_dispose( m_xLogFile
);
453 try_dispose( m_xRegistry
);
455 m_activePackagesDB
.reset(0);
456 m_xComponentContext
.clear();
458 t_pm_helper::disposing();
461 catch (const RuntimeException
&) {
464 catch (const Exception
&) {
465 Any
exc( ::cppu::getCaughtException() );
466 throw lang::WrappedTargetRuntimeException(
467 "caught unexpected exception while disposing...",
468 static_cast<OWeakObject
*>(this), exc
);
473 //______________________________________________________________________________
474 void PackageManagerImpl::dispose() throw (RuntimeException
)
476 //Do not call check here. We must not throw an exception here if the object
477 //is being disposed or is already disposed. See com.sun.star.lang.XComponent
478 WeakComponentImplHelperBase::dispose();
481 //______________________________________________________________________________
482 void PackageManagerImpl::addEventListener(
483 Reference
<lang::XEventListener
> const & xListener
) throw (RuntimeException
)
485 //Do not call check here. We must not throw an exception here if the object
486 //is being disposed or is already disposed. See com.sun.star.lang.XComponent
487 WeakComponentImplHelperBase::addEventListener( xListener
);
490 //______________________________________________________________________________
491 void PackageManagerImpl::removeEventListener(
492 Reference
<lang::XEventListener
> const & xListener
) throw (RuntimeException
)
494 //Do not call check here. We must not throw an exception here if the object
495 //is being disposed or is already disposed. See com.sun.star.lang.XComponent
496 WeakComponentImplHelperBase::removeEventListener( xListener
);
500 //______________________________________________________________________________
501 OUString
PackageManagerImpl::getContext() throw (RuntimeException
)
507 //______________________________________________________________________________
508 Sequence
< Reference
<deployment::XPackageTypeInfo
> >
509 PackageManagerImpl::getSupportedPackageTypes() throw (RuntimeException
)
511 OSL_ASSERT( m_xRegistry
.is() );
512 return m_xRegistry
->getSupportedPackageTypes();
515 //______________________________________________________________________________
516 Reference
<task::XAbortChannel
> PackageManagerImpl::createAbortChannel()
517 throw (RuntimeException
)
520 return new AbortChannel
;
523 // XModifyBroadcaster
524 //______________________________________________________________________________
525 void PackageManagerImpl::addModifyListener(
526 Reference
<util::XModifyListener
> const & xListener
)
527 throw (RuntimeException
)
530 rBHelper
.addListener( ::getCppuType( &xListener
), xListener
);
533 //______________________________________________________________________________
534 void PackageManagerImpl::removeModifyListener(
535 Reference
<util::XModifyListener
> const & xListener
)
536 throw (RuntimeException
)
539 rBHelper
.removeListener( ::getCppuType( &xListener
), xListener
);
542 //______________________________________________________________________________
543 OUString
PackageManagerImpl::detectMediaType(
544 ::ucbhelper::Content
const & ucbContent_
, bool throw_exc
)
546 ::ucbhelper::Content
ucbContent(ucbContent_
);
547 OUString
url( ucbContent
.getURL() );
549 if (url
.match( "vnd.sun.star.tdoc:" ) || url
.match( "vnd.sun.star.pkg:" ))
552 ucbContent
.getPropertyValue( "MediaType" ) >>= mediaType
;
554 catch (const beans::UnknownPropertyException
&) {
556 OSL_ENSURE( !mediaType
.isEmpty(), "### no media-type?!" );
558 if (mediaType
.isEmpty())
561 Reference
<deployment::XPackage
> xPackage(
562 m_xRegistry
->bindPackage(
563 url
, OUString(), false, OUString(), ucbContent
.getCommandEnvironment() ) );
564 const Reference
<deployment::XPackageTypeInfo
> xPackageType(
565 xPackage
->getPackageType() );
566 OSL_ASSERT( xPackageType
.is() );
567 if (xPackageType
.is())
568 mediaType
= xPackageType
->getMediaType();
570 catch (const lang::IllegalArgumentException
& exc
) {
574 OSL_FAIL( OUStringToOString(
575 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
581 //______________________________________________________________________________
582 OUString
PackageManagerImpl::insertToActivationLayer(
583 Sequence
<beans::NamedValue
> const & properties
,
584 OUString
const & mediaType
, ::ucbhelper::Content
const & sourceContent_
,
585 OUString
const & title
, ActivePackages::Data
* dbData
)
587 ::ucbhelper::Content
sourceContent(sourceContent_
);
588 Reference
<XCommandEnvironment
> xCmdEnv(
589 sourceContent
.getCommandEnvironment() );
591 String
baseDir(m_activePackages_expanded
);
592 ::utl::TempFile
aTemp(&baseDir
, sal_False
);
593 OUString tempEntry
= aTemp
.GetURL();
594 tempEntry
= tempEntry
.copy(tempEntry
.lastIndexOf('/') + 1);
595 OUString destFolder
= makeURL( m_activePackages
, tempEntry
);
598 // prepare activation folder:
599 ::ucbhelper::Content destFolderContent
;
600 create_folder( &destFolderContent
, destFolder
, xCmdEnv
);
602 // copy content into activation temp dir:
603 if (mediaType
.matchIgnoreAsciiCase("application/vnd.sun.star.package-bundle") ||
604 // xxx todo: more sophisticated parsing
605 mediaType
.matchIgnoreAsciiCase("application/vnd.sun.star.legacy-package-bundle"))
609 if (!sourceContent
.isFolder())
611 buf
.appendAscii( "vnd.sun.star.zip://" );
612 buf
.append( ::rtl::Uri::encode( sourceContent
.getURL(),
613 rtl_UriCharClassRegName
,
614 rtl_UriEncodeIgnoreEscapes
,
615 RTL_TEXTENCODING_UTF8
) );
619 //Folder. No need to unzip, just copy
620 buf
.append(sourceContent
.getURL());
622 buf
.append( static_cast<sal_Unicode
>('/') );
623 sourceContent
= ::ucbhelper::Content(
624 buf
.makeStringAndClear(), xCmdEnv
, m_xComponentContext
);
626 if (! destFolderContent
.transferContent(
627 sourceContent
, ::ucbhelper::InsertOperation_COPY
,
628 title
, NameClash::OVERWRITE
))
629 throw RuntimeException( "UCB transferContent() failed!", 0 );
633 //bundled extensions should only be added by the synchronizeAddedExtensions
634 //functions. Moreover, there is no "temporary folder" for bundled extensions.
635 OSL_ASSERT(!(m_context
== "bundled"));
636 OUString sFolderUrl
= makeURLAppendSysPathSegment(destFolderContent
.getURL(), title
);
637 DescriptionInfoset info
=
638 dp_misc::getDescriptionInfoset(sFolderUrl
);
639 dbData
->temporaryName
= tempEntry
;
640 dbData
->fileName
= title
;
641 dbData
->mediaType
= mediaType
;
642 dbData
->version
= info
.getVersion();
644 //No write the properties file next to the extension
645 ExtensionProperties
props(sFolderUrl
, properties
, xCmdEnv
, m_xComponentContext
);
650 //______________________________________________________________________________
651 void PackageManagerImpl::insertToActivationLayerDB(
652 OUString
const & id
, ActivePackages::Data
const & dbData
)
654 //access to the database must be guarded. See removePackage
655 const ::osl::MutexGuard
guard( getMutex() );
656 m_activePackagesDB
->put( id
, dbData
);
659 //______________________________________________________________________________
660 /* The function returns true if there is an extension with the same id already
661 installed which needs to be uninstalled, before the new extension can be installed.
663 bool PackageManagerImpl::isInstalled(
664 Reference
<deployment::XPackage
> const & package
)
666 OUString
id(dp_misc::getIdentifier(package
));
667 OUString
fn(package
->getName());
668 bool bInstalled
= false;
669 if (m_activePackagesDB
->has( id
, fn
))
677 //______________________________________________________________________________
678 Reference
<deployment::XPackage
> PackageManagerImpl::importExtension(
679 Reference
<deployment::XPackage
> const & extension
,
680 Reference
<task::XAbortChannel
> const & xAbortChannel
,
681 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
682 throw (deployment::DeploymentException
, CommandFailedException
,
683 CommandAbortedException
, lang::IllegalArgumentException
,
686 return addPackage(extension
->getURL(), Sequence
<beans::NamedValue
>(),
687 OUString(), xAbortChannel
, xCmdEnv_
);
690 /* The function adds an extension but does not register it!!!
691 It may not do any user interaction. This is done in XExtensionManager::addExtension
693 Reference
<deployment::XPackage
> PackageManagerImpl::addPackage(
694 OUString
const & url
,
695 css::uno::Sequence
<css::beans::NamedValue
> const & properties
,
696 OUString
const & mediaType_
,
697 Reference
<task::XAbortChannel
> const & xAbortChannel
,
698 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
699 throw (deployment::DeploymentException
, CommandFailedException
,
700 CommandAbortedException
, lang::IllegalArgumentException
,
707 if (m_context
== "shared")
708 message
= "You need write permissions to install a shared extension!";
710 message
= "You need write permissions to install this extension!";
711 throw deployment::DeploymentException(
712 message
, static_cast<OWeakObject
*>(this), Any() );
714 Reference
<XCommandEnvironment
> xCmdEnv
;
716 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
718 xCmdEnv
.set( xCmdEnv_
);
721 ::ucbhelper::Content sourceContent
;
722 create_ucb_content( &sourceContent
, url
, xCmdEnv
); // throws exc
723 const OUString
title( StrTitle::getTitle( sourceContent
) );
724 const OUString
title_enc( ::rtl::Uri::encode(
725 title
, rtl_UriCharClassPchar
,
726 rtl_UriEncodeIgnoreEscapes
,
727 RTL_TEXTENCODING_UTF8
) );
730 OUString
mediaType(mediaType_
);
731 if (mediaType
.isEmpty())
732 mediaType
= detectMediaType( sourceContent
);
734 Reference
<deployment::XPackage
> xPackage
;
737 getResourceString(RID_STR_COPYING_PACKAGE
) + title
, xCmdEnv
);
738 if (m_activePackages
.isEmpty())
740 ::ucbhelper::Content docFolderContent
;
741 create_folder( &docFolderContent
, m_context
, xCmdEnv
);
742 // copy into document, first:
743 if (! docFolderContent
.transferContent(
744 sourceContent
, ::ucbhelper::InsertOperation_COPY
,
746 NameClash::ASK
/* xxx todo: ASK not needed? */))
747 throw RuntimeException("UCB transferContent() failed!", 0 );
749 ::ucbhelper::Content
docContent(
750 makeURL( m_context
, title_enc
), xCmdEnv
, m_xComponentContext
);
751 //TODO #i73136#: using title instead of id can lead to
752 // clashes, but the whole m_activePackages.getLength()==0
753 // case (i.e., document-relative deployment) currently does
755 docContent
.setPropertyValue("MediaType", Any(mediaType
) );
757 // xxx todo: obsolete in the future
759 docFolderContent
.executeCommand( "flush", Any() );
761 catch (const UnsupportedCommandException
&) {
764 ActivePackages::Data dbData
;
765 destFolder
= insertToActivationLayer(
766 properties
, mediaType
, sourceContent
, title
, &dbData
);
769 // bind activation package:
770 //Because every shared/user extension will be unpacked in a folder,
771 //which was created with a unique name we will always have two different
772 //XPackage objects, even if the second extension is the same.
773 //Therefore bindPackage does not need a guard here.
774 xPackage
= m_xRegistry
->bindPackage(
775 makeURL( destFolder
, title_enc
), mediaType
, false, OUString(), xCmdEnv
);
777 OSL_ASSERT( xPackage
.is() );
780 bool install
= false;
783 OUString
const id
= dp_misc::getIdentifier( xPackage
);
785 ::osl::MutexGuard
g(m_addMutex
);
786 if (isInstalled(xPackage
))
788 //Do not guard the complete function with the getMutex
789 removePackage(id
, xPackage
->getName(), xAbortChannel
,
793 insertToActivationLayerDB(id
, dbData
);
797 deletePackageFromCache( xPackage
, destFolder
);
802 deletePackageFromCache( xPackage
, destFolder
);
804 //ToDo: We should notify only if the extension is registered
809 catch (const RuntimeException
&) {
812 catch (const CommandFailedException
& exc
) {
813 logIntern( Any(exc
) );
816 catch (const CommandAbortedException
& exc
) {
817 logIntern( Any(exc
) );
820 catch (const deployment::DeploymentException
& exc
) {
821 logIntern( Any(exc
) );
824 catch (const Exception
&) {
825 Any
exc( ::cppu::getCaughtException() );
827 throw deployment::DeploymentException(
828 getResourceString(RID_STR_ERROR_WHILE_ADDING
) + url
,
829 static_cast<OWeakObject
*>(this), exc
);
832 void PackageManagerImpl::deletePackageFromCache(
833 Reference
<deployment::XPackage
> const & xPackage
,
834 OUString
const & destFolder
)
836 try_dispose( xPackage
);
838 //we remove the package from the uno cache
839 //no service from the package may be loaded at this time!!!
840 erase_path( destFolder
, Reference
<XCommandEnvironment
>(),
841 false /* no throw: ignore errors */ );
842 //rm last character '_'
843 OUString url
= destFolder
.copy(0, destFolder
.getLength() - 1);
844 erase_path( url
, Reference
<XCommandEnvironment
>(),
845 false /* no throw: ignore errors */ );
848 //______________________________________________________________________________
849 void PackageManagerImpl::removePackage(
850 OUString
const & id
, OUString
const & fileName
,
851 Reference
<task::XAbortChannel
> const & /*xAbortChannel*/,
852 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
853 throw (deployment::DeploymentException
, CommandFailedException
,
854 CommandAbortedException
, lang::IllegalArgumentException
,
859 Reference
<XCommandEnvironment
> xCmdEnv
;
861 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
863 xCmdEnv
.set( xCmdEnv_
);
866 Reference
<deployment::XPackage
> xPackage
;
868 const ::osl::MutexGuard
guard(getMutex());
869 //Check if this extension exist and throw an IllegalArgumentException
871 //If the files of the extension are already removed, or there is a
872 //different extension at the same place, for example after updating the
873 //extension, then the returned object is that which uses the database data.
874 xPackage
= getDeployedPackage_(id
, fileName
, xCmdEnv
);
877 //Because the extension is only removed the next time the extension
878 //manager runs after restarting OOo, we need to indicate that a
879 //shared extension was "deleted". When a user starts OOo, then it
880 //will check if something changed in the shared repository. Based on
881 //the flag file it will then recognize, that the extension was
882 //deleted and can then update the extnesion database of the shared
883 //extensions in the user installation.
884 if ( xPackage
.is() && !m_readOnly
&& !xPackage
->isRemoved() && (m_context
== "shared"))
886 ActivePackages::Data val
;
887 m_activePackagesDB
->get( & val
, id
, fileName
);
888 OSL_ASSERT(!val
.temporaryName
.isEmpty());
889 OUString
url(makeURL(m_activePackages_expanded
,
890 val
.temporaryName
+ "removed"));
891 ::ucbhelper::Content
contentRemoved(url
, xCmdEnv
, m_xComponentContext
);
893 ::osl::Security aSecurity
;
894 aSecurity
.getUserName( aUserName
);
896 OString stamp
= OUStringToOString(aUserName
, RTL_TEXTENCODING_UTF8
);
897 Reference
<css::io::XInputStream
> xData(
898 ::xmlscript::createInputStream(
900 reinterpret_cast<sal_Int8
const *>(stamp
.getStr()),
901 stamp
.getLength() ) ) );
902 contentRemoved
.writeStream( xData
, true /* replace existing */ );
904 m_activePackagesDB
->erase( id
, fileName
); // to be removed upon next start
905 //remove any cached data hold by the backend
906 m_xRegistry
->packageRemoved(xPackage
->getURL(), xPackage
->getPackageType()->getMediaType());
908 try_dispose( xPackage
);
912 catch (const RuntimeException
&) {
915 catch (const CommandFailedException
& exc
) {
916 logIntern( Any(exc
) );
919 catch (const CommandAbortedException
& exc
) {
920 logIntern( Any(exc
) );
923 catch (const deployment::DeploymentException
& exc
) {
924 logIntern( Any(exc
) );
927 catch (const Exception
&) {
928 Any
exc( ::cppu::getCaughtException() );
930 throw deployment::DeploymentException(
931 getResourceString(RID_STR_ERROR_WHILE_REMOVING
) + id
,
932 static_cast<OWeakObject
*>(this), exc
);
936 //______________________________________________________________________________
937 OUString
PackageManagerImpl::getDeployPath( ActivePackages::Data
const & data
)
940 buf
.append( data
.temporaryName
);
941 //The bundled extensions are not contained in an additional folder
942 //with a unique name. data.temporaryName contains already the
943 //UTF8 encoded folder name. See PackageManagerImpl::synchronize
944 if (!(m_context
== "bundled"))
946 buf
.appendAscii( "_/" );
947 buf
.append( ::rtl::Uri::encode( data
.fileName
, rtl_UriCharClassPchar
,
948 rtl_UriEncodeIgnoreEscapes
,
949 RTL_TEXTENCODING_UTF8
) );
951 return makeURL( m_activePackages
, buf
.makeStringAndClear() );
954 //______________________________________________________________________________
955 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage_(
956 OUString
const & id
, OUString
const & fileName
,
957 Reference
<XCommandEnvironment
> const & xCmdEnv
)
959 ActivePackages::Data val
;
960 if (m_activePackagesDB
->get( &val
, id
, fileName
))
962 return getDeployedPackage_( id
, val
, xCmdEnv
, false );
964 throw lang::IllegalArgumentException(
965 getResourceString(RID_STR_NO_SUCH_PACKAGE
) + id
,
966 static_cast<OWeakObject
*>(this), static_cast<sal_Int16
>(-1) );
969 //______________________________________________________________________________
970 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage_(
971 OUString
const & id
, ActivePackages::Data
const & data
,
972 Reference
<XCommandEnvironment
> const & xCmdEnv
, bool ignoreAlienPlatforms
)
974 if (ignoreAlienPlatforms
)
976 OUString type
, subType
;
977 INetContentTypeParameterList params
;
978 if (INetContentTypes::parse( data
.mediaType
, type
, subType
, ¶ms
))
980 INetContentTypeParameter
const * param
= params
.find(
981 OString("platform") );
982 if (param
!= 0 && !platform_fits( param
->m_sValue
))
983 throw lang::IllegalArgumentException(
984 getResourceString(RID_STR_NO_SUCH_PACKAGE
) + id
,
985 static_cast<OWeakObject
*>(this),
986 static_cast<sal_Int16
>(-1) );
989 Reference
<deployment::XPackage
> xExtension
;
992 //Ignore extensions where XPackage::checkPrerequisites failed.
993 //They must not be usable for this user.
994 if (data
.failedPrerequisites
== "0")
996 xExtension
= m_xRegistry
->bindPackage(
997 getDeployPath( data
), data
.mediaType
, false, OUString(), xCmdEnv
);
1000 catch (const deployment::InvalidRemovedParameterException
& e
)
1002 xExtension
= e
.Extension
;
1007 //______________________________________________________________________________
1008 Sequence
< Reference
<deployment::XPackage
> >
1009 PackageManagerImpl::getDeployedPackages_(
1010 Reference
<XCommandEnvironment
> const & xCmdEnv
)
1012 ::std::vector
< Reference
<deployment::XPackage
> > packages
;
1013 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1014 ActivePackages::Entries::const_iterator
iPos( id2temp
.begin() );
1015 ActivePackages::Entries::const_iterator
const iEnd( id2temp
.end() );
1016 for ( ; iPos
!= iEnd
; ++iPos
)
1018 if (! (iPos
->second
.failedPrerequisites
== "0"))
1022 getDeployedPackage_(
1023 iPos
->first
, iPos
->second
, xCmdEnv
,
1024 true /* xxx todo: think of GUI:
1025 ignore other platforms than the current one */ ) );
1027 catch (const lang::IllegalArgumentException
& exc
) {
1029 (void) exc
; // avoid warnings
1030 OSL_FAIL( OUStringToOString(
1031 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
1033 catch (const deployment::DeploymentException
& exc
) {
1035 (void) exc
; // avoid warnings
1036 OSL_FAIL( OUStringToOString(
1037 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
1040 return comphelper::containerToSequence(packages
);
1043 //______________________________________________________________________________
1044 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage(
1045 OUString
const & id
, OUString
const & fileName
,
1046 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1047 throw (deployment::DeploymentException
, CommandFailedException
,
1048 lang::IllegalArgumentException
, RuntimeException
)
1051 Reference
<XCommandEnvironment
> xCmdEnv
;
1052 if (m_xLogFile
.is())
1053 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1055 xCmdEnv
.set( xCmdEnv_
);
1058 const ::osl::MutexGuard
guard( getMutex() );
1059 return getDeployedPackage_( id
, fileName
, xCmdEnv
);
1061 catch (const lang::IllegalArgumentException
& exc
) {
1062 logIntern( Any(exc
) );
1065 catch (const RuntimeException
&) {
1068 catch (const CommandFailedException
& exc
) {
1069 logIntern( Any(exc
) );
1072 catch (const deployment::DeploymentException
& exc
) {
1073 logIntern( Any(exc
) );
1076 catch (const Exception
&) {
1077 Any
exc( ::cppu::getCaughtException() );
1079 throw deployment::DeploymentException(
1080 // ought never occur...
1081 "error while accessing deployed package: " + id
,
1082 static_cast<OWeakObject
*>(this), exc
);
1086 //______________________________________________________________________________
1087 Sequence
< Reference
<deployment::XPackage
> >
1088 PackageManagerImpl::getDeployedPackages(
1089 Reference
<task::XAbortChannel
> const &,
1090 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1091 throw (deployment::DeploymentException
, CommandFailedException
,
1092 CommandAbortedException
, lang::IllegalArgumentException
,
1096 Reference
<XCommandEnvironment
> xCmdEnv
;
1097 if (m_xLogFile
.is())
1098 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1100 xCmdEnv
.set( xCmdEnv_
);
1103 const ::osl::MutexGuard
guard( getMutex() );
1104 return getDeployedPackages_( xCmdEnv
);
1106 catch (const RuntimeException
&) {
1109 catch (const CommandFailedException
& exc
) {
1110 logIntern( Any(exc
) );
1113 catch (const CommandAbortedException
& exc
) {
1114 logIntern( Any(exc
) );
1117 catch (const deployment::DeploymentException
& exc
) {
1118 logIntern( Any(exc
) );
1121 catch (const Exception
&) {
1122 Any
exc( ::cppu::getCaughtException() );
1124 throw deployment::DeploymentException(
1125 // ought never occur...
1126 "error while getting all deployed packages: " + m_context
,
1127 static_cast<OWeakObject
*>(this), exc
);
1131 //______________________________________________________________________________
1134 //ToDo: the function must not call registerPackage, do this in
1135 //XExtensionManager.reinstallDeployedExtensions
1136 void PackageManagerImpl::reinstallDeployedPackages(
1137 sal_Bool force
, Reference
<task::XAbortChannel
> const & /*xAbortChannel*/,
1138 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1139 throw (deployment::DeploymentException
,
1140 CommandFailedException
, CommandAbortedException
,
1141 lang::IllegalArgumentException
, RuntimeException
)
1144 if (!force
&& office_is_running())
1145 throw RuntimeException(
1146 "You must close any running Office process before reinstalling packages!",
1147 static_cast<OWeakObject
*>(this) );
1149 Reference
<XCommandEnvironment
> xCmdEnv
;
1150 if (m_xLogFile
.is())
1151 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1153 xCmdEnv
.set( xCmdEnv_
);
1156 ProgressLevel
progress(
1157 xCmdEnv
, "Reinstalling all deployed packages..." );
1159 try_dispose( m_xRegistry
);
1160 m_xRegistry
.clear();
1161 if (!m_registryCache
.isEmpty())
1162 erase_path( m_registryCache
, xCmdEnv
);
1163 initRegistryBackends();
1164 Reference
<util::XUpdatable
> xUpdatable( m_xRegistry
, UNO_QUERY
);
1165 if (xUpdatable
.is())
1166 xUpdatable
->update();
1168 //registering is done by the ExtensionManager service.
1170 catch (const RuntimeException
&) {
1173 catch (const CommandFailedException
& exc
) {
1174 logIntern( Any(exc
) );
1177 catch (const CommandAbortedException
& exc
) {
1178 logIntern( Any(exc
) );
1181 catch (const deployment::DeploymentException
& exc
) {
1182 logIntern( Any(exc
) );
1185 catch (const Exception
&) {
1186 Any
exc( ::cppu::getCaughtException() );
1188 throw deployment::DeploymentException(
1189 "Error while reinstalling all previously deployed packages of context " + m_context
,
1190 static_cast<OWeakObject
*>(this), exc
);
1195 ::sal_Bool SAL_CALL
PackageManagerImpl::isReadOnly( )
1196 throw (::com::sun::star::uno::RuntimeException
)
1200 bool PackageManagerImpl::synchronizeRemovedExtensions(
1201 Reference
<task::XAbortChannel
> const & xAbortChannel
,
1202 Reference
<css::ucb::XCommandEnvironment
> const & xCmdEnv
)
1205 //find all which are in the extension data base but which
1206 //are removed already.
1207 OSL_ASSERT(!(m_context
== "user"));
1208 bool bModified
= false;
1209 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1211 typedef ActivePackages::Entries::const_iterator ITActive
;
1212 bool bShared
= (m_context
== "shared");
1214 for (ITActive i
= id2temp
.begin(); i
!= id2temp
.end(); ++i
)
1218 //Get the URL to the extensions folder, first make the url for the
1219 //shared repository including the temporary name
1220 OUString url
= makeURL(m_activePackages
, i
->second
.temporaryName
);
1222 url
= makeURLAppendSysPathSegment( url
+ "_", i
->second
.fileName
);
1224 bool bRemoved
= false;
1225 //Check if the URL to the extension is still the same
1226 ::ucbhelper::Content contentExtension
;
1228 if (!create_ucb_content(
1229 &contentExtension
, url
,
1230 Reference
<XCommandEnvironment
>(), false))
1235 //The folder is in the extension database, but it can still be deleted.
1236 //look for the xxx.tmpremoved file
1237 //There can also be the case that a different extension was installed
1238 //in a "temp" folder with name that is already used.
1239 if (!bRemoved
&& bShared
)
1241 ::ucbhelper::Content contentRemoved
;
1243 if (create_ucb_content(
1245 m_activePackages_expanded
+ "/" +
1246 i
->second
.temporaryName
+ "removed",
1247 Reference
<XCommandEnvironment
>(), false))
1255 //There may be another extensions at the same place
1256 dp_misc::DescriptionInfoset infoset
=
1257 dp_misc::getDescriptionInfoset(url
);
1258 OSL_ENSURE(infoset
.hasDescription() && infoset
.getIdentifier(),
1259 "Extension Manager: bundled and shared extensions "
1260 "must have an identifer and a version");
1261 if (infoset
.hasDescription() &&
1262 infoset
.getIdentifier() &&
1263 (! i
->first
.equals(*(infoset
.getIdentifier()))
1264 || ! i
->second
.version
.equals(infoset
.getVersion())))
1272 Reference
<deployment::XPackage
> xPackage
= m_xRegistry
->bindPackage(
1273 url
, i
->second
.mediaType
, true, i
->first
, xCmdEnv
);
1274 OSL_ASSERT(xPackage
.is()); //Even if the files are removed, we must get the object.
1275 xPackage
->revokePackage(true, xAbortChannel
, xCmdEnv
);
1276 removePackage(xPackage
->getIdentifier().Value
, xPackage
->getName(),
1277 xAbortChannel
, xCmdEnv
);
1281 catch( const uno::Exception
& e
)
1283 SAL_WARN("desktop.deployment", e
.Message
);
1290 bool PackageManagerImpl::synchronizeAddedExtensions(
1291 Reference
<task::XAbortChannel
> const & xAbortChannel
,
1292 Reference
<css::ucb::XCommandEnvironment
> const & xCmdEnv
)
1294 bool bModified
= false;
1295 OSL_ASSERT(!(m_context
== "user"));
1297 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1298 //check if the folder exist at all. The shared extension folder
1299 //may not exist for a normal user.
1300 if (!create_ucb_content(
1301 NULL
, m_activePackages_expanded
, Reference
<css::ucb::XCommandEnvironment
>(), false))
1304 ::ucbhelper::Content
tempFolder( m_activePackages_expanded
, xCmdEnv
, m_xComponentContext
);
1305 Reference
<sdbc::XResultSet
> xResultSet(
1306 StrTitle::createCursor( tempFolder
,
1307 ::ucbhelper::INCLUDE_FOLDERS_ONLY
) );
1309 while (xResultSet
->next())
1314 Reference
<sdbc::XRow
>(
1315 xResultSet
, UNO_QUERY_THROW
)->getString(
1317 //The temporary folders of user and shared have an '_' at then end.
1318 //But the name in ActivePackages.temporaryName is saved without.
1319 OUString title2
= title
;
1320 bool bShared
= (m_context
== "shared");
1323 OSL_ASSERT(title2
[title2
.getLength() -1] == '_');
1324 title2
= title2
.copy(0, title2
.getLength() -1);
1326 OUString titleEncoded
= ::rtl::Uri::encode(
1327 title2
, rtl_UriCharClassPchar
,
1328 rtl_UriEncodeIgnoreEscapes
,
1329 RTL_TEXTENCODING_UTF8
);
1331 //It it sufficient to check for the folder name, because when the administor
1332 //installed the extension it was already checked if there is one with the
1334 const MatchTempDir
match(titleEncoded
);
1335 if (::std::find_if( id2temp
.begin(), id2temp
.end(), match
) ==
1339 // The folder was not found in the data base, so it must be
1340 // an added extension
1341 OUString
url(m_activePackages_expanded
+ "/" + titleEncoded
);
1342 OUString sExtFolder
;
1343 if (bShared
) //that is, shared
1345 //Check if the extension was not "deleted" already which is indicated
1346 //by a xxx.tmpremoved file
1347 ::ucbhelper::Content contentRemoved
;
1348 if (create_ucb_content(&contentRemoved
, url
+ "removed",
1349 Reference
<XCommandEnvironment
>(), false))
1351 sExtFolder
= getExtensionFolder(
1352 m_activePackages_expanded
+ "/" + titleEncoded
+ "_",
1353 xCmdEnv
, m_xComponentContext
);
1354 url
= makeURLAppendSysPathSegment(m_activePackages_expanded
, title
);
1355 url
= makeURLAppendSysPathSegment(url
, sExtFolder
);
1357 Reference
<deployment::XPackage
> xPackage
= m_xRegistry
->bindPackage(
1358 url
, OUString(), false, OUString(), xCmdEnv
);
1361 //Prepare the database entry
1362 ActivePackages::Data dbData
;
1364 dbData
.temporaryName
= titleEncoded
;
1366 dbData
.fileName
= sExtFolder
;
1368 dbData
.fileName
= title
;
1369 dbData
.mediaType
= xPackage
->getPackageType()->getMediaType();
1370 dbData
.version
= xPackage
->getVersion();
1371 OSL_ENSURE(!dbData
.version
.isEmpty(),
1372 "Extension Manager: bundled and shared extensions must have "
1373 "an identifier and a version");
1375 OUString id
= dp_misc::getIdentifier( xPackage
);
1377 //We provide a special command environment that will prevent
1378 //showing a license if simple-licens/@accept-by = "admin"
1379 //It will also prevent showing the license for bundled extensions
1380 //which is not supported.
1381 OSL_ASSERT(!(m_context
== "user"));
1383 // shall the license be suppressed?
1384 DescriptionInfoset info
=
1385 dp_misc::getDescriptionInfoset(url
);
1386 ::boost::optional
<dp_misc::SimpleLicenseAttributes
>
1387 attr
= info
.getSimpleLicenseAttributes();
1388 ExtensionProperties
props(url
, xCmdEnv
, m_xComponentContext
);
1389 bool bNoLicense
= false;
1390 if (attr
&& attr
->suppressIfRequired
&& props
.isSuppressedLicense())
1393 Reference
<ucb::XCommandEnvironment
> licCmdEnv(
1394 new LicenseCommandEnv(xCmdEnv
->getInteractionHandler(),
1395 bNoLicense
, m_context
));
1396 sal_Int32 failedPrereq
= xPackage
->checkPrerequisites(
1397 xAbortChannel
, licCmdEnv
, false);
1398 //Remember that this failed. For example, the user
1399 //could have declined the license. Then the next time the
1400 //extension folder is investigated we do not want to
1401 //try to install the extension again.
1402 dbData
.failedPrerequisites
= OUString::valueOf(failedPrereq
);
1403 insertToActivationLayerDB(id
, dbData
);
1408 catch (const uno::Exception
& e
)
1410 // Looks like exceptions being caught here is not an uncommon case.
1411 SAL_WARN("desktop.deployment", e
.Message
);
1417 sal_Bool
PackageManagerImpl::synchronize(
1418 Reference
<task::XAbortChannel
> const & xAbortChannel
,
1419 Reference
<css::ucb::XCommandEnvironment
> const & xCmdEnv
)
1420 throw (css::deployment::DeploymentException
,
1421 css::ucb::CommandFailedException
,
1422 css::ucb::CommandAbortedException
,
1423 css::uno::RuntimeException
)
1426 bool bModified
= false;
1427 if (m_context
== "user")
1430 synchronizeRemovedExtensions(xAbortChannel
, xCmdEnv
);
1431 bModified
|= synchronizeAddedExtensions(xAbortChannel
, xCmdEnv
);
1436 Sequence
< Reference
<deployment::XPackage
> > PackageManagerImpl::getExtensionsWithUnacceptedLicenses(
1437 Reference
<ucb::XCommandEnvironment
> const & xCmdEnv
)
1438 throw (deployment::DeploymentException
, RuntimeException
)
1440 ::std::vector
<Reference
<deployment::XPackage
> > vec
;
1444 const ::osl::MutexGuard
guard( getMutex() );
1445 // clean up activation layer, scan for zombie temp dirs:
1446 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1448 ActivePackages::Entries::const_iterator i
= id2temp
.begin();
1449 bool bShared
= (m_context
== "shared");
1451 for (; i
!= id2temp
.end(); ++i
)
1453 //Get the database entry
1454 ActivePackages::Data
const & dbData
= i
->second
;
1455 sal_Int32 failedPrereq
= dbData
.failedPrerequisites
.toInt32();
1456 //If the installation failed for other reason then the license then we
1458 if (failedPrereq
^= deployment::Prerequisites::LICENSE
)
1461 //Prepare the URL to the extension
1462 OUString url
= makeURL(m_activePackages
, i
->second
.temporaryName
);
1464 url
= makeURLAppendSysPathSegment( url
+ "_", i
->second
.fileName
);
1466 Reference
<deployment::XPackage
> p
= m_xRegistry
->bindPackage(
1467 url
, OUString(), false, OUString(), xCmdEnv
);
1473 return ::comphelper::containerToSequence(vec
);
1475 catch (const deployment::DeploymentException
&)
1479 catch (const RuntimeException
&)
1485 Any exc
= ::cppu::getCaughtException();
1486 deployment::DeploymentException
de(
1487 "PackageManagerImpl::getExtensionsWithUnacceptedLicenses",
1488 static_cast<OWeakObject
*>(this), exc
);
1490 ::cppu::throwException(exc
);
1493 return ::comphelper::containerToSequence(vec
);
1496 sal_Int32
PackageManagerImpl::checkPrerequisites(
1497 css::uno::Reference
<css::deployment::XPackage
> const & extension
,
1498 css::uno::Reference
<css::task::XAbortChannel
> const & xAbortChannel
,
1499 css::uno::Reference
<css::ucb::XCommandEnvironment
> const & xCmdEnv
)
1500 throw (css::deployment::DeploymentException
,
1501 css::ucb::CommandFailedException
,
1502 css::ucb::CommandAbortedException
,
1503 css::lang::IllegalArgumentException
,
1504 css::uno::RuntimeException
)
1508 if (!extension
.is())
1510 if (!m_context
.equals(extension
->getRepositoryName()))
1511 throw lang::IllegalArgumentException(
1512 "PackageManagerImpl::checkPrerequisites: extension is not from this repository.",
1515 ActivePackages::Data dbData
;
1516 OUString id
= dp_misc::getIdentifier(extension
);
1517 if (m_activePackagesDB
->get( &dbData
, id
, OUString()))
1519 //If the license was already displayed, then do not show it again
1520 Reference
<ucb::XCommandEnvironment
> _xCmdEnv
= xCmdEnv
;
1521 sal_Int32 prereq
= dbData
.failedPrerequisites
.toInt32();
1522 if ( !(prereq
& deployment::Prerequisites::LICENSE
))
1523 _xCmdEnv
= new NoLicenseCommandEnv(xCmdEnv
->getInteractionHandler());
1525 sal_Int32 failedPrereq
= extension
->checkPrerequisites(
1526 xAbortChannel
, _xCmdEnv
, false);
1527 dbData
.failedPrerequisites
= OUString::valueOf(failedPrereq
);
1528 insertToActivationLayerDB(id
, dbData
);
1532 throw lang::IllegalArgumentException(
1533 "PackageManagerImpl::checkPrerequisites: unknown extension",
1539 catch ( const deployment::DeploymentException
& ) {
1541 } catch ( const ucb::CommandFailedException
& ) {
1543 } catch ( const ucb::CommandAbortedException
& ) {
1545 } catch (const lang::IllegalArgumentException
&) {
1547 } catch (const uno::RuntimeException
&) {
1550 uno::Any excOccurred
= ::cppu::getCaughtException();
1551 deployment::DeploymentException
exc(
1552 "PackageManagerImpl::checkPrerequisites: exception ",
1553 static_cast<OWeakObject
*>(this), excOccurred
);
1559 //______________________________________________________________________________
1560 PackageManagerImpl::CmdEnvWrapperImpl::~CmdEnvWrapperImpl()
1564 //______________________________________________________________________________
1565 PackageManagerImpl::CmdEnvWrapperImpl::CmdEnvWrapperImpl(
1566 Reference
<XCommandEnvironment
> const & xUserCmdEnv
,
1567 Reference
<XProgressHandler
> const & xLogFile
)
1568 : m_xLogFile( xLogFile
)
1570 if (xUserCmdEnv
.is()) {
1571 m_xUserProgress
.set( xUserCmdEnv
->getProgressHandler() );
1572 m_xUserInteractionHandler
.set( xUserCmdEnv
->getInteractionHandler() );
1576 // XCommandEnvironment
1577 //______________________________________________________________________________
1578 Reference
<task::XInteractionHandler
>
1579 PackageManagerImpl::CmdEnvWrapperImpl::getInteractionHandler()
1580 throw (RuntimeException
)
1582 return m_xUserInteractionHandler
;
1585 //______________________________________________________________________________
1586 Reference
<XProgressHandler
>
1587 PackageManagerImpl::CmdEnvWrapperImpl::getProgressHandler()
1588 throw (RuntimeException
)
1594 //______________________________________________________________________________
1595 void PackageManagerImpl::CmdEnvWrapperImpl::push( Any
const & Status
)
1596 throw (RuntimeException
)
1598 if (m_xLogFile
.is())
1599 m_xLogFile
->push( Status
);
1600 if (m_xUserProgress
.is())
1601 m_xUserProgress
->push( Status
);
1604 //______________________________________________________________________________
1605 void PackageManagerImpl::CmdEnvWrapperImpl::update( Any
const & Status
)
1606 throw (RuntimeException
)
1608 if (m_xLogFile
.is())
1609 m_xLogFile
->update( Status
);
1610 if (m_xUserProgress
.is())
1611 m_xUserProgress
->update( Status
);
1614 //______________________________________________________________________________
1615 void PackageManagerImpl::CmdEnvWrapperImpl::pop() throw (RuntimeException
)
1617 if (m_xLogFile
.is())
1619 if (m_xUserProgress
.is())
1620 m_xUserProgress
->pop();
1623 } // namespace dp_manager
1625 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */