/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
OUString mediaType( detectMediaType( sourceContent, false/* no throw */) ); if (!mediaType.isEmpty())
{
ActivePackages::Data dbData;
insertToActivationLayer(
Sequence<css::beans::NamedValue>(),mediaType, sourceContent,
title, &dbData );
insertToActivationLayerDB( title, dbData ); //TODO #i73136#: insertToActivationLayerDB needs id not // title, but the whole m_activePackages.getLength()==0 // case (i.e., document-relative deployment) currently // does not work, anyway.
}
}
}
} else
{ // user|share:
OSL_ASSERT( !m_activePackages.isEmpty() );
m_activePackages_expanded = expandUnoRcUrl( m_activePackages );
m_registrationData_expanded = expandUnoRcUrl(m_registrationData); if (!m_readOnly)
create_folder( nullptr, m_activePackages_expanded, xCmdEnv);
OUString dbName; if (m_context == "user")
dbName = m_activePackages_expanded + ".pmap"; else
{ // Create the extension data base in the user installation
create_folder( nullptr, m_registrationData_expanded, xCmdEnv);
dbName = m_registrationData_expanded + "/extensions.pmap";
} // The data base can always be written because it is always in the user installation
m_activePackagesDB.reset( new ActivePackages( dbName ) );
if (! m_readOnly && m_context != "bundled")
{ // clean up activation layer, scan for zombie temp dirs:
ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() );
//In case of shared extensions, new entries are regarded as //added extensions if there is no xxx.tmpremoved file. if (bShared)
{ if (std::find(removedEntries.begin(), removedEntries.end(), tempEntry) ==
removedEntries.end())
{ continue;
} else
{ //Make sure only the same user removes the extension, who //previously unregistered it. This is avoid races if multiple instances //of OOo are running which all have write access to the shared installation. //For example, a user removes the extension, but keeps OOo //running. Parts of the extension may still be loaded and used by OOo. //Therefore the extension is only deleted the next time the extension manager is //run after restarting OOo. While OOo is still running, another user starts OOo //which would deleted the extension files. If the same user starts another //instance of OOo then the lock file will prevent this.
OUString aUserName;
::osl::Security aSecurity;
aSecurity.getUserName( aUserName );
ucbhelper::Content remFileContent(
url + "removed", Reference<XCommandEnvironment>(), m_xComponentContext);
std::vector<sal_Int8> data = dp_misc::readFile(remFileContent);
std::string_view osData(reinterpret_cast<constchar*>(data.data()),
data.size());
OUString sData = OStringToOUString(
osData, RTL_TEXTENCODING_UTF8); if (sData != aUserName) continue;
}
} // temp entry not needed anymore:
erase_path( url + "_",
Reference<XCommandEnvironment>(), false/* no throw: ignore errors */ );
erase_path( url, Reference<XCommandEnvironment>(), false/* no throw: ignore errors */ ); //delete the xxx.tmpremoved file
erase_path(url + "removed",
Reference<XCommandEnvironment>(), false);
}
}
}
}
}
osl::FileBase::RC createDirectory(OUString const & url) { auto e = osl::Directory::create(url); if (e != osl::FileBase::E_NOENT) { return e;
}
INetURLObject o(url); if (!o.removeSegment()) { return osl::FileBase::E_INVAL; // anything but E_None/E_EXIST
}
e = createDirectory(o.GetMainURL(INetURLObject::DecodeMechanism::NONE)); if (e != osl::FileBase::E_None && e != osl::FileBase::E_EXIST) { return e;
} return osl::Directory::create(url);
}
::osl::FileBase::RC aErr = createDirectory( aDirURL ); if ( aErr == ::osl::FileBase::E_None ) returnfalse; // it will be writeable if ( aErr != ::osl::FileBase::E_EXIST ) returntrue; // some serious problem creating it
Reference<deployment::XPackageManager> PackageManagerImpl::create(
Reference<XComponentContext> const & xComponentContext,
OUString const & context )
{
rtl::Reference<PackageManagerImpl> that = new PackageManagerImpl(
xComponentContext, context );
OUString logFile, stamp; if ( context == "user" ) {
that->m_activePackages = "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages";
that->m_registrationData = "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE";
that->m_registryCache = "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/registry";
logFile = "$UNO_USER_PACKAGES_CACHE/log.txt"; //We use the extension .sys for the file because on Windows Vista a sys //(as well as exe and dll) file //will not be written in the VirtualStore. For example if the process has no //admin right once cannot write to the %programfiles% folder. However, when //virtualization is used, the file will be written into the VirtualStore and //it appears as if one could write to %programfiles%. When we test for write //access to the office/shared folder for shared extensions then this typically //fails because a normal user typically cannot write to this folder. However, //using virtualization it appears that he/she can. Then a shared extension can //be installed but is only visible for the user (because the extension is in //the virtual store).
stamp = "$UNO_USER_PACKAGES_CACHE";
} elseif ( context == "shared" ) {
that->m_activePackages = "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages";
that->m_registrationData = "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER";
that->m_registryCache = "vnd.sun.star.expand:$SHARED_EXTENSIONS_USER/registry";
logFile = "$SHARED_EXTENSIONS_USER/log.txt"; #if !HAVE_FEATURE_READONLY_INSTALLSET // The "shared" extensions are read-only when we have a // read-only installset.
stamp = "$UNO_SHARED_PACKAGES_CACHE"; #endif
} elseif ( context == "bundled" ) {
that->m_activePackages = "vnd.sun.star.expand:$BUNDLED_EXTENSIONS";
that->m_registrationData = "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER";
that->m_registryCache = "vnd.sun.star.expand:$BUNDLED_EXTENSIONS_USER/registry";
logFile = "$BUNDLED_EXTENSIONS_USER/log.txt"; //No stamp file. We assume that bundled is always readonly. It must not be //modified from ExtensionManager but only by the installer
} elseif ( context == "tmp" ) {
that->m_activePackages = "vnd.sun.star.expand:$TMP_EXTENSIONS/extensions";
that->m_registrationData = "vnd.sun.star.expand:$TMP_EXTENSIONS";
that->m_registryCache = "vnd.sun.star.expand:$TMP_EXTENSIONS/registry";
stamp = "$TMP_EXTENSIONS";
} elseif (context == "bak") {
that->m_activePackages = "vnd.sun.star.expand:$BAK_EXTENSIONS/extensions";
that->m_registrationData = "vnd.sun.star.expand:$BAK_EXTENSIONS";
that->m_registryCache = "vnd.sun.star.expand:$BAK_EXTENSIONS/registry";
stamp = "$BAK_EXTENSIONS";
}
void PackageManagerImpl::dispose()
{ //Do not call check here. We must not throw an exception here if the object //is being disposed or is already disposed. See com.sun.star.lang.XComponent
WeakComponentImplHelperBase::dispose();
}
void PackageManagerImpl::addEventListener(
Reference<lang::XEventListener> const & xListener )
{ //Do not call check here. We must not throw an exception here if the object //is being disposed or is already disposed. See com.sun.star.lang.XComponent
WeakComponentImplHelperBase::addEventListener( xListener );
}
void PackageManagerImpl::removeEventListener(
Reference<lang::XEventListener> const & xListener )
{ //Do not call check here. We must not throw an exception here if the object //is being disposed or is already disposed. See com.sun.star.lang.XComponent
WeakComponentImplHelperBase::removeEventListener( xListener );
}
// copy content into activation temp dir: if (mediaType.matchIgnoreAsciiCase("application/vnd.sun.star.package-bundle") || // xxx todo: more sophisticated parsing
mediaType.matchIgnoreAsciiCase("application/vnd.sun.star.legacy-package-bundle"))
{ // inflate content:
OUStringBuffer buf; if (!sourceContent.isFolder())
{
buf.append( "vnd.sun.star.zip://" );
buf.append( ::rtl::Uri::encode( sourceContent.getURL(),
rtl_UriCharClassRegName,
rtl_UriEncodeIgnoreEscapes,
RTL_TEXTENCODING_UTF8 ) );
} else
{ //Folder. No need to unzip, just copy
buf.append(sourceContent.getURL());
}
buf.append( '/' );
sourceContent = ::ucbhelper::Content(
buf.makeStringAndClear(), xCmdEnv, m_xComponentContext );
}
destFolderContent.transferContent(
sourceContent, ::ucbhelper::InsertOperation::Copy,
title, NameClash::OVERWRITE );
// write to DB: //bundled extensions should only be added by the synchronizeAddedExtensions //functions. Moreover, there is no "temporary folder" for bundled extensions.
OSL_ASSERT(!(m_context == "bundled"));
OUString sFolderUrl = makeURLAppendSysPathSegment(destFolderContent.getURL(), title);
DescriptionInfoset info =
dp_misc::getDescriptionInfoset(sFolderUrl);
dbData->temporaryName = tempEntry;
dbData->fileName = title;
dbData->mediaType = mediaType;
dbData->version = info.getVersion();
//No write the properties file next to the extension
ExtensionProperties props(sFolderUrl, properties, xCmdEnv, m_xComponentContext);
props.write(); return destFolder;
}
void PackageManagerImpl::insertToActivationLayerDB(
OUString const & id, ActivePackages::Data const & dbData )
{ //access to the database must be guarded. See removePackage const ::osl::MutexGuard guard( m_aMutex );
m_activePackagesDB->put( id, dbData );
}
/* The function returns true if there is an extension with the same id already installed which needs to be uninstalled, before the new extension can be installed.
*/ bool PackageManagerImpl::isInstalled(
Reference<deployment::XPackage> const & package)
{
OUString id(dp_misc::getIdentifier(package));
OUString fn(package->getName()); bool bInstalled = false; if (m_activePackagesDB->has( id, fn ))
{
bInstalled = true;
} return bInstalled;
}
/* The function adds an extension but does not register it!!! It may not do any user interaction. This is done in XExtensionManager::addExtension
*/
Reference<deployment::XPackage> PackageManagerImpl::addPackage(
OUString const & url,
css::uno::Sequence<css::beans::NamedValue> const & properties,
OUString const & mediaType_,
Reference<task::XAbortChannel> const & xAbortChannel,
Reference<XCommandEnvironment> const & xCmdEnv_ )
{
check(); if (m_readOnly)
{
OUString message; if (m_context == "shared")
message = "You need write permissions to install a shared extension!"; else
message = "You need write permissions to install this extension!"; throw deployment::DeploymentException(
message, static_cast<OWeakObject *>(this), Any() );
}
Reference<XCommandEnvironment> xCmdEnv; if (m_xLogFile.is())
xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); else
xCmdEnv.set( xCmdEnv_ );
OUString mediaType(mediaType_); if (mediaType.isEmpty())
mediaType = detectMediaType( sourceContent );
Reference<deployment::XPackage> xPackage; // copy file:
progressUpdate(
DpResId(RID_STR_COPYING_PACKAGE) + title, xCmdEnv ); if (m_activePackages.isEmpty())
{
::ucbhelper::Content docFolderContent;
create_folder( &docFolderContent, m_context, xCmdEnv ); // copy into document, first:
docFolderContent.transferContent(
sourceContent, ::ucbhelper::InsertOperation::Copy,
OUString(),
NameClash::ASK /* xxx todo: ASK not needed? */); // set media-type:
::ucbhelper::Content docContent(
makeURL( m_context, title_enc ), xCmdEnv, m_xComponentContext ); //TODO #i73136#: using title instead of id can lead to // clashes, but the whole m_activePackages.getLength()==0 // case (i.e., document-relative deployment) currently does // not work, anyway.
docContent.setPropertyValue(u"MediaType"_ustr, Any(mediaType) );
// bind activation package: //Because every shared/user extension will be unpacked in a folder, //which was created with a unique name we will always have two different //XPackage objects, even if the second extension is the same. //Therefore bindPackage does not need a guard here.
xPackage = m_xRegistry->bindPackage(
makeURL( destFolder, title_enc ), mediaType, false, OUString(), xCmdEnv );
OSL_ASSERT( xPackage.is() ); if (xPackage.is())
{ bool install = false; try
{
OUString const id = dp_misc::getIdentifier( xPackage );
std::unique_lock g(m_addMutex); if (isInstalled(xPackage))
{ //Do not guard the complete function with the getMutex
removePackage(id, xPackage->getName(), xAbortChannel,
xCmdEnv);
}
install = true;
insertToActivationLayerDB(id, dbData);
} catch (...)
{
deletePackageFromCache( xPackage, destFolder ); throw;
} if (!install)
{
deletePackageFromCache( xPackage, destFolder );
} //ToDo: We should notify only if the extension is registered
fireModified();
} return xPackage;
} catch (const RuntimeException &) { throw;
} catch (const CommandFailedException & exc) {
logIntern( Any(exc) ); throw;
} catch (const CommandAbortedException & exc) {
logIntern( Any(exc) ); throw;
} catch (const deployment::DeploymentException & exc) {
logIntern( Any(exc) ); throw;
} catch (const Exception &) {
Any exc( ::cppu::getCaughtException() );
logIntern( exc ); throw deployment::DeploymentException(
DpResId(RID_STR_ERROR_WHILE_ADDING) + url, static_cast<OWeakObject *>(this), exc );
}
} void PackageManagerImpl::deletePackageFromCache(
Reference<deployment::XPackage> const & xPackage,
OUString const & destFolder)
{
try_dispose( xPackage );
//we remove the package from the uno cache //no service from the package may be loaded at this time!!!
erase_path( destFolder, Reference<XCommandEnvironment>(), false/* no throw: ignore errors */ ); //rm last character '_'
OUString url = destFolder.copy(0, destFolder.getLength() - 1);
erase_path( url, Reference<XCommandEnvironment>(), false/* no throw: ignore errors */ );
Reference<XCommandEnvironment> xCmdEnv; if (m_xLogFile.is())
xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); else
xCmdEnv.set( xCmdEnv_ );
try {
Reference<deployment::XPackage> xPackage;
{ const ::osl::MutexGuard guard(m_aMutex); //Check if this extension exist and throw an IllegalArgumentException //if it does not //If the files of the extension are already removed, or there is a //different extension at the same place, for example after updating the //extension, then the returned object is that which uses the database data.
xPackage = getDeployedPackage_(id, fileName, xCmdEnv );
//Because the extension is only removed the next time the extension //manager runs after restarting OOo, we need to indicate that a //shared extension was "deleted". When a user starts OOo, then it //will check if something changed in the shared repository. Based on //the flag file it will then recognize, that the extension was //deleted and can then update the extension database of the shared //extensions in the user installation. if ( xPackage.is() && !m_readOnly && !xPackage->isRemoved() && (m_context == "shared"))
{
ActivePackages::Data val;
m_activePackagesDB->get( & val, id, fileName);
OSL_ASSERT(!val.temporaryName.isEmpty());
OUString url(makeURL(m_activePackages_expanded,
val.temporaryName + "removed"));
::ucbhelper::Content contentRemoved(url, xCmdEnv, m_xComponentContext);
OUString aUserName;
::osl::Security aSecurity;
aSecurity.getUserName( aUserName );
OString stamp = OUStringToOString(aUserName, RTL_TEXTENCODING_UTF8);
Reference<css::io::XInputStream> xData(
::xmlscript::createInputStream( reinterpret_cast<sal_Int8 const *>(stamp.getStr()),
stamp.getLength() ) );
contentRemoved.writeStream( xData, true/* replace existing */ );
}
m_activePackagesDB->erase( id, fileName ); // to be removed upon next start //remove any cached data hold by the backend
m_xRegistry->packageRemoved(xPackage->getURL(), xPackage->getPackageType()->getMediaType());
}
try_dispose( xPackage );
//ToDo: the function must not call registerPackage, do this in //XExtensionManager.reinstallDeployedExtensions void PackageManagerImpl::reinstallDeployedPackages(
sal_Bool force, Reference<task::XAbortChannel> const & /*xAbortChannel*/,
Reference<XCommandEnvironment> const & xCmdEnv_ )
{
check(); if (!force && office_is_running()) throw RuntimeException(
u"You must close any running Office process before reinstalling packages!"_ustr, static_cast<OWeakObject *>(this) );
Reference<XCommandEnvironment> xCmdEnv; if (m_xLogFile.is())
xCmdEnv.set( new CmdEnvWrapperImpl( xCmdEnv_, m_xLogFile ) ); else
xCmdEnv.set( xCmdEnv_ );
try {
ProgressLevel progress(
xCmdEnv, u"Reinstalling all deployed packages..."_ustr );
try_dispose( m_xRegistry );
m_xRegistry.clear(); if (!m_registryCache.isEmpty())
erase_path( m_registryCache, xCmdEnv );
initRegistryBackends();
Reference<util::XUpdatable> xUpdatable( m_xRegistry, UNO_QUERY ); if (xUpdatable.is())
xUpdatable->update();
//find all which are in the extension data base but which //are removed already.
OSL_ASSERT(!(m_context == "user")); bool bModified = false;
ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() );
bool bShared = (m_context == "shared");
for (autoconst& elem : id2temp)
{ try
{ //Get the URL to the extensions folder, first make the url for the //shared repository including the temporary name
OUString url = makeURL(m_activePackages, elem.second.temporaryName); if (bShared)
url = makeURLAppendSysPathSegment( Concat2View(url + "_"), elem.second.fileName);
bool bRemoved = false; //Check if the URL to the extension is still the same
::ucbhelper::Content contentExtension;
//The folder is in the extension database, but it can still be deleted. //look for the xxx.tmpremoved file //There can also be the case that a different extension was installed //in a "temp" folder with name that is already used. if (!bRemoved && bShared)
{
::ucbhelper::Content contentRemoved;
if (!bRemoved)
{ //There may be another extensions at the same place
dp_misc::DescriptionInfoset infoset =
dp_misc::getDescriptionInfoset(url);
OSL_ENSURE(infoset.hasDescription() && infoset.getIdentifier(), "Extension Manager: bundled and shared extensions " "must have an identifier and a version"); if (infoset.hasDescription() &&
infoset.getIdentifier() &&
( elem.first != *(infoset.getIdentifier())
|| elem.second.version != infoset.getVersion()))
{
bRemoved = true;
}
} if (bRemoved)
{
Reference<deployment::XPackage> xPackage = m_xRegistry->bindPackage(
url, elem.second.mediaType, true, elem.first, xCmdEnv );
OSL_ASSERT(xPackage.is()); //Even if the files are removed, we must get the object.
xPackage->revokePackage(true, xAbortChannel, xCmdEnv);
removePackage(xPackage->getIdentifier().Value, xPackage->getName(),
xAbortChannel, xCmdEnv);
bModified = true;
}
} catch( const uno::Exception & )
{
TOOLS_WARN_EXCEPTION("desktop.deployment", "");
}
} return bModified;
}
ActivePackages::Entries id2temp( m_activePackagesDB->getEntries() ); //check if the folder exist at all. The shared extension folder //may not exist for a normal user. bool bOk=true; try
{
bOk = create_ucb_content(
nullptr, m_activePackages_expanded, Reference<css::ucb::XCommandEnvironment>(), false);
} catch (const css::ucb::ContentCreationException&)
{
bOk = false;
}
while (xResultSet->next())
{ try
{
OUString title(
Reference<sdbc::XRow>(
xResultSet, UNO_QUERY_THROW )->getString(
1 /* Title */ ) ); //The temporary folders of user and shared have an '_' at then end. //But the name in ActivePackages.temporaryName is saved without.
OUString title2 = title; bool bShared = (m_context == "shared"); if (bShared)
{
OSL_ASSERT(title2.endsWith("_"));
title2 = title2.copy(0, title2.getLength() -1);
}
OUString titleEncoded = ::rtl::Uri::encode(
title2, rtl_UriCharClassPchar,
rtl_UriEncodeIgnoreEscapes,
RTL_TEXTENCODING_UTF8);
//It is sufficient to check for the folder name, because when the administrator //installed the extension it was already checked if there is one with the //same identifier. const MatchTempDir match(titleEncoded); if (std::none_of( id2temp.begin(), id2temp.end(), match ))
{
// The folder was not found in the data base, so it must be // an added extension
OUString url(m_activePackages_expanded + "/" + titleEncoded);
OUString sExtFolder; if (bShared) //that is, shared
{ //Check if the extension was not "deleted" already which is indicated //by a xxx.tmpremoved file
::ucbhelper::Content contentRemoved; if (create_ucb_content(&contentRemoved, url + "removed",
Reference<XCommandEnvironment>(), false)) continue;
sExtFolder = getExtensionFolder(
m_activePackages_expanded + "/" + titleEncoded + "_",
xCmdEnv, m_xComponentContext);
url = makeURLAppendSysPathSegment(m_activePackages_expanded, title);
url = makeURLAppendSysPathSegment(url, sExtFolder);
}
Reference<deployment::XPackage> xPackage = m_xRegistry->bindPackage(
url, OUString(), false, OUString(), xCmdEnv ); if (xPackage.is())
{
OUString id = dp_misc::getIdentifier( xPackage );
//Prepare the database entry
ActivePackages::Data dbData;
dbData.temporaryName = titleEncoded; if (bShared)
dbData.fileName = sExtFolder; else
dbData.fileName = title;
dbData.mediaType = xPackage->getPackageType()->getMediaType();
dbData.version = xPackage->getVersion();
SAL_WARN_IF(
dbData.version.isEmpty(), "desktop.deployment", "bundled/shared extension " << id << " at <" << url
<< "> has no explicit version");
//We provide a special command environment that will prevent //showing a license if simple-license/@accept-by = "admin" //It will also prevent showing the license for bundled extensions //which is not supported.
OSL_ASSERT(!(m_context == "user"));
// shall the license be suppressed?
DescriptionInfoset info =
dp_misc::getDescriptionInfoset(url);
::std::optional<dp_misc::SimpleLicenseAttributes>
attr = info.getSimpleLicenseAttributes();
ExtensionProperties props(url, xCmdEnv, m_xComponentContext); bool bNoLicense = false; if (attr && attr->suppressIfRequired && props.isSuppressedLicense())
bNoLicense = true;
Reference<ucb::XCommandEnvironment> licCmdEnv( new LicenseCommandEnv(xCmdEnv->getInteractionHandler(),
bNoLicense, m_context));
sal_Int32 failedPrereq = xPackage->checkPrerequisites(
xAbortChannel, licCmdEnv, false); //Remember that this failed. For example, the user //could have declined the license. Then the next time the //extension folder is investigated we do not want to //try to install the extension again.
dbData.failedPrerequisites = OUString::number(failedPrereq);
insertToActivationLayerDB(id, dbData);
bModified = true;
}
}
} catch (const uno::Exception &)
{ // Looks like exceptions being caught here is not an uncommon case.
TOOLS_WARN_EXCEPTION("desktop.deployment", "");
}
} return bModified;
}
for (autoconst& elem : id2temp)
{ //Get the database entry
ActivePackages::Data const & dbData = elem.second;
sal_Int32 failedPrereq = dbData.failedPrerequisites.toInt32(); //If the installation failed for other reason then the license then we //ignore it. if (failedPrereq ^ deployment::Prerequisites::LICENSE) continue;
//Prepare the URL to the extension
OUString url = makeURL(m_activePackages, elem.second.temporaryName); if (bShared)
url = makeURLAppendSysPathSegment( Concat2View(url + "_"), elem.second.fileName);
Reference<deployment::XPackage> p = m_xRegistry->bindPackage(
url, OUString(), false, OUString(), xCmdEnv );
sal_Int32 PackageManagerImpl::checkPrerequisites(
css::uno::Reference<css::deployment::XPackage> const & extension,
css::uno::Reference<css::task::XAbortChannel> const & xAbortChannel,
css::uno::Reference<css::ucb::XCommandEnvironment> const & xCmdEnv )
{ try
{ if (!extension.is()) return 0; if (m_context != extension->getRepositoryName()) throw lang::IllegalArgumentException(
u"PackageManagerImpl::checkPrerequisites: extension is not from this repository."_ustr,
nullptr, 0);
ActivePackages::Data dbData;
OUString id = dp_misc::getIdentifier(extension); if (!m_activePackagesDB->get( &dbData, id, OUString()))
{ throw lang::IllegalArgumentException(
u"PackageManagerImpl::checkPrerequisites: unknown extension"_ustr,
nullptr, 0);
} //If the license was already displayed, then do not show it again
Reference<ucb::XCommandEnvironment> _xCmdEnv = xCmdEnv;
sal_Int32 prereq = dbData.failedPrerequisites.toInt32(); if ( !(prereq & deployment::Prerequisites::LICENSE))
_xCmdEnv = new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler());
void PackageManagerImpl::CmdEnvWrapperImpl::push( Any const & Status )
{ if (m_xLogFile.is())
m_xLogFile->push( Status ); if (m_xUserProgress.is())
m_xUserProgress->push( Status );
}
void PackageManagerImpl::CmdEnvWrapperImpl::update( Any const & Status )
{ if (m_xLogFile.is())
m_xLogFile->update( Status ); if (m_xUserProgress.is())
m_xUserProgress->update( Status );
}
void PackageManagerImpl::CmdEnvWrapperImpl::pop()
{ if (m_xLogFile.is())
m_xLogFile->pop(); if (m_xUserProgress.is())
m_xUserProgress->pop();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.