feat: add plugin unstructured resource loader (#2154)

* feat: add plugin unstructured resource loader

* feat: add test unit case
pull/2158/head
guqing 2022-06-14 23:38:12 +08:00 committed by GitHub
parent 6bbaa9aeba
commit 83d668b0a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 149 additions and 2 deletions

View File

@ -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 =

View File

@ -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();
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}