
org.xwiki.extension.job.internal.AbstractExtensionPlanJob Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xwiki-commons-extension-api Show documentation
Show all versions of xwiki-commons-extension-api Show documentation
XWiki Commons - Extension - API
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.extension.job.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.xwiki.component.manager.ComponentLookupException;
import org.xwiki.extension.InstalledExtension;
import org.xwiki.extension.ResolveException;
import org.xwiki.extension.UninstallException;
import org.xwiki.extension.handler.ExtensionHandler;
import org.xwiki.extension.job.ExtensionRequest;
import org.xwiki.extension.job.plan.ExtensionPlanAction.Action;
import org.xwiki.extension.job.plan.ExtensionPlanNode;
import org.xwiki.extension.job.plan.internal.DefaultExtensionPlan;
import org.xwiki.extension.job.plan.internal.DefaultExtensionPlanAction;
import org.xwiki.extension.job.plan.internal.DefaultExtensionPlanNode;
import org.xwiki.extension.job.plan.internal.DefaultExtensionPlanTree;
import org.xwiki.job.Job;
import org.xwiki.job.event.status.JobStatus;
import org.xwiki.logging.marker.TranslationMarker;
/**
* Base class for plan calculation jobs.
*
* @param the type of the request
* @version $Id: e128cb3bdbe1710ea45ad49a45e04d1ff04c455b $
* @since 5.4RC1
*/
public abstract class AbstractExtensionPlanJob extends
AbstractExtensionJob>
{
protected static final TranslationMarker LOG_RESOLVE = new TranslationMarker("extension.log.job.plan.resolve");
protected static final TranslationMarker LOG_RESOLVE_NAMESPACE = new TranslationMarker(
"extension.log.job.plan.resolve.namespace");
protected static final TranslationMarker LOG_RESOLVEDEPENDENCY = new TranslationMarker(
"extension.log.job.plan.resolvedependency");
protected static final TranslationMarker LOG_RESOLVEDEPENDENCY_NAMESPACE = new TranslationMarker(
"extension.log.job.plan.resolvedependency.namespace");
/**
* Error message used in exception throw when trying to uninstall an extension which is not installed.
*/
private static final String EXCEPTION_NOTINSTALLED = "Extension [%s] is not installed";
/**
* Error message used in exception throw when trying to uninstall an extension which is not installed.
*/
private static final String EXCEPTION_NOTINSTALLEDNAMESPACE = EXCEPTION_NOTINSTALLED + " on namespace [%s]";
/**
* The install plan.
*/
protected DefaultExtensionPlanTree extensionTree = new DefaultExtensionPlanTree();
@Override
protected DefaultExtensionPlan createNewStatus(R request)
{
Job currentJob = this.jobContext.getCurrentJob();
JobStatus currentJobStatus = currentJob != null ? currentJob.getStatus() : null;
return new DefaultExtensionPlan(request, this.observationManager, this.loggerManager, this.extensionTree,
currentJobStatus);
}
/**
* @param extensionId the identifier of the extension to uninstall
* @param namespaces the namespaces from where to uninstall the extension
* @param parentBranch the children of the parent {@link DefaultExtensionPlanNode}
* @param withBackWard uninstall also the backward dependencies
* @throws UninstallException error when trying to uninstall provided extensions
*/
protected void uninstallExtension(String extensionId, Collection namespaces,
Collection parentBranch, boolean withBackWard) throws UninstallException
{
this.progressManager.pushLevelProgress(namespaces.size(), this);
try {
for (String namespace : namespaces) {
this.progressManager.startStep(this);
uninstallExtension(extensionId, namespace, parentBranch, withBackWard);
}
} finally {
this.progressManager.popLevelProgress(this);
}
}
/**
* @param extensionId the identifier of the extension to uninstall
* @param namespace the namespace from where to uninstall the extension
* @param parentBranch the children of the parent {@link DefaultExtensionPlanNode}
* @param withBackWard uninstall also the backward dependencies
* @throws UninstallException error when trying to uninstall provided extension
*/
protected void uninstallExtension(String extensionId, String namespace, Collection parentBranch,
boolean withBackWard) throws UninstallException
{
InstalledExtension installedExtension =
this.installedExtensionRepository.getInstalledExtension(extensionId, namespace);
if (installedExtension == null) {
throw new UninstallException(String.format(EXCEPTION_NOTINSTALLED, extensionId));
}
try {
uninstallExtension(installedExtension, namespace, parentBranch, withBackWard);
} catch (Exception e) {
throw new UninstallException("Failed to uninstall extension", e);
}
}
/**
* @param installedExtension the extension to uninstall
* @param namespaces the namespaces from where to uninstall the extension
* @param parentBranch the children of the parent {@link DefaultExtensionPlanNode}
* @param withBackWard uninstall also the backward dependencies
* @throws UninstallException error when trying to uninstall provided extension
*/
protected void uninstallExtension(InstalledExtension installedExtension, Collection namespaces,
Collection parentBranch, boolean withBackWard) throws UninstallException
{
this.progressManager.pushLevelProgress(namespaces.size(), this);
try {
for (String namespace : namespaces) {
this.progressManager.startStep(this);
uninstallExtension(installedExtension, namespace, parentBranch, withBackWard);
}
} finally {
this.progressManager.popLevelProgress(this);
}
}
/**
* @param extensions the installed extensions to uninstall
* @param namespace the namespaces from where to uninstall the extensions
* @param parentBranch the children of the parent {@link DefaultExtensionPlanNode}
* @param withBackWard uninstall also the backward dependencies
* @throws UninstallException error when trying to uninstall provided extensions
*/
protected void uninstallExtensions(Collection extensions, String namespace,
Collection parentBranch, boolean withBackWard) throws UninstallException
{
this.progressManager.pushLevelProgress(extensions.size(), this);
try {
for (InstalledExtension backardDependency : extensions) {
this.progressManager.startStep(this);
uninstallExtension(backardDependency, namespace, parentBranch, withBackWard);
}
} finally {
this.progressManager.popLevelProgress(this);
}
}
/**
* @param installedExtension the extension to uninstall
* @param namespace the namespace from where to uninstall the extension
* @param parentBranch the children of the parent {@link ExtensionPlanNode}
* @param withBackWard uninstall also the backward dependencies
* @throws UninstallException error when trying to uninstall provided extension
*/
protected void uninstallExtension(InstalledExtension installedExtension, String namespace,
Collection parentBranch, boolean withBackWard) throws UninstallException
{
if (namespace != null) {
if (installedExtension.getNamespaces() == null || !installedExtension.getNamespaces().contains(namespace)) {
throw new UninstallException(String.format(EXCEPTION_NOTINSTALLEDNAMESPACE, installedExtension,
namespace));
}
}
ExtensionHandler extensionHandler;
// Is type supported ?
try {
extensionHandler = this.componentManager.getInstance(ExtensionHandler.class, installedExtension.getType());
} catch (ComponentLookupException e) {
throw new UninstallException(String.format("Unsupported type [%s]", installedExtension.getType()), e);
}
// Is uninstalling the extension allowed ?
extensionHandler.checkUninstall(installedExtension, namespace, getRequest());
// Log progression
if (getRequest().isVerbose()) {
if (namespace != null) {
this.logger.info(LOG_RESOLVE_NAMESPACE, "Resolving extension [{}] from namespace [{}]",
installedExtension.getId(), namespace);
} else {
this.logger.info(LOG_RESOLVE, "Resolving extension [{}]", installedExtension.getId());
}
}
List children = new ArrayList();
// Uninstall backward dependencies
if (withBackWard) {
uninstallBackwardDependencies(installedExtension, namespace, children, withBackWard);
}
// Uninstall the extension
DefaultExtensionPlanAction action = new DefaultExtensionPlanAction(installedExtension,
Collections.singleton(installedExtension), Action.UNINSTALL, namespace, false);
parentBranch.add(new DefaultExtensionPlanNode(action, children, null));
}
/**
* @param installedExtension the extension to uninstall
* @param namespace the namespace from where to uninstall the extension
* @param parentBranch the children of the parent {@link ExtensionPlanNode}
* @param withBackWard uninstall also the backward dependencies
* @throws UninstallException error when trying to uninstall backward dependencies
* @throws ResolveException error when trying to resolve backward dependencies
*/
protected void uninstallBackwardDependencies(InstalledExtension installedExtension, String namespace,
List parentBranch, boolean withBackWard) throws UninstallException
{
try {
if (namespace != null) {
Collection installedExtensions =
this.installedExtensionRepository.getBackwardDependencies(installedExtension.getId().getId(),
namespace);
if (!installedExtensions.isEmpty()) {
uninstallExtensions(installedExtensions, namespace, parentBranch, withBackWard);
}
} else {
uninstallBackwardDependencies(installedExtension, parentBranch, withBackWard);
}
} catch (ResolveException e) {
throw new UninstallException("Failed to resolve backward dependencies of extension [" + installedExtension
+ "]", e);
}
}
/**
* @param installedExtension the extension to uninstall
* @param parentBranch the children of the parent {@link ExtensionPlanNode}
* @param withBackWard uninstall also the backward dependencies
* @throws UninstallException error when trying to uninstall backward dependencies
* @throws ResolveException error when trying to resolve backward dependencies
*/
protected void uninstallBackwardDependencies(InstalledExtension installedExtension,
List parentBranch, boolean withBackWard) throws UninstallException, ResolveException
{
Map> backwardDependencies =
this.installedExtensionRepository.getBackwardDependencies(installedExtension.getId());
this.progressManager.pushLevelProgress(backwardDependencies.size(), this);
try {
for (Map.Entry> entry : backwardDependencies.entrySet()) {
this.progressManager.startStep(this);
uninstallExtensions(entry.getValue(), entry.getKey(), parentBranch, withBackWard);
}
} finally {
this.progressManager.popLevelProgress(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy