mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 00:45:44 +01:00
implemented optional dependencies
Plugin authors could now define optional dependencies to other plugins in their pom. Extensions which are using classes from optional dependencies must specify this with the "requires" attribute of the extension annotation. Extensions with "requires" attribute are not installed if one of the specified plugins, is not installed.
This commit is contained in:
@@ -99,7 +99,7 @@ public class DefaultPluginLoader implements PluginLoader
|
||||
|
||||
modules = getInstalled(parent, context, PATH_MODULECONFIG);
|
||||
|
||||
collector = new ExtensionCollector(Iterables.concat(modules, unwrap()));
|
||||
collector = new ExtensionCollector(parent, modules, installedPlugins);
|
||||
extensionProcessor = new DefaultExtensionProcessor(collector);
|
||||
}
|
||||
catch (IOException | JAXBException ex)
|
||||
@@ -170,19 +170,6 @@ public class DefaultPluginLoader implements PluginLoader
|
||||
return uberWebResourceLoader;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Iterable<InstalledPluginDescriptor> unwrap()
|
||||
{
|
||||
return PluginsInternal.unwrap(installedPlugins);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -98,8 +98,8 @@ public final class ExplodedSmp implements Comparable<ExplodedSmp>
|
||||
{
|
||||
int result;
|
||||
|
||||
Set<String> depends = plugin.getDependencies();
|
||||
Set<String> odepends = o.plugin.getDependencies();
|
||||
Set<String> depends = plugin.getDependenciesInclusiveOptionals();
|
||||
Set<String> odepends = o.plugin.getDependenciesInclusiveOptionals();
|
||||
|
||||
if (depends.isEmpty() && odepends.isEmpty())
|
||||
{
|
||||
|
||||
@@ -39,6 +39,8 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
@@ -47,6 +49,7 @@ import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -56,23 +59,33 @@ import java.util.Set;
|
||||
public final class ExtensionCollector
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param modules
|
||||
*/
|
||||
ExtensionCollector(Iterable<ScmModule> modules)
|
||||
{
|
||||
for (ScmModule module : modules)
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ExtensionCollector.class);
|
||||
|
||||
private final Set<String> pluginIndex;
|
||||
|
||||
public ExtensionCollector(ClassLoader moduleClassLoader, Set<ScmModule> modules, Set<InstalledPlugin> installedPlugins) {
|
||||
this.pluginIndex = createPluginIndex(installedPlugins);
|
||||
|
||||
for (ScmModule module : modules) {
|
||||
collectRootElements(module);
|
||||
}
|
||||
|
||||
for (ScmModule module : modules)
|
||||
{
|
||||
collectExtensions(module);
|
||||
for (ScmModule plugin : PluginsInternal.unwrap(installedPlugins)) {
|
||||
collectRootElements(plugin);
|
||||
}
|
||||
|
||||
for (ScmModule module : modules) {
|
||||
collectExtensions(moduleClassLoader, module);
|
||||
}
|
||||
|
||||
for (InstalledPlugin plugin : installedPlugins) {
|
||||
collectExtensions(plugin.getClassLoader(), plugin.getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> createPluginIndex(Set<InstalledPlugin> installedPlugins) {
|
||||
return installedPlugins.stream()
|
||||
.map(p -> p.getDescriptor().getInformation().getName())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
@@ -245,20 +258,35 @@ public final class ExtensionCollector
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param module
|
||||
*/
|
||||
private void collectExtensions(ScmModule module)
|
||||
{
|
||||
for (Class extension : module.getExtensions())
|
||||
{
|
||||
appendExtension(extension);
|
||||
private void collectExtensions(ClassLoader defaultClassLoader, ScmModule module) {
|
||||
for (ExtensionElement extension : module.getExtensions()) {
|
||||
if (isRequirementFulfilled(extension)) {
|
||||
Class<?> extensionClass = loadExtension(defaultClassLoader, extension);
|
||||
appendExtension(extensionClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> loadExtension(ClassLoader classLoader, ExtensionElement extension) {
|
||||
try {
|
||||
return classLoader.loadClass(extension.getClazz());
|
||||
} catch (ClassNotFoundException ex) {
|
||||
throw new RuntimeException("failed to load clazz", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRequirementFulfilled(ExtensionElement extension) {
|
||||
if (extension.getRequires() != null) {
|
||||
for (String requiredPlugin : extension.getRequires()) {
|
||||
if (!pluginIndex.contains(requiredPlugin)) {
|
||||
LOG.debug("skip loading of extension {}, because the required plugin {} is not installed", extension.getClazz(), requiredPlugin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -189,7 +189,7 @@ public final class PluginProcessor
|
||||
|
||||
PluginTree pluginTree = new PluginTree(smps);
|
||||
|
||||
logger.trace("build plugin tree: {}", pluginTree);
|
||||
logger.info("install plugin tree:\n{}", pluginTree);
|
||||
|
||||
List<PluginNode> rootNodes = pluginTree.getRootNodes();
|
||||
|
||||
|
||||
@@ -35,15 +35,13 @@ package sonia.scm.plugin;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Ordering;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -104,9 +102,7 @@ public final class PluginTree
|
||||
|
||||
if ((condition == null) || condition.isSupported())
|
||||
{
|
||||
Set<String> dependencies = plugin.getDependencies();
|
||||
|
||||
if ((dependencies == null) || dependencies.isEmpty())
|
||||
if (plugin.getDependencies().isEmpty() && plugin.getOptionalDependencies().isEmpty())
|
||||
{
|
||||
rootNodes.add(new PluginNode(smp));
|
||||
}
|
||||
@@ -170,6 +166,20 @@ public final class PluginTree
|
||||
//J+
|
||||
}
|
||||
}
|
||||
|
||||
boolean rootNode = smp.getPlugin().getDependencies().isEmpty();
|
||||
for (String dependency : smp.getPlugin().getOptionalDependencies()) {
|
||||
if (appendNode(rootNodes, child, dependency)) {
|
||||
rootNode = false;
|
||||
} else {
|
||||
logger.info("optional dependency {} of {} is not installed", dependency, child.getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (rootNode) {
|
||||
logger.info("could not find optional dependencies of {}, append it as root node", child.getId());
|
||||
rootNodes.add(new PluginNode(smp));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,7 +222,18 @@ public final class PluginTree
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "plugin tree: " + rootNodes.toString();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (PluginNode node : rootNodes) {
|
||||
append(buffer, "", node);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void append(StringBuilder buffer, String indent, PluginNode node) {
|
||||
buffer.append(indent).append("+- ").append(node.getId()).append("\n");
|
||||
for (PluginNode child : node.getChildren()) {
|
||||
append(buffer, indent + " ", child);
|
||||
}
|
||||
}
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user