mirror of https://github.com/halo-dev/halo
feat: add plugin unstructured resource loader (#2154)
* feat: add plugin unstructured resource loader * feat: add test unit casepull/2158/head
parent
6bbaa9aeba
commit
83d668b0a9
|
@ -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 =
|
||||
|
|
|
@ -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<ApplicationReadyEvent> {
|
||||
|
||||
private final HaloPluginManager haloPluginManager;
|
||||
|
||||
public PluginInitializationLoadOnApplicationReady(HaloPluginManager haloPluginManager) {
|
||||
this.haloPluginManager = haloPluginManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
haloPluginManager.loadPlugins();
|
||||
}
|
||||
}
|
|
@ -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<Unstructured> loadUnstructured(PluginWrapper pluginWrapper) {
|
||||
List<String> 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Lists the path of the unstructured yaml configuration file from the plugin jar.</p>
|
||||
*
|
||||
* @param jarPath plugin jar path
|
||||
* @return Unstructured file paths relative to plugin classpath
|
||||
* @throws PluginRuntimeException If loading the file fails
|
||||
*/
|
||||
public List<String> 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");
|
||||
}
|
||||
}
|
|
@ -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<String> unstructuredFilePathFromJar =
|
||||
unstructuredResourceLoader.getUnstructuredFilePathFromJar(file.toPath());
|
||||
assertThat(unstructuredFilePathFromJar).hasSize(3);
|
||||
assertThat(unstructuredFilePathFromJar).contains("extensions/roles.yaml",
|
||||
"extensions/reverseProxy.yaml", "extensions/test.yml");
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue