diff --git a/src/main/java/run/halo/app/plugin/HaloPluginManager.java b/src/main/java/run/halo/app/plugin/HaloPluginManager.java index 642d48737..ad0773dae 100644 --- a/src/main/java/run/halo/app/plugin/HaloPluginManager.java +++ b/src/main/java/run/halo/app/plugin/HaloPluginManager.java @@ -82,8 +82,6 @@ public class HaloPluginManager extends DefaultPluginManager @Override public void afterPropertiesSet() { - // This method load, start plugins and inject extensions in Spring - loadPlugins(); this.pluginApplicationInitializer = new PluginApplicationInitializer(this); this.requestMappingManager = diff --git a/src/main/java/run/halo/app/plugin/PluginInitializationLoadOnApplicationReady.java b/src/main/java/run/halo/app/plugin/PluginInitializationLoadOnApplicationReady.java new file mode 100644 index 000000000..e3c6092f4 --- /dev/null +++ b/src/main/java/run/halo/app/plugin/PluginInitializationLoadOnApplicationReady.java @@ -0,0 +1,27 @@ +package run.halo.app.plugin; + +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +/** + * Load plugins after application ready. + * + * @author guqing + * @since 2.0.0 + */ +@Component +public class PluginInitializationLoadOnApplicationReady + implements ApplicationListener { + + private final HaloPluginManager haloPluginManager; + + public PluginInitializationLoadOnApplicationReady(HaloPluginManager haloPluginManager) { + this.haloPluginManager = haloPluginManager; + } + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + haloPluginManager.loadPlugins(); + } +} diff --git a/src/main/java/run/halo/app/plugin/PluginUnstructuredResourceLoader.java b/src/main/java/run/halo/app/plugin/PluginUnstructuredResourceLoader.java new file mode 100644 index 000000000..2a72b19a6 --- /dev/null +++ b/src/main/java/run/halo/app/plugin/PluginUnstructuredResourceLoader.java @@ -0,0 +1,86 @@ +package run.halo.app.plugin; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import org.pf4j.PluginRuntimeException; +import org.pf4j.PluginWrapper; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.lang.NonNull; +import run.halo.app.extension.Unstructured; +import run.halo.app.infra.utils.YamlUnstructuredLoader; + +/** + * Plug in unstructured data loader. + * TODO Rename this class to an appropriate name. + * + * @author guqing + * @see YamlUnstructuredLoader + * @see PluginWrapper + * @see DefaultResourceLoader + * @since 2.0.0 + */ +public class PluginUnstructuredResourceLoader { + private static final String DEFAULT_RESOURCE_LOCATION = "extensions/"; + private final String resourceLocation; + + public PluginUnstructuredResourceLoader() { + resourceLocation = DEFAULT_RESOURCE_LOCATION; + } + + public PluginUnstructuredResourceLoader(String resourceLocation) { + this.resourceLocation = resourceLocation; + } + + /** + * Loading unstructured yaml configuration files in plugins. + * + * @param pluginWrapper Wrapper object holding plugin data + * @return a collection of {@link Unstructured} data(never null) + */ + @NonNull + public List loadUnstructured(PluginWrapper pluginWrapper) { + List unstructuredFilePaths = + getUnstructuredFilePathFromJar(pluginWrapper.getPluginPath()); + + DefaultResourceLoader resourceLoader = + new DefaultResourceLoader(pluginWrapper.getPluginClassLoader()); + Resource[] resources = unstructuredFilePaths.stream() + .map(resourceLoader::getResource) + .filter(Resource::exists) + .toArray(Resource[]::new); + + YamlUnstructuredLoader yamlUnstructuredLoader = new YamlUnstructuredLoader(resources); + return yamlUnstructuredLoader.load(); + } + + /** + *

Lists the path of the unstructured yaml configuration file from the plugin jar.

+ * + * @param jarPath plugin jar path + * @return Unstructured file paths relative to plugin classpath + * @throws PluginRuntimeException If loading the file fails + */ + public List getUnstructuredFilePathFromJar(Path jarPath) { + try (JarFile jarFile = new JarFile(jarPath.toFile())) { + return jarFile.stream() + .filter(jarEntry -> { + String name = jarEntry.getName(); + return name.startsWith(resourceLocation) + && !jarEntry.isDirectory() + && isYamlFile(name); + }) + .map(ZipEntry::getName) + .toList(); + } catch (IOException e) { + throw new PluginRuntimeException(e); + } + } + + private boolean isYamlFile(String path) { + return path.endsWith(".yaml") || path.endsWith(".yml"); + } +} diff --git a/src/test/java/run/halo/app/plugin/PluginUnstructuredResourceLoaderTest.java b/src/test/java/run/halo/app/plugin/PluginUnstructuredResourceLoaderTest.java new file mode 100644 index 000000000..ec3e2f2e5 --- /dev/null +++ b/src/test/java/run/halo/app/plugin/PluginUnstructuredResourceLoaderTest.java @@ -0,0 +1,36 @@ +package run.halo.app.plugin; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.util.ResourceUtils; + +/** + * Tests for {@link PluginUnstructuredResourceLoader}. + * + * @author guqing + * @since 2.0.0 + */ +class PluginUnstructuredResourceLoaderTest { + + private PluginUnstructuredResourceLoader unstructuredResourceLoader; + + @BeforeEach + void setUp() { + unstructuredResourceLoader = new PluginUnstructuredResourceLoader(); + } + + @Test + void getUnstructuredFilePathFromJar() throws FileNotFoundException { + File file = ResourceUtils.getFile("classpath:plugin/test-unstructured-resource-loader.jar"); + List unstructuredFilePathFromJar = + unstructuredResourceLoader.getUnstructuredFilePathFromJar(file.toPath()); + assertThat(unstructuredFilePathFromJar).hasSize(3); + assertThat(unstructuredFilePathFromJar).contains("extensions/roles.yaml", + "extensions/reverseProxy.yaml", "extensions/test.yml"); + } +} \ No newline at end of file diff --git a/src/test/resources/plugin/test-unstructured-resource-loader.jar b/src/test/resources/plugin/test-unstructured-resource-loader.jar new file mode 100644 index 000000000..bca38cec2 Binary files /dev/null and b/src/test/resources/plugin/test-unstructured-resource-loader.jar differ