1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dp_manager.cxx,v $
10 * $Revision: 1.33.8.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_desktop.hxx"
35 #include "dp_resource.h"
36 #include "dp_platform.hxx"
37 #include "dp_manager.h"
38 #include "dp_identifier.hxx"
39 #include "rtl/ustrbuf.hxx"
40 #include "rtl/string.hxx"
41 #include "rtl/uri.hxx"
42 #include "rtl/bootstrap.hxx"
43 #include "osl/diagnose.h"
44 #include "osl/file.hxx"
45 #include "cppuhelper/weakref.hxx"
46 #include "cppuhelper/exc_hlp.hxx"
47 #include "cppuhelper/implbase1.hxx"
48 #include "cppuhelper/interfacecontainer.hxx"
49 #include "comphelper/servicedecl.hxx"
50 #include "comphelper/sequence.hxx"
51 #include "xmlscript/xml_helper.hxx"
52 #include "svtools/inettype.hxx"
53 #include "com/sun/star/lang/DisposedException.hpp"
54 #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
55 #include "com/sun/star/beans/UnknownPropertyException.hpp"
56 #include "com/sun/star/util/XUpdatable.hpp"
57 #include "com/sun/star/sdbc/XResultSet.hpp"
58 #include "com/sun/star/sdbc/XRow.hpp"
59 #include "com/sun/star/ucb/XContentAccess.hpp"
60 #include "com/sun/star/ucb/NameClash.hpp"
61 #include "com/sun/star/deployment/VersionException.hpp"
62 #include "com/sun/star/deployment/InstallException.hpp"
63 #include "com/sun/star/deployment/LinkException.hpp"
64 #include "com/sun/star/task/XInteractionApprove.hpp"
65 #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
66 #include "boost/bind.hpp"
70 using namespace ::dp_misc
;
71 using namespace ::com::sun::star
;
72 using namespace ::com::sun::star::uno
;
73 using namespace ::com::sun::star::ucb
;
74 using ::rtl::OUString
;
77 extern comphelper::service_decl::ServiceDecl
const serviceDecl
;
80 namespace dp_registry
{
81 Reference
<deployment::XPackageRegistry
> create(
82 OUString
const & context
,
83 OUString
const & cachePath
, bool readOnly
,
84 Reference
<XComponentContext
> const & xComponentContext
);
87 namespace dp_manager
{
92 MatchTempDir( OUString
const & str
) : m_str( str
) {}
93 bool operator () ( ActivePackages::Entries::value_type
const & v
) const {
94 return v
.second
.temporaryName
.equalsIgnoreAsciiCase( m_str
);
98 //______________________________________________________________________________
99 void PackageManagerImpl::initActivationLayer(
100 Reference
<XCommandEnvironment
> const & xCmdEnv
)
102 if (m_activePackages
.getLength() == 0)
104 OSL_ASSERT( m_registryCache
.getLength() == 0 );
105 // documents temp activation:
106 m_activePackagesDB
.reset( new ActivePackages
);
107 ::ucbhelper::Content ucbContent
;
108 if (create_ucb_content( &ucbContent
, m_context
, xCmdEnv
,
109 false /* no throw */ ))
111 // scan for all entries in m_packagesDir:
112 Reference
<sdbc::XResultSet
> xResultSet(
113 ucbContent
.createCursor(
114 Sequence
<OUString
>( &StrTitle::get(), 1 ),
115 ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS
) );
116 while (xResultSet
->next())
118 Reference
<sdbc::XRow
> xRow( xResultSet
, UNO_QUERY_THROW
);
119 OUString
title( xRow
->getString( 1 /* Title */ ) );
120 // xxx todo: remove workaround for tdoc
121 if (title
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
122 "this_is_a_dummy_stream_just_there_"
123 "as_a_workaround_for_a_"
124 "temporary_limitation_of_the_"
125 "storage_api_implementation") ))
127 if (title
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
131 ::ucbhelper::Content
sourceContent(
132 Reference
<XContentAccess
>(
133 xResultSet
, UNO_QUERY_THROW
)->queryContent(),
136 OUString
mediaType( detectMediaType( sourceContent
,
137 false /* no throw */) );
138 if (mediaType
.getLength() >0)
140 ActivePackages::Data dbData
;
141 insertToActivationLayer(
142 mediaType
, sourceContent
, title
, &dbData
);
144 insertToActivationLayerDB( title
, dbData
);
145 //TODO #i73136#: insertToActivationLayerDB needs id not
146 // title, but the whole m_activePackages.getLength()==0
147 // case (i.e., document-relative deployment) currently
148 // does not work, anyway.
156 OSL_ASSERT( m_activePackages
.getLength() > 0 );
157 m_activePackages_expanded
= expandUnoRcUrl( m_activePackages
);
158 create_folder( 0, m_activePackages_expanded
, xCmdEnv
, !m_readOnly
);
159 m_activePackagesDB
.reset(
161 m_activePackages_expanded
+ OUSTR(".db"), m_readOnly
) );
165 // clean up activation layer, scan for zombie temp dirs:
166 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
168 ::ucbhelper::Content
tempFolder(
169 m_activePackages_expanded
, xCmdEnv
);
170 Reference
<sdbc::XResultSet
> xResultSet(
171 tempFolder
.createCursor(
172 Sequence
<OUString
>( &StrTitle::get(), 1 ),
173 ::ucbhelper::INCLUDE_DOCUMENTS_ONLY
) );
174 // get all temp directories:
175 ::std::vector
<OUString
> tempEntries
;
176 while (xResultSet
->next()) {
178 Reference
<sdbc::XRow
>(
179 xResultSet
, UNO_QUERY_THROW
)->getString(
181 tempEntries
.push_back( ::rtl::Uri::encode(
182 title
, rtl_UriCharClassPchar
,
183 rtl_UriEncodeIgnoreEscapes
,
184 RTL_TEXTENCODING_UTF8
) );
187 for ( ::std::size_t pos
= 0; pos
< tempEntries
.size(); ++pos
)
189 OUString
const & tempEntry
= tempEntries
[ pos
];
190 const MatchTempDir
match( tempEntry
);
191 if (::std::find_if( id2temp
.begin(), id2temp
.end(), match
) ==
194 // temp entry not needed anymore:
195 const OUString
url( makeURL( m_activePackages_expanded
,
197 erase_path( url
+ OUSTR("_"),
198 Reference
<XCommandEnvironment
>(),
199 false /* no throw: ignore errors */ );
200 erase_path( url
, Reference
<XCommandEnvironment
>(),
201 false /* no throw: ignore errors */ );
208 //______________________________________________________________________________
209 void PackageManagerImpl::initRegistryBackends()
211 if (m_registryCache
.getLength() > 0)
212 create_folder( 0, m_registryCache
,
213 Reference
<XCommandEnvironment
>(), !m_readOnly
);
214 m_xRegistry
.set( ::dp_registry::create(
215 m_context
, m_registryCache
, m_readOnly
,
216 m_xComponentContext
) );
219 //______________________________________________________________________________
220 Reference
<deployment::XPackageManager
> PackageManagerImpl::create(
221 Reference
<XComponentContext
> const & xComponentContext
,
222 OUString
const & context
)
224 PackageManagerImpl
* that
= new PackageManagerImpl(
225 xComponentContext
, context
);
226 Reference
<deployment::XPackageManager
> xPackageManager( that
);
228 OUString packages
, logFile
, stampURL
;
229 if (context
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("user") )) {
230 that
->m_activePackages
= OUSTR("vnd.sun.star.expand:$UNO_"
231 "USER_PACKAGES_CACHE/uno_packages");
232 that
->m_registryCache
= OUSTR("vnd.sun.star.expand:$UNO_"
233 "USER_PACKAGES_CACHE/registry");
234 logFile
= OUSTR("vnd.sun.star.expand:$UNO_"
235 "USER_PACKAGES_CACHE/log.txt");
236 //We use the extension .sys for the file because on Windows Vista a sys
237 //(as well as exe and dll) file
238 //will not be written in the VirtualStore. For example if the process has no
239 //admin right once cannot write to the %programfiles% folder. However, when
240 //virtualization is used, the file will be written into the VirtualStore and
241 //it appears as if one could write to %programfiles%. When we test for write
242 //access to the office/shared folder for shared extensions then this typically
243 //fails because a normal user typically cannot write to this folder. However,
244 //using virtualization it appears that he/she can. Then a shared extension can
245 //be installed but is only visible for the user (because the extension is in
246 //the virtual store).
247 stampURL
= OUSTR("vnd.sun.star.expand:$UNO_"
248 "USER_PACKAGES_CACHE/stamp.sys");
250 else if (context
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") )) {
251 that
->m_activePackages
= OUSTR("vnd.sun.star.expand:$UNO_"
252 "SHARED_PACKAGES_CACHE/uno_packages");
253 that
->m_registryCache
= OUSTR("vnd.sun.star.expand:$UNO_"
254 "SHARED_PACKAGES_CACHE/registry");
255 // The current logging implementation does not work for shared, because it requires
256 // write access to the logfile. When two users run OOo at the same time on the same machine
258 // second will fail because it does not get write access. One cannot write into the
259 // user's home, because then people may complain that when installing shared extension
260 // stuff is written in their home.
261 // logFile = OUSTR("vnd.sun.star.expand:$UNO_"
262 // "SHARED_PACKAGES_CACHE/log.txt");
263 //See description for stampURL for user packages.
264 stampURL
= OUSTR("vnd.sun.star.expand:$UNO_"
265 "SHARED_PACKAGES_CACHE/stamp.sys");
267 else if (! context
.matchAsciiL(
268 RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:/") )) {
269 throw lang::IllegalArgumentException(
270 OUSTR("invalid context given: ") + context
,
271 Reference
<XInterface
>(), static_cast<sal_Int16
>(-1) );
274 Reference
<XCommandEnvironment
> xCmdEnv
;
277 bool renewal
= false;
279 if (stampURL
.getLength() > 0)
281 // currently no automatic renewal possible, because quickstarter
282 // already hinders from deleting registry directory...
284 #define CURRENT_STAMP "1"
287 // ::ucbhelper::Content ucbStamp;
288 // if (create_ucb_content(
289 // &ucbStamp, stampURL, xCmdEnv, false /* no throw */ ))
292 // renewal = !readLine( &line, OUSTR(CURRENT_STAMP), ucbStamp,
293 // RTL_TEXTENCODING_ASCII_US );
299 erase_path( stampURL
, xCmdEnv
);
300 ::ucbhelper::Content
ucbStamp( stampURL
, xCmdEnv
);
301 ::rtl::OString
stamp(
302 RTL_CONSTASCII_STRINGPARAM(CURRENT_STAMP
) );
303 Reference
<io::XInputStream
> xData(
304 ::xmlscript::createInputStream(
306 reinterpret_cast<sal_Int8
const *>(stamp
.getStr()),
307 stamp
.getLength() ) ) );
308 ucbStamp
.writeStream( xData
, true /* replace existing */ );
310 catch (RuntimeException
&) {
313 catch (Exception
&) {
314 that
->m_readOnly
= true;
318 //Workaround. See issue http://www.openoffice.org/issues/show_bug.cgi?id=99257
319 //This prevents the copying of the common.rdbf and native rdbs. It disables the
320 //feature to add shared extensions in a running office.
321 if (!that
->m_readOnly
&& context
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("shared") ))
324 ::rtl::Bootstrap::get(OUSTR("NORDBCOPY"), sNoRdb
);
325 if (sNoRdb
.equalsIgnoreAsciiCase(OUSTR("true"))
326 && dp_misc::office_is_running())
327 that
->m_readOnly
= true;
330 if (!that
->m_readOnly
&& logFile
.getLength() > 0)
332 const Any
any_logFile(logFile
);
333 that
->m_xLogFile
.set(
334 that
->m_xComponentContext
->getServiceManager()
335 ->createInstanceWithArgumentsAndContext(
336 dp_log::serviceDecl
.getSupportedServiceNames()[0],
337 Sequence
<Any
>( &any_logFile
, 1 ),
338 that
->m_xComponentContext
),
340 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv
, that
->m_xLogFile
) );
343 OSL_ENSURE( !that
->m_readOnly
|| !renewal
,
344 "### ought to reinstall all packages, but cannot write!" );
345 if (!that
->m_readOnly
&& renewal
) // try to reinstall
346 that
->reinstallDeployedPackages(
347 Reference
<task::XAbortChannel
>(), xCmdEnv
);
349 that
->initRegistryBackends();
350 that
->initActivationLayer( xCmdEnv
);
352 return xPackageManager
;
355 catch (RuntimeException
&) {
358 catch (Exception
&) {
359 Any
exc( ::cppu::getCaughtException() );
360 ::rtl::OUStringBuffer buf
;
361 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("[context=\"") );
362 buf
.append( context
);
363 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM(
364 "\"] caught unexpected exception!") );
365 throw lang::WrappedTargetRuntimeException(
366 buf
.makeStringAndClear(), Reference
<XInterface
>(), exc
);
370 //______________________________________________________________________________
371 PackageManagerImpl::~PackageManagerImpl()
375 //______________________________________________________________________________
376 void PackageManagerImpl::fireModified()
378 ::cppu::OInterfaceContainerHelper
* pContainer
= rBHelper
.getContainer(
379 util::XModifyListener::static_type() );
380 if (pContainer
!= 0) {
381 pContainer
->forEach
<util::XModifyListener
>(
382 boost::bind(&util::XModifyListener::modified
, _1
,
383 lang::EventObject(static_cast<OWeakObject
*>(this))) );
387 //______________________________________________________________________________
388 void PackageManagerImpl::disposing()
391 // // xxx todo: guarding?
392 // ::osl::MutexGuard guard( getMutex() );
393 try_dispose( m_xLogFile
);
395 try_dispose( m_xRegistry
);
397 m_activePackagesDB
.reset(0);
398 m_xComponentContext
.clear();
400 t_pm_helper::disposing();
403 catch (RuntimeException
&) {
406 catch (Exception
&) {
407 Any
exc( ::cppu::getCaughtException() );
408 throw lang::WrappedTargetRuntimeException(
409 OUSTR("caught unexpected exception while disposing..."),
410 static_cast<OWeakObject
*>(this), exc
);
415 //______________________________________________________________________________
416 void PackageManagerImpl::dispose() throw (RuntimeException
)
419 WeakComponentImplHelperBase::dispose();
422 //______________________________________________________________________________
423 void PackageManagerImpl::addEventListener(
424 Reference
<lang::XEventListener
> const & xListener
) throw (RuntimeException
)
427 WeakComponentImplHelperBase::addEventListener( xListener
);
430 //______________________________________________________________________________
431 void PackageManagerImpl::removeEventListener(
432 Reference
<lang::XEventListener
> const & xListener
) throw (RuntimeException
)
435 WeakComponentImplHelperBase::removeEventListener( xListener
);
439 //______________________________________________________________________________
440 OUString
PackageManagerImpl::getContext() throw (RuntimeException
)
446 //______________________________________________________________________________
447 Sequence
< Reference
<deployment::XPackageTypeInfo
> >
448 PackageManagerImpl::getSupportedPackageTypes() throw (RuntimeException
)
450 OSL_ASSERT( m_xRegistry
.is() );
451 return m_xRegistry
->getSupportedPackageTypes();
454 //______________________________________________________________________________
455 Reference
<task::XAbortChannel
> PackageManagerImpl::createAbortChannel()
456 throw (RuntimeException
)
459 return new AbortChannel
;
462 // XModifyBroadcaster
463 //______________________________________________________________________________
464 void PackageManagerImpl::addModifyListener(
465 Reference
<util::XModifyListener
> const & xListener
)
466 throw (RuntimeException
)
469 rBHelper
.addListener( ::getCppuType( &xListener
), xListener
);
472 //______________________________________________________________________________
473 void PackageManagerImpl::removeModifyListener(
474 Reference
<util::XModifyListener
> const & xListener
)
475 throw (RuntimeException
)
478 rBHelper
.removeListener( ::getCppuType( &xListener
), xListener
);
481 //______________________________________________________________________________
482 OUString
PackageManagerImpl::detectMediaType(
483 ::ucbhelper::Content
const & ucbContent_
, bool throw_exc
)
485 ::ucbhelper::Content
ucbContent(ucbContent_
);
486 OUString
url( ucbContent
.getURL() );
488 if (url
.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.tdoc:") ) ||
489 url
.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.pkg:") ))
492 ucbContent
.getPropertyValue( OUSTR("MediaType") ) >>= mediaType
;
494 catch (beans::UnknownPropertyException
&) {
496 OSL_ENSURE( mediaType
.getLength() > 0, "### no media-type?!" );
498 if (mediaType
.getLength() == 0)
501 Reference
<deployment::XPackage
> xPackage(
502 m_xRegistry
->bindPackage(
503 url
, OUString(), ucbContent
.getCommandEnvironment() ) );
504 const Reference
<deployment::XPackageTypeInfo
> xPackageType(
505 xPackage
->getPackageType() );
506 OSL_ASSERT( xPackageType
.is() );
507 if (xPackageType
.is())
508 mediaType
= xPackageType
->getMediaType();
510 catch (lang::IllegalArgumentException
& exc
) {
514 OSL_ENSURE( 0, ::rtl::OUStringToOString(
515 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
521 oslFileError
dp_linkFile( rtl_uString
* ustrFileURL
, rtl_uString
* ustrDestURL
)
523 oslFileError eRet
= osl_File_E_invalidError
;
525 OSL_ASSERT( ustrFileURL
);
526 OSL_ASSERT( ustrDestURL
);
528 /* convert source url to system path */
530 eRet
= osl_getSystemPathFromFileURL( ustrFileURL
, &aSrc
.pData
);
531 if( eRet
!= osl_File_E_None
)
533 rtl::OString aSrcPath
= rtl::OUStringToOString( aSrc
, osl_getThreadTextEncoding() );
535 /* convert destination url to system path */
537 osl_getSystemPathFromFileURL( ustrDestURL
, &aDest
.pData
);
538 if( eRet
!= osl_File_E_None
)
540 rtl::OString aDestPath
= rtl::OUStringToOString( aDest
, osl_getThreadTextEncoding() );
542 rtl::OString sName
= aSrcPath
;
543 sal_Int32 nEnd
= sName
.getLength()-1;
544 if (sName
.pData
->buffer
[nEnd
] == '/')
546 sal_Int32 nStart
= sName
.lastIndexOf( '/', nEnd
);
547 sName
= sName
.copy(nStart
, nEnd
- nStart
+ 1);
549 int nRet
= symlink(aSrcPath
.getStr(), (aDestPath
+ sName
).getStr());
550 eRet
= nRet
!= 0 ? osl_File_E_invalidError
: osl_File_E_None
;
555 //______________________________________________________________________________
556 OUString
PackageManagerImpl::insertToActivationLayer(
557 OUString
const & mediaType
, ::ucbhelper::Content
const & sourceContent_
,
558 OUString
const & title
, ActivePackages::Data
* dbData
)
560 ::ucbhelper::Content
sourceContent(sourceContent_
);
561 Reference
<XCommandEnvironment
> xCmdEnv(
562 sourceContent
.getCommandEnvironment() );
563 OUString destFolder
, tempEntry
;
564 if (::osl::File::createTempFile(
565 m_activePackages_expanded
.getLength() == 0
566 ? 0 : &m_activePackages_expanded
,
567 0, &tempEntry
) != ::osl::File::E_None
)
568 throw RuntimeException(
569 OUSTR("::osl::File::createTempFile() failed!"), 0 );
570 if (m_activePackages_expanded
.getLength() == 0) {
571 destFolder
= tempEntry
;
574 tempEntry
= tempEntry
.copy( tempEntry
.lastIndexOf( '/' ) + 1 );
575 // tweak user|share to macrofied url:
576 destFolder
= makeURL( m_activePackages
, tempEntry
);
578 destFolder
+= OUSTR("_");
580 // prepare activation folder:
581 ::ucbhelper::Content destFolderContent
;
582 create_folder( &destFolderContent
, destFolder
, xCmdEnv
);
584 // copy content into activation temp dir:
585 if (mediaType
.matchIgnoreAsciiCaseAsciiL(
586 RTL_CONSTASCII_STRINGPARAM(
587 "application/vnd.sun.star.package-bundle") ) ||
588 // xxx todo: more sophisticated parsing
589 mediaType
.matchIgnoreAsciiCaseAsciiL(
590 RTL_CONSTASCII_STRINGPARAM(
591 "application/vnd.sun.star.legacy-package-bundle") ))
594 ::rtl::OUStringBuffer buf
;
595 if (!sourceContent
.isFolder())
597 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.zip://") );
598 buf
.append( ::rtl::Uri::encode( sourceContent
.getURL(),
599 rtl_UriCharClassRegName
,
600 rtl_UriEncodeIgnoreEscapes
,
601 RTL_TEXTENCODING_UTF8
) );
604 buf
.append( sourceContent
.getURL() );
606 buf
.append( static_cast<sal_Unicode
>('/') );
607 sourceContent
= ::ucbhelper::Content( buf
.makeStringAndClear(), xCmdEnv
);
611 Any
request( (deployment::LinkException()) );
612 bool approve
= false, abort
= false;
613 interactContinuation( request
, task::XInteractionApprove::static_type(),
614 xCmdEnv
, &approve
, &abort
);
616 if (!abort
&& approve
)
622 (!sourceContent
.isFolder()) ||
623 (osl_File_E_None
!= dp_linkFile(sourceContent
.getURL().pData
, destFolderContent
.getURL().pData
))
626 throw RuntimeException( OUSTR("dp_linkFile() failed!"), 0 );
631 if (! destFolderContent
.transferContent(
632 sourceContent
, ::ucbhelper::InsertOperation_COPY
,
633 title
, NameClash::OVERWRITE
))
635 throw RuntimeException( OUSTR("UCB transferContent() failed!"), 0 );
640 dbData
->temporaryName
= tempEntry
;
641 dbData
->fileName
= title
;
642 dbData
->mediaType
= mediaType
;
646 //______________________________________________________________________________
647 void PackageManagerImpl::insertToActivationLayerDB(
648 OUString
const & id
, ActivePackages::Data
const & dbData
)
650 m_activePackagesDB
->put( id
, dbData
);
653 //______________________________________________________________________________
654 /* The function returns true if there is an extension with the same id already
655 installed which needs to be uninstalled, before the new extension can be installed.
657 bool PackageManagerImpl::checkUpdate(
658 Reference
<deployment::XPackage
> const & package
,
659 Reference
<XCommandEnvironment
> const & origCmdEnv
,
660 Reference
<XCommandEnvironment
> const & wrappedCmdEnv
)
662 OUString
id(dp_misc::getIdentifier(package
));
663 OUString
fn(package
->getName());
664 bool removeExisting
= false;
665 if (m_activePackagesDB
->has( id
, fn
))
667 // package already deployed, interact --force:
669 (deployment::VersionException(
670 getResourceString( RID_STR_PACKAGE_ALREADY_ADDED
) + id
,
671 static_cast<OWeakObject
*>(this), package
,
672 getDeployedPackage_( id
, fn
, origCmdEnv
) ) ) );
673 bool replace
= false, abort
= false;
674 if (! interactContinuation(
675 request
, task::XInteractionApprove::static_type(),
676 wrappedCmdEnv
, &replace
, &abort
)) {
677 OSL_ASSERT( !replace
&& !abort
);
678 throw deployment::DeploymentException(
679 getResourceString(RID_STR_ERROR_WHILE_ADDING
) + id
,
680 static_cast<OWeakObject
*>(this), request
);
682 if (abort
|| !replace
)
683 throw CommandFailedException(
684 getResourceString(RID_STR_PACKAGE_ALREADY_ADDED
) + id
,
685 static_cast<OWeakObject
*>(this), request
);
687 // remove clashing package before registering new version:
688 removeExisting
= true;
690 return removeExisting
;
692 //______________________________________________________________________________
693 // Notify the user when a new extension is to be installed. This is only the case
694 //when unopkg gui extension1 is used (used by system integration (double click on .oxt
695 // file etc.)). In case there is already this extension then the function returns
697 //ToDo: Function always returns true or throws an exception
698 bool PackageManagerImpl::checkInstall(
699 Reference
<deployment::XPackage
> const & package
,
700 Reference
<XCommandEnvironment
> const & cmdEnv
)
702 OUString
id(dp_misc::getIdentifier(package
));
703 if ( ! m_activePackagesDB
->has( id
, package
->getName() ))
706 deployment::InstallException(
707 OUSTR("Extension ") + id
+ OUSTR(" is about to be installed."),
708 static_cast<OWeakObject
*>(this), package
));
709 bool approve
= false, abort
= false;
710 if (! interactContinuation(
711 request
, task::XInteractionApprove::static_type(),
712 cmdEnv
, &approve
, &abort
))
714 OSL_ASSERT( !approve
&& !abort
);
715 throw deployment::DeploymentException(
716 getResourceString(RID_STR_ERROR_WHILE_ADDING
) + id
,
717 static_cast<OWeakObject
*>(this), request
);
719 if (abort
|| !approve
)
720 throw CommandFailedException(
721 getResourceString(RID_STR_ERROR_WHILE_ADDING
) + id
,
722 static_cast<OWeakObject
*>(this), request
);
729 //______________________________________________________________________________
730 Reference
<deployment::XPackage
> PackageManagerImpl::addPackage(
731 OUString
const & url
, OUString
const & mediaType_
,
732 Reference
<task::XAbortChannel
> const & xAbortChannel
,
733 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
734 throw (deployment::DeploymentException
, CommandFailedException
,
735 CommandAbortedException
, lang::IllegalArgumentException
,
742 if (m_context
== OUSTR("shared"))
743 message
= OUSTR("You need write permissions to install a shared extension!");
745 message
= OUSTR("You need write permissions to install this extension!");
746 throw deployment::DeploymentException(
747 message
, static_cast<OWeakObject
*>(this), Any() );
749 Reference
<XCommandEnvironment
> xCmdEnv
;
751 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
753 xCmdEnv
.set( xCmdEnv_
);
756 ::ucbhelper::Content sourceContent
;
757 create_ucb_content( &sourceContent
, url
, xCmdEnv
); // throws exc
758 const OUString
title(sourceContent
.getPropertyValue(
759 StrTitle::get() ).get
<OUString
>() );
760 const OUString
title_enc( ::rtl::Uri::encode(
761 title
, rtl_UriCharClassPchar
,
762 rtl_UriEncodeIgnoreEscapes
,
763 RTL_TEXTENCODING_UTF8
) );
766 OUString
mediaType(mediaType_
);
767 if (mediaType
.getLength() == 0)
768 mediaType
= detectMediaType( sourceContent
);
770 Reference
<deployment::XPackage
> xPackage
;
773 getResourceString(RID_STR_COPYING_PACKAGE
) + title
, xCmdEnv
);
774 if (m_activePackages
.getLength() == 0)
776 ::ucbhelper::Content docFolderContent
;
777 create_folder( &docFolderContent
, m_context
, xCmdEnv
);
778 // copy into document, first:
779 if (! docFolderContent
.transferContent(
780 sourceContent
, ::ucbhelper::InsertOperation_COPY
,
782 NameClash::ASK
/* xxx todo: ASK not needed? */))
783 throw RuntimeException(
784 OUSTR("UCB transferContent() failed!"), 0 );
786 ::ucbhelper::Content
docContent(
787 makeURL( m_context
, title_enc
), xCmdEnv
);
788 //TODO #i73136#: using title instead of id can lead to
789 // clashes, but the whole m_activePackages.getLength()==0
790 // case (i.e., document-relative deployment) currently does
792 docContent
.setPropertyValue(
793 OUSTR("MediaType"), Any(mediaType
) );
795 // xxx todo: obsolete in the future
797 docFolderContent
.executeCommand( OUSTR("flush"), Any() );
799 catch (UnsupportedCommandException
&) {
802 ActivePackages::Data dbData
;
803 destFolder
= insertToActivationLayer(
804 mediaType
, sourceContent
, title
, &dbData
);
807 // bind activation package:
808 //Because every extension will be unpacked in a folder, which was created with a unique name
809 //we will always have two different XPackage objects, even if the second extension is the same.
810 //Therefore bindPackage does not need a guard here.
811 xPackage
= m_xRegistry
->bindPackage(
812 makeURL( destFolder
, title_enc
), mediaType
, xCmdEnv
);
814 OSL_ASSERT( xPackage
.is() );
817 bool install
= false;
822 id
= dp_misc::getIdentifier( xPackage
);
823 //checkInstall throws an exception if the user denies the installation
824 checkInstall(xPackage
, xCmdEnv
);
825 //checkUpdate throws an exception if the user cancels the interaction.
826 //For example, he may be asked if he wants to replace the older version
827 //with the new version.
828 //checkUpdates must be called before checkPrerequisites
829 bool bAlreadyInstalled
= checkUpdate(
830 xPackage
, xCmdEnv_
, xCmdEnv
);
832 if (xPackage
->checkPrerequisites(xAbortChannel
, xCmdEnv
, bAlreadyInstalled
, m_context
))
834 //This guard is used to prevent that an extension is installed twice. Do not use it in other
836 //Imagine addPackage is called two times by different threads for the same extension quickly
838 //The second call would calculate "bAlreadyInstalled = false" if the first thread has not yet reached
839 //insertToActivationLayerDB.
840 ::osl::MutexGuard
g(m_addMutex
);
842 //Holds the database data of the old extension, in case we need to roll back.
843 ActivePackages::Data oldDbData
;
844 if (bAlreadyInstalled
)
846 // Remove extension which is already installed. It is not removed from disk, only
847 // the different contents are being unregisterd. We remember the databas information
848 // in case we need to roll back this operation.
849 // When the user canceled the operation (CommandAbortedException) than the package is still
851 // Do not guard the complete function with the getMutex
852 removePackage_(id
, xPackage
->getName(), xAbortChannel
,
853 xCmdEnv
, & oldDbData
);
856 const ::osl::MutexGuard
guard( getMutex() );
859 //throws CommandAbortedException if the user cancelled the installation.
860 xPackage
->registerPackage(xAbortChannel
, xCmdEnv
);
862 catch(CommandAbortedException
& )
863 { //ToDo: Interaction so that the gui can display an appropriate string.
864 //See also removePackage_
865 //User aborted installation, restore the previous situation.
866 //Use a private AbortChannel so the user cannot interrupt.
867 xPackage
->revokePackage(new AbortChannel(), xCmdEnv
);
868 if (bAlreadyInstalled
)
870 OUString instFolder
= makeURL( m_activePackages
, oldDbData
.temporaryName
)
872 Reference
<deployment::XPackage
> xOldPgk
= m_xRegistry
->bindPackage(
873 makeURL( instFolder
, oldDbData
.fileName
), oldDbData
.mediaType
, xCmdEnv
);
874 xOldPgk
->registerPackage(new AbortChannel(), xCmdEnv
);
875 insertToActivationLayerDB(dp_misc::getIdentifier( xOldPgk
), oldDbData
);
879 //access to the database must be guarded. See removePackage_
880 insertToActivationLayerDB(id
, dbData
);
885 deletePackageFromCache( xPackage
, destFolder
);
890 deletePackageFromCache( xPackage
, destFolder
);
896 catch (RuntimeException
&) {
899 catch (CommandFailedException
& exc
) {
900 logIntern( Any(exc
) );
903 catch (CommandAbortedException
& exc
) {
904 logIntern( Any(exc
) );
907 catch (deployment::DeploymentException
& exc
) {
908 logIntern( Any(exc
) );
911 catch (Exception
&) {
912 Any
exc( ::cppu::getCaughtException() );
914 throw deployment::DeploymentException(
915 getResourceString(RID_STR_ERROR_WHILE_ADDING
) + url
,
916 static_cast<OWeakObject
*>(this), exc
);
919 void PackageManagerImpl::deletePackageFromCache(
920 Reference
<deployment::XPackage
> const & xPackage
,
921 OUString
const & destFolder
)
923 try_dispose( xPackage
);
925 //we remove the package from the uno cache
926 //no service from the package may be loaded at this time!!!
927 erase_path( destFolder
, Reference
<XCommandEnvironment
>(),
928 false /* no throw: ignore errors */ );
929 //rm last character '_'
930 OUString url
= destFolder
.copy(0, destFolder
.getLength() - 1);
931 erase_path( url
, Reference
<XCommandEnvironment
>(),
932 false /* no throw: ignore errors */ );
935 //______________________________________________________________________________
936 void PackageManagerImpl::removePackage_(
937 OUString
const & id
, OUString
const & fileName
,
938 Reference
<task::XAbortChannel
> const & xAbortChannel
,
939 Reference
<XCommandEnvironment
> const & xCmdEnv
,
940 ActivePackages::Data
* out_dbData
)
942 Reference
<deployment::XPackage
> xPackage
;
945 const ::osl::MutexGuard
guard(getMutex());
946 xPackage
= getDeployedPackage_(id
, fileName
, xCmdEnv
);
947 m_activePackagesDB
->get(out_dbData
, id
, fileName
);
948 beans::Optional
< beans::Ambiguous
<sal_Bool
> > option(
949 xPackage
->isRegistered( Reference
<task::XAbortChannel
>(),
951 if (!option
.IsPresent
|| option
.Value
.IsAmbiguous
|| option
.Value
.Value
)
952 xPackage
->revokePackage( xAbortChannel
, xCmdEnv
);
953 m_activePackagesDB
->erase( id
, fileName
); // to be removed upon next start
955 catch (CommandAbortedException
&)
957 //ToDo: interaction, so that gui can show an appropriate string
958 //reregister the package
959 //Create our own XAbortChannel, so the user cannot interrupt the registration.
960 xPackage
->registerPackage(new AbortChannel(), xCmdEnv
);
964 try_dispose( xPackage
);
967 //______________________________________________________________________________
968 void PackageManagerImpl::removePackage(
969 OUString
const & id
, ::rtl::OUString
const & fileName
,
970 Reference
<task::XAbortChannel
> const & xAbortChannel
,
971 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
972 throw (deployment::DeploymentException
, CommandFailedException
,
973 CommandAbortedException
, lang::IllegalArgumentException
,
980 if (m_context
== OUSTR("shared"))
981 message
= OUSTR("You need write permissions in order to remove a shared extension!");
983 message
= OUSTR("You need write permissions in order to remove this extension!");
984 throw deployment::DeploymentException(
985 message
, static_cast<OWeakObject
*>(this), Any() );
988 Reference
<XCommandEnvironment
> xCmdEnv
;
990 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
992 xCmdEnv
.set( xCmdEnv_
);
995 removePackage_( id
, fileName
, xAbortChannel
, xCmdEnv
, NULL
);
998 catch (RuntimeException
&) {
1001 catch (lang::IllegalArgumentException
&) {
1004 catch (CommandFailedException
& exc
) {
1005 logIntern( Any(exc
) );
1008 catch (CommandAbortedException
& exc
) {
1009 logIntern( Any(exc
) );
1012 catch (deployment::DeploymentException
& exc
) {
1013 logIntern( Any(exc
) );
1016 catch (Exception
&) {
1017 Any
exc( ::cppu::getCaughtException() );
1019 throw deployment::DeploymentException(
1020 getResourceString(RID_STR_ERROR_WHILE_REMOVING
) + id
,
1021 static_cast<OWeakObject
*>(this), exc
);
1025 //______________________________________________________________________________
1026 OUString
PackageManagerImpl::getDeployPath( ActivePackages::Data
const & data
)
1028 ::rtl::OUStringBuffer buf
;
1029 buf
.append( data
.temporaryName
);
1030 buf
.appendAscii( RTL_CONSTASCII_STRINGPARAM("_/") );
1031 buf
.append( ::rtl::Uri::encode( data
.fileName
, rtl_UriCharClassPchar
,
1032 rtl_UriEncodeIgnoreEscapes
,
1033 RTL_TEXTENCODING_UTF8
) );
1034 return makeURL( m_activePackages
, buf
.makeStringAndClear() );
1037 //______________________________________________________________________________
1038 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage_(
1039 OUString
const & id
, OUString
const & fileName
,
1040 Reference
<XCommandEnvironment
> const & xCmdEnv
)
1042 ActivePackages::Data val
;
1043 if (m_activePackagesDB
->get( &val
, id
, fileName
))
1045 return getDeployedPackage_( id
, val
, xCmdEnv
, false );
1047 throw lang::IllegalArgumentException(
1048 getResourceString(RID_STR_NO_SUCH_PACKAGE
) + id
,
1049 static_cast<OWeakObject
*>(this), static_cast<sal_Int16
>(-1) );
1052 //______________________________________________________________________________
1053 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage_(
1054 OUString
const & id
, ActivePackages::Data
const & data
,
1055 Reference
<XCommandEnvironment
> const & xCmdEnv
, bool ignoreAlienPlatforms
)
1057 if (ignoreAlienPlatforms
)
1059 String type
, subType
;
1060 INetContentTypeParameterList params
;
1061 if (INetContentTypes::parse( data
.mediaType
, type
, subType
, ¶ms
))
1063 INetContentTypeParameter
const * param
= params
.find(
1064 ByteString("platform") );
1065 if (param
!= 0 && !platform_fits( param
->m_sValue
))
1066 throw lang::IllegalArgumentException(
1067 getResourceString(RID_STR_NO_SUCH_PACKAGE
) + id
,
1068 static_cast<OWeakObject
*>(this),
1069 static_cast<sal_Int16
>(-1) );
1072 return m_xRegistry
->bindPackage(
1073 getDeployPath( data
), data
.mediaType
, xCmdEnv
);
1076 //______________________________________________________________________________
1077 Sequence
< Reference
<deployment::XPackage
> >
1078 PackageManagerImpl::getDeployedPackages_(
1079 Reference
<XCommandEnvironment
> const & xCmdEnv
)
1081 ::std::vector
< Reference
<deployment::XPackage
> > packages
;
1082 ActivePackages::Entries
id2temp( m_activePackagesDB
->getEntries() );
1083 ActivePackages::Entries::const_iterator
iPos( id2temp
.begin() );
1084 ActivePackages::Entries::const_iterator
const iEnd( id2temp
.end() );
1085 for ( ; iPos
!= iEnd
; ++iPos
)
1089 getDeployedPackage_(
1090 iPos
->first
, iPos
->second
, xCmdEnv
,
1091 true /* xxx todo: think of GUI:
1092 ignore other platforms than the current one */ ) );
1094 catch (lang::IllegalArgumentException
& exc
) {
1096 (void) exc
; // avoid warnings
1097 OSL_ENSURE( 0, ::rtl::OUStringToOString(
1098 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
1100 catch (deployment::DeploymentException
& exc
) {
1102 (void) exc
; // avoid warnings
1103 OSL_ENSURE( 0, ::rtl::OUStringToOString(
1104 exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
1107 return comphelper::containerToSequence(packages
);
1110 //______________________________________________________________________________
1111 Reference
<deployment::XPackage
> PackageManagerImpl::getDeployedPackage(
1112 OUString
const & id
, ::rtl::OUString
const & fileName
,
1113 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1114 throw (deployment::DeploymentException
, CommandFailedException
,
1115 lang::IllegalArgumentException
, RuntimeException
)
1118 Reference
<XCommandEnvironment
> xCmdEnv
;
1119 if (m_xLogFile
.is())
1120 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1122 xCmdEnv
.set( xCmdEnv_
);
1125 const ::osl::MutexGuard
guard( getMutex() );
1126 return getDeployedPackage_( id
, fileName
, xCmdEnv
);
1128 catch (RuntimeException
&) {
1131 catch (CommandFailedException
& exc
) {
1132 logIntern( Any(exc
) );
1135 catch (lang::IllegalArgumentException
& exc
) {
1136 logIntern( Any(exc
) );
1139 catch (deployment::DeploymentException
& exc
) {
1140 logIntern( Any(exc
) );
1143 catch (Exception
&) {
1144 Any
exc( ::cppu::getCaughtException() );
1146 throw deployment::DeploymentException(
1147 // ought never occur...
1148 OUSTR("error while accessing deployed package: ") + id
,
1149 static_cast<OWeakObject
*>(this), exc
);
1153 //______________________________________________________________________________
1154 Sequence
< Reference
<deployment::XPackage
> >
1155 PackageManagerImpl::getDeployedPackages(
1156 Reference
<task::XAbortChannel
> const &,
1157 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1158 throw (deployment::DeploymentException
, CommandFailedException
,
1159 CommandAbortedException
, lang::IllegalArgumentException
,
1163 Reference
<XCommandEnvironment
> xCmdEnv
;
1164 if (m_xLogFile
.is())
1165 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1167 xCmdEnv
.set( xCmdEnv_
);
1170 const ::osl::MutexGuard
guard( getMutex() );
1171 return getDeployedPackages_( xCmdEnv
);
1173 catch (RuntimeException
&) {
1176 catch (CommandFailedException
& exc
) {
1177 logIntern( Any(exc
) );
1180 catch (CommandAbortedException
& exc
) {
1181 logIntern( Any(exc
) );
1184 catch (deployment::DeploymentException
& exc
) {
1185 logIntern( Any(exc
) );
1188 catch (Exception
&) {
1189 Any
exc( ::cppu::getCaughtException() );
1191 throw deployment::DeploymentException(
1192 // ought never occur...
1193 OUSTR("error while getting all deployed packages: ") + m_context
,
1194 static_cast<OWeakObject
*>(this), exc
);
1198 //______________________________________________________________________________
1199 void PackageManagerImpl::reinstallDeployedPackages(
1200 Reference
<task::XAbortChannel
> const & xAbortChannel
,
1201 Reference
<XCommandEnvironment
> const & xCmdEnv_
)
1202 throw (deployment::DeploymentException
,
1203 CommandFailedException
, CommandAbortedException
,
1204 lang::IllegalArgumentException
, RuntimeException
)
1210 if (m_context
== OUSTR("shared"))
1211 message
= OUSTR("You need write permissions in order to install shared extensions!");
1213 message
= OUSTR("You need write permissions in order to install extensions!");
1214 throw deployment::DeploymentException(
1215 message
, static_cast<OWeakObject
*>(this), Any() );
1218 if (office_is_running())
1219 throw RuntimeException(
1220 OUSTR("You must close any running Office process before "
1221 "reinstalling packages!"), static_cast<OWeakObject
*>(this) );
1223 Reference
<XCommandEnvironment
> xCmdEnv
;
1224 if (m_xLogFile
.is())
1225 xCmdEnv
.set( new CmdEnvWrapperImpl( xCmdEnv_
, m_xLogFile
) );
1227 xCmdEnv
.set( xCmdEnv_
);
1230 ProgressLevel
progress(
1231 xCmdEnv
, OUSTR("Reinstalling all deployed packages...") );
1233 try_dispose( m_xRegistry
);
1234 m_xRegistry
.clear();
1235 if (m_registryCache
.getLength() > 0)
1236 erase_path( m_registryCache
, xCmdEnv
);
1237 initRegistryBackends();
1238 Reference
<util::XUpdatable
> xUpdatable( m_xRegistry
, UNO_QUERY
);
1239 if (xUpdatable
.is())
1240 xUpdatable
->update();
1243 const ::osl::MutexGuard
guard( getMutex() );
1244 const Sequence
< Reference
<deployment::XPackage
> > packages(
1245 getDeployedPackages_( xCmdEnv
) );
1246 for ( sal_Int32 pos
= 0; pos
< packages
.getLength(); ++pos
)
1247 packages
[ pos
]->registerPackage( xAbortChannel
, xCmdEnv
);
1249 catch (RuntimeException
&) {
1252 catch (CommandFailedException
& exc
) {
1253 logIntern( Any(exc
) );
1256 catch (CommandAbortedException
& exc
) {
1257 logIntern( Any(exc
) );
1260 catch (deployment::DeploymentException
& exc
) {
1261 logIntern( Any(exc
) );
1264 catch (Exception
&) {
1265 Any
exc( ::cppu::getCaughtException() );
1267 throw deployment::DeploymentException(
1268 OUSTR("Error while reinstalling all previously deployed "
1269 "packages of context ") + m_context
,
1270 static_cast<OWeakObject
*>(this), exc
);
1275 ::sal_Bool SAL_CALL
PackageManagerImpl::isReadOnly( )
1276 throw (::com::sun::star::uno::RuntimeException
)
1281 //##############################################################################
1283 //______________________________________________________________________________
1284 PackageManagerImpl::CmdEnvWrapperImpl::~CmdEnvWrapperImpl()
1288 //______________________________________________________________________________
1289 PackageManagerImpl::CmdEnvWrapperImpl::CmdEnvWrapperImpl(
1290 Reference
<XCommandEnvironment
> const & xUserCmdEnv
,
1291 Reference
<XProgressHandler
> const & xLogFile
)
1292 : m_xLogFile( xLogFile
)
1294 if (xUserCmdEnv
.is()) {
1295 m_xUserProgress
.set( xUserCmdEnv
->getProgressHandler() );
1296 m_xUserInteractionHandler
.set( xUserCmdEnv
->getInteractionHandler() );
1300 // XCommandEnvironment
1301 //______________________________________________________________________________
1302 Reference
<task::XInteractionHandler
>
1303 PackageManagerImpl::CmdEnvWrapperImpl::getInteractionHandler()
1304 throw (RuntimeException
)
1306 return m_xUserInteractionHandler
;
1309 //______________________________________________________________________________
1310 Reference
<XProgressHandler
>
1311 PackageManagerImpl::CmdEnvWrapperImpl::getProgressHandler()
1312 throw (RuntimeException
)
1318 //______________________________________________________________________________
1319 void PackageManagerImpl::CmdEnvWrapperImpl::push( Any
const & Status
)
1320 throw (RuntimeException
)
1322 if (m_xLogFile
.is())
1323 m_xLogFile
->push( Status
);
1324 if (m_xUserProgress
.is())
1325 m_xUserProgress
->push( Status
);
1328 //______________________________________________________________________________
1329 void PackageManagerImpl::CmdEnvWrapperImpl::update( Any
const & Status
)
1330 throw (RuntimeException
)
1332 if (m_xLogFile
.is())
1333 m_xLogFile
->update( Status
);
1334 if (m_xUserProgress
.is())
1335 m_xUserProgress
->update( Status
);
1338 //______________________________________________________________________________
1339 void PackageManagerImpl::CmdEnvWrapperImpl::pop() throw (RuntimeException
)
1341 if (m_xLogFile
.is())
1343 if (m_xUserProgress
.is())
1344 m_xUserProgress
->pop();
1347 } // namespace dp_manager