From 6f16cc47bc2d2c9ba0fc51c043cc53857cf1c40a Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sun, 10 Jan 2021 00:42:01 +0200 Subject: [PATCH] Fix for #394 (#417) --- .../java/org/pf4j/DependencyResolver.java | 10 +-- .../java/org/pf4j/PluginDependencyTest.java | 71 ++++++++++++++++++- .../test/java/org/pf4j/test/PluginZip.java | 14 ++++ 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/DependencyResolver.java b/pf4j/src/main/java/org/pf4j/DependencyResolver.java index 866eb93..7960a46 100644 --- a/pf4j/src/main/java/org/pf4j/DependencyResolver.java +++ b/pf4j/src/main/java/org/pf4j/DependencyResolver.java @@ -88,7 +88,7 @@ public class DependencyResolver { String pluginId = plugin.getPluginId(); String existingVersion = plugin.getVersion(); - List dependents = new ArrayList<>(getDependents(pluginId)); + List dependents = getDependents(pluginId); while (!dependents.isEmpty()) { String dependentId = dependents.remove(0); PluginDescriptor dependent = pluginByIds.get(dependentId); @@ -107,22 +107,22 @@ public class DependencyResolver { * Retrieves the plugins ids that the given plugin id directly depends on. * * @param pluginId the unique plugin identifier, specified in its metadata - * @return + * @return an immutable list of dependencies (new list for each call) */ public List getDependencies(String pluginId) { checkResolved(); - return dependenciesGraph.getNeighbors(pluginId); + return new ArrayList<>(dependenciesGraph.getNeighbors(pluginId)); } /** * Retrieves the plugins ids that the given content is a direct dependency of. * * @param pluginId the unique plugin identifier, specified in its metadata - * @return + * @return an immutable list of dependents (new list for each call) */ public List getDependents(String pluginId) { checkResolved(); - return dependentsGraph.getNeighbors(pluginId); + return new ArrayList<>(dependentsGraph.getNeighbors(pluginId)); } /** diff --git a/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java b/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java index c605d23..662c287 100644 --- a/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java +++ b/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java @@ -15,8 +15,12 @@ */ package org.pf4j; - +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.pf4j.test.PluginZip; + +import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -27,6 +31,16 @@ import static org.junit.jupiter.api.Assertions.assertTrue; */ public class PluginDependencyTest { + private DefaultPluginManager pluginManager; + + @TempDir + Path pluginsPath; + + @BeforeEach + public void setUp() { + pluginManager = new DefaultPluginManager(pluginsPath); + } + /** * Test of getPluginId method, of class PluginDependency. */ @@ -77,4 +91,59 @@ public class PluginDependencyTest { assertEquals("PluginDependency [pluginId=test, pluginVersionSupport=1.0, optional=true]", instance.toString()); } + @Test + public void dependentStop() throws Exception { + // B depends on A + PluginZip pluginA = new PluginZip.Builder(pluginsPath.resolve("A-plugin-1.2.3.zip"), "plugin.a") + .pluginVersion("1.2.3").build(); + + PluginZip pluginB = new PluginZip.Builder(pluginsPath.resolve("B-plugin-1.2.3.zip"), "plugin.b") + .pluginDependencies("plugin.a") + .pluginVersion("1.2.3").build(); + + pluginManager.loadPlugins(); + assertEquals(2, pluginManager.getPlugins().size()); + + pluginManager.startPlugins(); + assertEquals(2, pluginManager.getStartedPlugins().size()); + + // stop A, both A and B should be stopped + pluginManager.stopPlugin("plugin.a"); + assertEquals(0, pluginManager.getStartedPlugins().size()); + + // start all again + pluginManager.startPlugins(); + assertEquals(2, pluginManager.getStartedPlugins().size()); + + // dependent info should be kept. #394 + pluginManager.stopPlugin("plugin.a"); + assertEquals(0, pluginManager.getStartedPlugins().size()); + } + + @Test + public void dependentUnload() throws Exception { + // B depends on A + PluginZip pluginA = new PluginZip.Builder(pluginsPath.resolve("A-plugin-1.2.3.zip"), "plugin.a") + .pluginVersion("1.2.3").build(); + + PluginZip pluginB = new PluginZip.Builder(pluginsPath.resolve("B-plugin-1.2.3.zip"), "plugin.b") + .pluginDependencies("plugin.a") + .pluginVersion("1.2.3").build(); + + pluginManager.loadPlugins(); + assertEquals(2, pluginManager.getPlugins().size()); + + pluginManager.startPlugins(); + assertEquals(2, pluginManager.getStartedPlugins().size()); + + // stop A, both A and B should be stopped + pluginManager.stopPlugin("plugin.a"); + assertEquals(0, pluginManager.getStartedPlugins().size()); + + // unload A, both A and B should be unloaded + pluginManager.unloadPlugin("plugin.a"); + assertEquals(0, pluginManager.getResolvedPlugins().size()); + assertEquals(0, pluginManager.getPlugins().size()); + } + } diff --git a/pf4j/src/test/java/org/pf4j/test/PluginZip.java b/pf4j/src/test/java/org/pf4j/test/PluginZip.java index 5dd2291..4b9a0c9 100644 --- a/pf4j/src/test/java/org/pf4j/test/PluginZip.java +++ b/pf4j/src/test/java/org/pf4j/test/PluginZip.java @@ -39,12 +39,14 @@ public class PluginZip { private final String pluginId; private final String pluginClass; private final String pluginVersion; + private final String pluginDependencies; protected PluginZip(Builder builder) { this.path = builder.path; this.pluginId = builder.pluginId; this.pluginClass = builder.pluginClass; this.pluginVersion = builder.pluginVersion; + this.pluginDependencies = builder.pluginDependencies; } public Path path() { @@ -67,6 +69,8 @@ public class PluginZip { return pluginVersion; } + public String pluginDependencies() { return pluginDependencies; } + public Path unzippedPath() { Path path = path(); String fileName = path.getFileName().toString(); @@ -88,6 +92,7 @@ public class PluginZip { private String pluginClass; private String pluginVersion; + private String pluginDependencies; private Map properties = new LinkedHashMap<>(); private Map files = new LinkedHashMap<>(); @@ -108,6 +113,12 @@ public class PluginZip { return this; } + public Builder pluginDependencies(String pluginDependencies) { + this.pluginDependencies = pluginDependencies; + + return this; + } + /** * Add extra properties to the {@code properties} file. * As possible attribute name please see {@link PropertiesPluginDescriptorFinder}. @@ -162,6 +173,9 @@ public class PluginZip { Map map = new LinkedHashMap<>(); map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, pluginId); map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); + if (pluginDependencies != null) { + map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, pluginDependencies); + } if (pluginClass != null) { map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); } -- 2.39.5