aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pf4j/src/main/java/org/pf4j/AbstractPluginManager.java1
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginState.java11
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java43
3 files changed, 53 insertions, 2 deletions
diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
index f3a7231..78c261c 100644
--- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
+++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
@@ -311,6 +311,7 @@ public abstract class AbstractPluginManager implements PluginManager {
}
// remove the plugin
+ pluginWrapper.setPluginState(PluginState.UNLOADED);
plugins.remove(pluginId);
getResolvedPlugins().remove(pluginWrapper);
getUnresolvedPlugins().remove(pluginWrapper);
diff --git a/pf4j/src/main/java/org/pf4j/PluginState.java b/pf4j/src/main/java/org/pf4j/PluginState.java
index 989157f..6a6c1f9 100644
--- a/pf4j/src/main/java/org/pf4j/PluginState.java
+++ b/pf4j/src/main/java/org/pf4j/PluginState.java
@@ -20,7 +20,7 @@ package org.pf4j;
* <p>
* Lifecycle of a plugin:
* <pre>
- * CREATED -> RESOLVED -> STARTED -> STOPPED
+ * CREATED -> RESOLVED -> STARTED -> STOPPED -> UNLOADED
* CREATED -> DISABLED
* CREATED -> FAILED
*
@@ -57,7 +57,14 @@ public enum PluginState {
/**
* Plugin failed to start.
*/
- FAILED("FAILED");
+ FAILED("FAILED"),
+
+ /**
+ * The plugin has been unloaded. After this event has been completed, the plugin's
+ * {@link ClassLoader} will be closed.
+ */
+ UNLOADED("UNLOADED"),
+ ;
private final String status;
diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java
index 2e78ad2..d95a2d0 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java
@@ -25,6 +25,9 @@ import org.pf4j.test.PluginZip;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -40,12 +43,17 @@ public class DefaultPluginManagerTest {
private DefaultPluginDescriptor pluginDescriptor;
private PluginWrapper pluginWrapper;
+ private List<PluginStateEvent> receivedEvents;
+
@TempDir
Path pluginsPath;
@BeforeEach
public void setUp() throws IOException {
+ receivedEvents = new ArrayList<>();
+
pluginManager = new DefaultPluginManager(pluginsPath);
+ pluginManager.addPluginStateListener(event -> receivedEvents.add(event));
pluginDescriptor = new DefaultPluginDescriptor();
pluginDescriptor.setPluginId("myPlugin");
@@ -63,6 +71,7 @@ public class DefaultPluginManagerTest {
pluginManager = null;
pluginDescriptor = null;
pluginWrapper = null;
+ receivedEvents = null;
}
@Test
@@ -140,6 +149,7 @@ public class DefaultPluginManagerTest {
PluginManager pluginManager = new DefaultPluginManager(pluginsPath) {
+ @Override
protected PluginStatusProvider createPluginStatusProvider() {
return statusProvider;
}
@@ -171,6 +181,12 @@ public class DefaultPluginManagerTest {
assertTrue(deleted);
assertFalse(pluginZip.file().exists());
+
+ Optional<PluginStateEvent> unloadedEvent = receivedEvents.stream()
+ .filter(event -> event.getPluginState() == PluginState.UNLOADED)
+ .findFirst();
+
+ assertTrue(unloadedEvent.isPresent());
}
@Test
@@ -188,6 +204,12 @@ public class DefaultPluginManagerTest {
assertTrue(deleted);
assertFalse(pluginJar.file().exists());
+
+ Optional<PluginStateEvent> unloadedEvent = receivedEvents.stream()
+ .filter(event -> event.getPluginState() == PluginState.UNLOADED)
+ .findFirst();
+
+ assertTrue(unloadedEvent.isPresent());
}
@Test
@@ -310,4 +332,25 @@ public class DefaultPluginManagerTest {
assertThrows(DependencyResolver.CyclicDependencyException.class, () -> pluginManager.loadPlugins());
}
+ @Test
+ public void deleteZipPluginForPluginThatHasNotBeenStartedPostsUnloadedEvent() throws Exception {
+ PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin")
+ .pluginVersion("1.2.3")
+ .build();
+
+ pluginManager.loadPlugin(pluginZip.path());
+
+ assertEquals(1, pluginManager.getPlugins().size());
+
+ boolean deleted = pluginManager.deletePlugin(pluginZip.pluginId());
+ assertTrue(deleted);
+
+ assertFalse(pluginZip.file().exists());
+
+ Optional<PluginStateEvent> unloadedEvent = receivedEvents.stream()
+ .filter(event -> event.getPluginState() == PluginState.UNLOADED)
+ .findFirst();
+
+ assertTrue(unloadedEvent.isPresent());
+ }
}