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 76b44f870e..49a2af2c4d 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.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 @@ * @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 @@ protected void initialize() { // 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 ApplicationContext getSharedContext() { @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 0000000000..90e65ca1ee --- /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()); + } + + +}