From 8ff1bc497e5f6387fcc03dbdcd18c19ed8ed78fd Mon Sep 17 00:00:00 2001 From: John Niang Date: Thu, 25 Jul 2024 10:59:36 +0800 Subject: [PATCH] [release-2.17] Fix the problem that plugins without jar file may not be deleted (#6374) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an automated cherry-pick of #6334 /assign JohnNiang ```release-note 修复在没有插件文件的情况下可能无法删除插件的问题 ``` --- .../halo/app/plugin/HaloPluginManager.java | 36 +++++++----- .../app/plugin/HaloPluginManagerTest.java | 58 +++++++++++++++++++ 2 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 application/src/test/java/run/halo/app/plugin/HaloPluginManagerTest.java diff --git a/application/src/main/java/run/halo/app/plugin/HaloPluginManager.java b/application/src/main/java/run/halo/app/plugin/HaloPluginManager.java index 76b44f870..49a2af2c4 100644 --- a/application/src/main/java/run/halo/app/plugin/HaloPluginManager.java +++ b/application/src/main/java/run/halo/app/plugin/HaloPluginManager.java @@ -25,6 +25,7 @@ import org.pf4j.PluginStateEvent; import org.pf4j.PluginStateListener; import org.pf4j.PluginStatusProvider; import org.pf4j.PluginWrapper; +import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.data.util.Lazy; import run.halo.app.infra.SystemVersionSupplier; @@ -39,30 +40,23 @@ import run.halo.app.plugin.event.PluginStartedEvent; * @since 2.0.0 */ @Slf4j -public class HaloPluginManager extends DefaultPluginManager implements SpringPluginManager { +public class HaloPluginManager extends DefaultPluginManager + implements SpringPluginManager, InitializingBean { private final ApplicationContext rootContext; - private final Lazy sharedContext; + private Lazy sharedContext; private final PluginProperties pluginProperties; + private final SystemVersionSupplier systemVersionSupplier; + public HaloPluginManager(ApplicationContext rootContext, PluginProperties pluginProperties, SystemVersionSupplier systemVersionSupplier) { this.pluginProperties = pluginProperties; this.rootContext = rootContext; - // We have to initialize share context lazily because the root context has not refreshed - this.sharedContext = Lazy.of(() -> SharedApplicationContextFactory.create(rootContext)); - super.runtimeMode = pluginProperties.getRuntimeMode(); - - setExactVersionAllowed(pluginProperties.isExactVersionAllowed()); - setSystemVersion(systemVersionSupplier.get().getNormalVersion()); - - super.initialize(); - - // the listener must be after the super#initialize - addPluginStateListener(new PluginStartedListener()); + this.systemVersionSupplier = systemVersionSupplier; } @Override @@ -71,6 +65,18 @@ public class HaloPluginManager extends DefaultPluginManager implements SpringPlu // components before properties set. } + @Override + public void afterPropertiesSet() throws Exception { + super.runtimeMode = pluginProperties.getRuntimeMode(); + this.sharedContext = Lazy.of(() -> SharedApplicationContextFactory.create(rootContext)); + setExactVersionAllowed(pluginProperties.isExactVersionAllowed()); + setSystemVersion(systemVersionSupplier.get().toStableVersion().toString()); + + super.initialize(); + // the listener must be after the super#initialize + addPluginStateListener(new PluginStartedListener()); + } + @Override protected ExtensionFactory createExtensionFactory() { return new SpringExtensionFactory(this); @@ -169,6 +175,10 @@ public class HaloPluginManager extends DefaultPluginManager implements SpringPlu @Override public List getDependents(String pluginId) { + if (getPlugin(pluginId) == null) { + return List.of(); + } + var dependents = new ArrayList(); var stack = new Stack(); dependencyResolver.getDependents(pluginId).forEach(stack::push); diff --git a/application/src/test/java/run/halo/app/plugin/HaloPluginManagerTest.java b/application/src/test/java/run/halo/app/plugin/HaloPluginManagerTest.java new file mode 100644 index 000000000..90e65ca1e --- /dev/null +++ b/application/src/test/java/run/halo/app/plugin/HaloPluginManagerTest.java @@ -0,0 +1,58 @@ +package run.halo.app.plugin; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + +import com.github.zafarkhaja.semver.Version; +import java.nio.file.Path; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.io.TempDir; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.pf4j.RuntimeMode; +import org.springframework.context.ApplicationContext; +import run.halo.app.infra.SystemVersionSupplier; + +@ExtendWith(MockitoExtension.class) +class HaloPluginManagerTest { + + @Mock + PluginProperties pluginProperties; + + @Mock + SystemVersionSupplier systemVersionSupplier; + + @Mock + ApplicationContext rootContext; + + @InjectMocks + HaloPluginManager pluginManager; + + @TempDir + Path tempDir; + + @Test + void shouldGetDependentsWhilePluginsNotResolved() throws Exception { + when(pluginProperties.getRuntimeMode()).thenReturn(RuntimeMode.DEPLOYMENT); + when(systemVersionSupplier.get()).thenReturn(Version.of(1, 2, 3)); + pluginManager.afterPropertiesSet(); + // if we don't invoke resolves + var dependents = pluginManager.getDependents("fake-plugin"); + assertTrue(dependents.isEmpty()); + } + + @Test + void shouldGetDependentsWhilePluginsResolved() throws Exception { + when(pluginProperties.getRuntimeMode()).thenReturn(RuntimeMode.DEPLOYMENT); + when(systemVersionSupplier.get()).thenReturn(Version.of(1, 2, 3)); + pluginManager.afterPropertiesSet(); + pluginManager.loadPlugins(); + // if we don't invoke resolves + var dependents = pluginManager.getDependents("fake-plugin"); + assertTrue(dependents.isEmpty()); + } + + +}