From 286ed8ed2e08d97b8a76abd7cbbaf5e9f6d4e3bb Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sun, 30 Jan 2022 20:45:35 +0200 Subject: [PATCH] Inject FileSystem via PluginManager.getFileSystem and improve PluginZip/PluginJar --- .../java/org/pf4j/AbstractPluginManager.java | 4 +- .../java/org/pf4j/DefaultPluginManager.java | 3 +- .../src/main/java/org/pf4j/PluginManager.java | 10 + .../PropertiesPluginDescriptorFinder.java | 35 +--- .../pf4j/ServiceProviderExtensionFinder.java | 11 +- .../main/java/org/pf4j/util/FileUtils.java | 59 ++---- .../CompoundPluginDescriptorFinderTest.java | 37 ++-- .../org/pf4j/DefaultPluginManagerTest.java | 30 ++- .../org/pf4j/DefaultPluginRepositoryTest.java | 7 +- .../java/org/pf4j/JarPluginManagerTest.java | 9 +- .../org/pf4j/LegacyExtensionFinderTest.java | 9 +- .../LoadPluginsFromMultipleRootsTest.java | 15 +- .../test/java/org/pf4j/LoadPluginsTest.java | 99 ++++----- .../ManifestPluginDescriptorFinderTest.java | 97 +++++---- .../java/org/pf4j/PluginClassLoaderTest.java | 10 +- .../java/org/pf4j/PluginDependencyTest.java | 37 ++-- .../PropertiesPluginDescriptorFinderTest.java | 109 +++++----- .../pf4j/SecurePluginManagerWrapperTest.java | 18 +- .../test/java/org/pf4j/test/PluginJar.java | 93 ++------- .../java/org/pf4j/test/PluginManifest.java | 195 ++++++++++++++++++ .../java/org/pf4j/test/PluginProperties.java | 186 +++++++++++++++++ .../test/java/org/pf4j/test/PluginZip.java | 89 +------- .../java/org/pf4j/util/FileUtilsTest.java | 19 +- 23 files changed, 730 insertions(+), 451 deletions(-) create mode 100644 pf4j/src/test/java/org/pf4j/test/PluginManifest.java create mode 100644 pf4j/src/test/java/org/pf4j/test/PluginProperties.java diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 9496013..24f219e 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -734,7 +734,9 @@ public abstract class AbstractPluginManager implements PluginManager { } pluginsDir = isDevelopment() ? DEVELOPMENT_PLUGINS_DIR : DEFAULT_PLUGINS_DIR; - return Collections.singletonList(Paths.get(pluginsDir)); + Path pluginsPath = getFileSystem().getPath(pluginsDir); + + return Collections.singletonList(pluginsPath); } /** diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java index e2667d4..ebb7e06 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java @@ -20,7 +20,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; /** @@ -79,7 +78,7 @@ public class DefaultPluginManager extends AbstractPluginManager { protected PluginStatusProvider createPluginStatusProvider() { String configDir = System.getProperty(PLUGINS_DIR_CONFIG_PROPERTY_NAME); Path configPath = configDir != null - ? Paths.get(configDir) + ? getFileSystem().getPath(configDir) : getPluginsRoots().stream() .findFirst() .orElseThrow(() -> new IllegalArgumentException("No pluginsRoot configured")); diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java index b717656..87cc9a4 100644 --- a/pf4j/src/main/java/org/pf4j/PluginManager.java +++ b/pf4j/src/main/java/org/pf4j/PluginManager.java @@ -15,6 +15,8 @@ */ package org.pf4j; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; import java.nio.file.Path; import java.util.List; import java.util.Set; @@ -223,4 +225,12 @@ public interface PluginManager { VersionManager getVersionManager(); + /** + * Returns the {@link FileSystem} used to deal with {@link Path}. + * By default, it's used {@link FileSystems#getDefault()}. + */ + default FileSystem getFileSystem() { + return FileSystems.getDefault(); + } + } diff --git a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java index a04d268..5eb7ff8 100644 --- a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Properties; /** @@ -75,36 +74,24 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder throw new PluginRuntimeException("Cannot find the properties path"); } + log.debug("Lookup plugin descriptor in '{}'", propertiesPath); + if (Files.notExists(propertiesPath)) { + throw new PluginRuntimeException("Cannot find '{}' path", propertiesPath); + } + Properties properties = new Properties(); - try { - log.debug("Lookup plugin descriptor in '{}'", propertiesPath); - if (Files.notExists(propertiesPath)) { - throw new PluginRuntimeException("Cannot find '{}' path", propertiesPath); - } - - try (InputStream input = Files.newInputStream(propertiesPath)) { - properties.load(input); - } catch (IOException e) { - throw new PluginRuntimeException(e); - } - } finally { - FileUtils.closePath(propertiesPath); + + try (InputStream input = Files.newInputStream(propertiesPath)) { + properties.load(input); + } catch (IOException e) { + throw new PluginRuntimeException(e); } return properties; } protected Path getPropertiesPath(Path pluginPath, String propertiesFileName) { - if (Files.isDirectory(pluginPath)) { - return pluginPath.resolve(Paths.get(propertiesFileName)); - } - - // it's a zip or jar file - try { - return FileUtils.getPath(pluginPath, propertiesFileName); - } catch (IOException e) { - throw new PluginRuntimeException(e); - } + return pluginPath.resolve(propertiesFileName); } protected PluginDescriptor createPluginDescriptor(Properties properties) { diff --git a/pf4j/src/main/java/org/pf4j/ServiceProviderExtensionFinder.java b/pf4j/src/main/java/org/pf4j/ServiceProviderExtensionFinder.java index b477192..8d0afd3 100644 --- a/pf4j/src/main/java/org/pf4j/ServiceProviderExtensionFinder.java +++ b/pf4j/src/main/java/org/pf4j/ServiceProviderExtensionFinder.java @@ -30,7 +30,6 @@ import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.Collections; @@ -123,16 +122,12 @@ public class ServiceProviderExtensionFinder extends AbstractExtensionFinder { Path extensionPath; if (url.toURI().getScheme().equals("jar")) { - extensionPath = FileUtils.getPath(url.toURI(), EXTENSIONS_RESOURCE); + extensionPath = FileUtils.getPath(url.toURI(), pluginManager.getFileSystem()).resolve(EXTENSIONS_RESOURCE); } else { - extensionPath = Paths.get(url.toURI()); + extensionPath = pluginManager.getFileSystem().getPath(url.getPath()); } - try { - bucket.addAll(readExtensions(extensionPath)); - } finally { - FileUtils.closePath(extensionPath); - } + bucket.addAll(readExtensions(extensionPath)); } private Set readExtensions(Path extensionPath) throws IOException { diff --git a/pf4j/src/main/java/org/pf4j/util/FileUtils.java b/pf4j/src/main/java/org/pf4j/util/FileUtils.java index 2f66595..59e27de 100644 --- a/pf4j/src/main/java/org/pf4j/util/FileUtils.java +++ b/pf4j/src/main/java/org/pf4j/util/FileUtils.java @@ -27,16 +27,15 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystem; import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.FileTime; +import java.nio.file.spi.FileSystemProvider; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -165,7 +164,7 @@ public final class FileUtils { String directoryName = fileName.substring(0, fileName.lastIndexOf(".")); Path pluginDirectory = filePath.resolveSibling(directoryName); - if (!Files.exists(pluginDirectory) || pluginZipDate.compareTo(Files.getLastModifiedTime(pluginDirectory)) > 0) { + if (Files.notExists(pluginDirectory) || pluginZipDate.compareTo(Files.getLastModifiedTime(pluginDirectory)) > 0) { // expand '.zip' file Unzip unzip = new Unzip(); unzip.setSource(filePath); @@ -207,37 +206,6 @@ public final class FileUtils { return isZipFile(path) || isJarFile(path); } - public static Path getPath(Path path, String first, String... more) throws IOException { - URI uri = path.toUri(); - if (isZipOrJarFile(path)) { - String pathString = path.toAbsolutePath().toString(); - // transformation for Windows OS - pathString = StringUtils.addStart(pathString.replace("\\", "/"), "/"); - // space is replaced with %20 - pathString = pathString.replace(" ","%20"); - uri = URI.create("jar:file:" + pathString); - } - - return getPath(uri, first, more); - } - - public static Path getPath(URI uri, String first, String... more) throws IOException { - return getFileSystem(uri).getPath(first, more); - } - - /** - * Quietly close a path. - */ - public static void closePath(Path path) { - if (path != null) { - try { - path.getFileSystem().close(); - } catch (Exception e) { - // close silently - } - } - } - public static Stream findPaths(Path path, PathFilter filter) { return findPaths(path, Integer.MAX_VALUE, filter); } @@ -256,12 +224,25 @@ public final class FileUtils { } } - private static FileSystem getFileSystem(URI uri) throws IOException { - try { - return FileSystems.getFileSystem(uri); - } catch (FileSystemNotFoundException e) { - return FileSystems.newFileSystem(uri, Collections.emptyMap()); + public static Path getPath(URI uri, FileSystem fileSystem) { + String scheme = uri.getScheme(); + if (scheme == null) { + throw new IllegalArgumentException("Missing scheme"); + } + + // check for default provider to avoid loading of installed providers + if (scheme.equalsIgnoreCase("file")) { + return fileSystem.provider().getPath(uri); } + + // try to find provider + for (FileSystemProvider provider: FileSystemProvider.installedProviders()) { + if (provider.getScheme().equalsIgnoreCase(scheme)) { + return provider.getPath(uri); + } + } + + throw new FileSystemNotFoundException("Provider '" + scheme + "' not installed"); } } diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java index 39bb77a..97914ce 100644 --- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java @@ -18,7 +18,8 @@ package org.pf4j; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.test.PluginJar; -import org.pf4j.test.PluginZip; +import org.pf4j.test.PluginManifest; +import org.pf4j.test.PluginProperties; import org.pf4j.test.TestPlugin; import java.io.IOException; @@ -26,8 +27,7 @@ import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.Arrays; import java.util.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -54,7 +54,7 @@ class CompoundPluginDescriptorFinderTest { @Test void find() throws Exception { Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1")); - storePropertiesToPath(getPlugin1Properties(), pluginPath); + storePropertiesToPath(createPropertiesPlugin1(), pluginPath); PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder() .add(new PropertiesPluginDescriptorFinder()); @@ -70,10 +70,12 @@ class CompoundPluginDescriptorFinderTest { PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder() .add(new ManifestPluginDescriptorFinder()); - PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin") + PluginManifest pluginManifest = new PluginManifest.Builder("myPlugin") .pluginClass(TestPlugin.class.getName()) .pluginVersion("1.2.3") .build(); + PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), pluginManifest) + .build(); PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginJar.path()); assertNotNull(pluginDescriptor); @@ -94,25 +96,26 @@ class CompoundPluginDescriptorFinderTest { PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder() .add(new ManifestPluginDescriptorFinder()); - PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my plugin-1.2.3.jar"), "myPlugin") + PluginManifest pluginManifest = new PluginManifest.Builder("myPlugin") .pluginVersion("1.2.3") .build(); + PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my plugin-1.2.3.jar"), pluginManifest) + .build(); PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginJar.path()); assertNotNull(pluginDescriptor); } - private Properties getPlugin1Properties() { - Map map = new LinkedHashMap<>(7); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName()); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "test-plugin-2,test-plugin-3@~1.0"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, ">=1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_LICENSE, "Apache-2.0"); - - return PluginZip.createProperties(map); + private Properties createPropertiesPlugin1() { + return new PluginProperties.Builder("test-plugin-1") + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("0.0.1") + .pluginProvider("Decebal Suiu") + .pluginDependencies(Arrays.asList("test-plugin-2", "test-plugin-3@~1.0")) + .pluginRequires(">=1") + .pluginLicense("Apache-2.0") + .build() + .properties(); } private void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException { diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java index d67746f..ccfc046 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java @@ -20,6 +20,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.test.PluginJar; +import org.pf4j.test.PluginManifest; +import org.pf4j.test.PluginProperties; import org.pf4j.test.PluginZip; import java.io.IOException; @@ -131,8 +133,8 @@ class DefaultPluginManagerTest { */ @Test void pluginDisabledNoStart() throws IOException { - new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") - .pluginVersion("1.2.3") + PluginProperties pluginProperties = createPluginProperties(); + new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); final PluginStatusProvider statusProvider = mock(PluginStatusProvider.class); @@ -157,9 +159,9 @@ class DefaultPluginManagerTest { } @Test - void deleteZipPlugin() throws Exception { - PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") - .pluginVersion("1.2.3") + void deleteZipPlugin() throws IOException { + PluginProperties pluginProperties = createPluginProperties(); + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); pluginManager.loadPlugin(pluginZip.path()); @@ -174,9 +176,9 @@ class DefaultPluginManagerTest { } @Test - void deleteJarPlugin() throws Exception { - PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin") - .pluginVersion("1.2.3") + void deleteJarPlugin() throws IOException { + PluginManifest pluginManifest = createPluginManifest(); + PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), pluginManifest) .build(); pluginManager.loadPlugin(pluginJar.path()); @@ -190,4 +192,16 @@ class DefaultPluginManagerTest { assertFalse(Files.exists(pluginJar.path())); } + private PluginProperties createPluginProperties() { + return new PluginProperties.Builder("myPlugin") + .pluginVersion("1.2.3") + .build(); + } + + private PluginManifest createPluginManifest() { + return new PluginManifest.Builder("myPlugin") + .pluginVersion("1.2.3") + .build(); + } + } diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java index 50831bd..1a68fd0 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -18,6 +18,7 @@ package org.pf4j; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.pf4j.test.PluginProperties; import org.pf4j.test.PluginZip; import org.pf4j.util.FileUtils; @@ -47,7 +48,11 @@ class DefaultPluginRepositoryTest { // Prove that we can delete a folder with a file inside Files.createFile(plugin1Path.resolve("myfile")); // Create a zip file for plugin-1 to test that it is deleted when plugin is deleted - new PluginZip.Builder(pluginsPath1.resolve("plugin-1.zip"), "plugin-1").pluginVersion("1.0").build(); + PluginProperties pluginProperties = new PluginProperties.Builder("plugin-1") + .pluginVersion("1.0") + .build(); + new PluginZip.Builder(pluginsPath1.resolve("plugin-1.zip"), pluginProperties) + .build(); Files.createDirectory(pluginsPath2.resolve("plugin-2")); Files.createDirectory(pluginsPath2.resolve("plugin-3")); } diff --git a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java index 42e4cde..aa707cb 100644 --- a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.test.PluginJar; +import org.pf4j.test.PluginManifest; import org.pf4j.test.TestExtension; import org.pf4j.test.TestExtensionPoint; import org.pf4j.test.TestPlugin; @@ -33,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -public class JarPluginManagerTest { +class JarPluginManagerTest { private PluginJar pluginJar; private JarPluginManager pluginManager; @@ -43,9 +44,11 @@ public class JarPluginManagerTest { @BeforeEach void setUp() throws IOException { - pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), "test-plugin") + PluginManifest pluginManifest = new PluginManifest.Builder("test-plugin") .pluginClass(TestPlugin.class.getName()) .pluginVersion("1.2.3") + .build(); + pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), pluginManifest) .extension(TestExtension.class.getName()) .build(); @@ -73,7 +76,7 @@ public class JarPluginManagerTest { } @Test - void unloadPlugin() throws Exception { + void unloadPlugin() { pluginManager.loadPlugins(); assertEquals(1, pluginManager.getPlugins().size()); diff --git a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java index 2d59911..06fa408 100644 --- a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledOnOs; import org.junit.jupiter.api.io.TempDir; import org.pf4j.test.PluginJar; +import org.pf4j.test.PluginManifest; import org.pf4j.test.TestExtension; import org.pf4j.test.TestPlugin; @@ -43,9 +44,11 @@ class LegacyExtensionFinderTest { @Test @EnabledOnOs(WINDOWS) void shouldUnlockFileAfterReadingExtensionsFromPlugin() throws Exception { - PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), "test-plugin") - .pluginClass(TestPlugin.class.getName()) - .pluginVersion("1.2.3") + PluginManifest pluginManifest = new PluginManifest.Builder("test-plugin") + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("1.2.3") + .build(); + PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), pluginManifest) .extension(TestExtension.class.getName()) .build(); diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsFromMultipleRootsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsFromMultipleRootsTest.java index 80d7ca8..e8f4d7c 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsFromMultipleRootsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsFromMultipleRootsTest.java @@ -18,6 +18,7 @@ package org.pf4j; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.pf4j.test.PluginProperties; import org.pf4j.test.PluginZip; import org.pf4j.util.FileUtils; @@ -50,13 +51,17 @@ class LoadPluginsFromMultipleRootsTest { @Test void load() throws Exception { - PluginZip pluginZip1 = new PluginZip.Builder(pluginsPath1.resolve("my-plugin-1.2.3.zip"), "myPlugin") + PluginProperties plugin1Properties = new PluginProperties.Builder("myPlugin") .pluginVersion("1.2.3") .build(); + PluginZip pluginZip1 = new PluginZip.Builder(pluginsPath1.resolve("my-plugin-1.2.3.zip"), plugin1Properties) + .build(); - PluginZip pluginZip2 = new PluginZip.Builder(pluginsPath2.resolve("my-other-plugin-4.5.6.zip"), "myOtherPlugin") + PluginProperties plugin2Properties = new PluginProperties.Builder("myOtherPlugin") .pluginVersion("4.5.6") .build(); + PluginZip plugin2Zip = new PluginZip.Builder(pluginsPath2.resolve("my-other-plugin-4.5.6.zip"), plugin2Properties) + .build(); assertTrue(Files.exists(pluginZip1.path())); assertEquals(0, pluginManager.getPlugins().size()); @@ -65,11 +70,11 @@ class LoadPluginsFromMultipleRootsTest { assertTrue(Files.exists(pluginZip1.path())); assertTrue(Files.exists(pluginZip1.unzippedPath())); - assertTrue(Files.exists(pluginZip2.path())); - assertTrue(Files.exists(pluginZip2.unzippedPath())); + assertTrue(Files.exists(plugin2Zip.path())); + assertTrue(Files.exists(plugin2Zip.unzippedPath())); assertEquals(2, pluginManager.getPlugins().size()); assertEquals(pluginZip1.pluginId(), pluginManager.idForPath(pluginZip1.unzippedPath())); - assertEquals(pluginZip2.pluginId(), pluginManager.idForPath(pluginZip2.unzippedPath())); + assertEquals(plugin2Zip.pluginId(), pluginManager.idForPath(plugin2Zip.unzippedPath())); } } diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java index 363acc3..ffd6267 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java @@ -18,8 +18,10 @@ package org.pf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.pf4j.test.PluginProperties; import org.pf4j.test.PluginZip; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -50,9 +52,9 @@ class LoadPluginsTest { } @Test - void load() throws Exception { - PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") - .pluginVersion("1.2.3") + void load() throws IOException { + PluginProperties pluginProperties = createPluginProperties(); + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); assertTrue(Files.exists(pluginZip.path())); @@ -71,9 +73,9 @@ class LoadPluginsTest { } @Test - void loadTwiceFails() throws Exception { - PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") - .pluginVersion("1.2.3") + void loadTwiceFails() throws IOException { + PluginProperties pluginProperties = createPluginProperties(); + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); assertNotNull(pluginManager.loadPluginFromPath(pluginZip.path())); @@ -83,21 +85,15 @@ class LoadPluginsTest { @Test void loadPluginWithSameIdDifferentPathFails() throws Exception { - String pluginId = "myPlugin"; - String pluginVersion = "1.2.3"; - Path plugin1Path = pluginsPath.resolve("my-plugin-1.2.3.zip"); - PluginZip plugin1 = new PluginZip.Builder(plugin1Path, pluginId) - .pluginVersion(pluginVersion) + PluginProperties pluginProperties = createPluginProperties(); + PluginZip plugin1 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); - - Path plugin2Path = pluginsPath.resolve("my-plugin-1.2.3-renamed.zip"); - PluginZip plugin2 = new PluginZip.Builder(plugin2Path, pluginId) - .pluginVersion(pluginVersion) + PluginZip plugin2 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3-renamed.zip"), pluginProperties) .build(); // Verify the first plugin with the given id is loaded assertNotNull(pluginManager.loadPluginFromPath(plugin1.path())); - Path loadedPlugin1Path = pluginManager.getPlugin(pluginId).getPluginPath(); + Path loadedPlugin1Path = pluginManager.getPlugin(plugin1.pluginId()).getPluginPath(); try { // Verify the second plugin is not loaded as it has the same metadata @@ -105,12 +101,12 @@ class LoadPluginsTest { fail("Expected loadPluginFromPath to fail"); } catch (PluginRuntimeException e) { // Check the io of the loaded plugin remains the same - PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId); + PluginWrapper loadedPlugin = pluginManager.getPlugin(plugin1.pluginId()); assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path)); // Check the message includes relevant information String message = e.getMessage(); assertThat(message, startsWith("There is an already loaded plugin")); - assertThat(message, containsString(pluginId)); + assertThat(message, containsString(plugin1.pluginId())); assertThat(message, containsString("my-plugin-1.2.3-renamed")); } } @@ -121,39 +117,38 @@ class LoadPluginsTest { * uses pluginId as the unique identifier of the loaded plugin. */ @Test - void loadPluginWithSameIdDifferentVersionsFails() throws Exception { - String pluginId = "myPlugin"; - String plugin1Version = "1.2.3"; - Path plugin1Path = pluginsPath.resolve("my-plugin-1.2.3.zip"); - PluginZip plugin1 = new PluginZip.Builder(plugin1Path, pluginId) - .pluginVersion(plugin1Version) + void loadPluginWithSameIdDifferentVersionsFails() throws IOException { + PluginProperties plugin1Properties = new PluginProperties.Builder("myPlugin") + .pluginVersion("1.2.3") + .build(); + PluginZip plugin1 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), plugin1Properties) .build(); - String plugin2Version = "2.0.0"; - Path plugin2Path = pluginsPath.resolve("my-plugin-2.0.0.zip"); - PluginZip plugin2 = new PluginZip.Builder(plugin2Path, pluginId) - .pluginVersion(plugin2Version) + PluginProperties plugin2Properties = new PluginProperties.Builder("myPlugin") + .pluginVersion("2.0.0") + .build(); + PluginZip plugin2 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-2.0.0.zip"), plugin2Properties) .build(); // Verify the first plugin with the given id is loaded assertNotNull(pluginManager.loadPluginFromPath(plugin1.path())); - Path loadedPlugin1Path = pluginManager.getPlugin(pluginId).getPluginPath(); + Path loadedPlugin1Path = pluginManager.getPlugin(plugin1.pluginId()).getPluginPath(); try { // Verify the second plugin is not loaded as it has the same pluginId pluginManager.loadPluginFromPath(plugin2.path()); fail("Expected loadPluginFromPath to fail"); } catch (PluginRuntimeException e) { // Check the io and version of the loaded plugin remain the same - PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId); + PluginWrapper loadedPlugin = pluginManager.getPlugin(plugin1.pluginId()); assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path)); - assertThat(loadedPlugin.getDescriptor().getVersion(), equalTo(plugin1Version)); + assertThat(loadedPlugin.getDescriptor().getVersion(), equalTo(plugin1.pluginVersion())); } } @Test - void loadUnloadLoad() throws Exception { - PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") - .pluginVersion("1.2.3") + void loadUnloadLoad() throws IOException { + PluginProperties pluginProperties = createPluginProperties(); + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); pluginManager.loadPlugins(); @@ -168,11 +163,9 @@ class LoadPluginsTest { } @Test - void upgrade() throws Exception { - String pluginId = "myPlugin"; - - new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginId) - .pluginVersion("1.2.3") + void upgrade() throws IOException { + PluginProperties pluginProperties = createPluginProperties(); + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); pluginManager.loadPlugins(); @@ -181,18 +174,20 @@ class LoadPluginsTest { assertEquals(1, pluginManager.getPlugins().size()); assertEquals(1, pluginManager.getStartedPlugins().size()); - PluginZip pluginZip2 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-2.0.0.ZIP"), pluginId) + PluginProperties plugin2Properties = new PluginProperties.Builder("myPlugin") .pluginVersion("2.0.0") .build(); + PluginZip pluginZip2 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-2.0.0.ZIP"), plugin2Properties) + .build(); - assertEquals("1.2.3", pluginManager.getPlugin(pluginId).getDescriptor().getVersion()); + assertEquals("1.2.3", pluginManager.getPlugin(pluginZip.pluginId()).getDescriptor().getVersion()); - pluginManager.unloadPlugin(pluginId); + pluginManager.unloadPlugin(pluginZip.pluginId()); pluginManager.loadPlugin(pluginZip2.path()); // or `pluginManager.loadPlugins();` - pluginManager.startPlugin(pluginId); + pluginManager.startPlugin(pluginZip.pluginId()); assertEquals(1, pluginManager.getPlugins().size()); - assertEquals("2.0.0", pluginManager.getPlugin(pluginId).getDescriptor().getVersion()); + assertEquals("2.0.0", pluginManager.getPlugin(pluginZip.pluginId()).getDescriptor().getVersion()); assertEquals("2.0.0", pluginManager.getStartedPlugins().get(0).getDescriptor().getVersion()); } @@ -216,14 +211,18 @@ class LoadPluginsTest { } @Test - void deletePlugin() throws Exception { - PluginZip pluginZip1 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") + void deletePlugin() throws IOException { + PluginProperties plugin1Properties = new PluginProperties.Builder("myPlugin") .pluginVersion("1.2.3") .build(); + PluginZip pluginZip1 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), plugin1Properties) + .build(); - PluginZip pluginZip3 = new PluginZip.Builder(pluginsPath.resolve("other-3.0.0.Zip"), "other") + PluginProperties plugin2Properties = new PluginProperties.Builder("other") .pluginVersion("3.0.0") .build(); + PluginZip pluginZip3 = new PluginZip.Builder(pluginsPath.resolve("other-3.0.0.Zip"), plugin2Properties) + .build(); pluginManager.loadPlugins(); pluginManager.startPlugins(); @@ -239,4 +238,10 @@ class LoadPluginsTest { assertTrue(Files.exists(pluginZip3.unzippedPath())); } + private PluginProperties createPluginProperties() { + return new PluginProperties.Builder("myPlugin") + .pluginVersion("1.2.3") + .build(); + } + } diff --git a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java index 73919f7..20aa385 100644 --- a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java @@ -18,14 +18,13 @@ package org.pf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.pf4j.test.PluginJar; +import org.pf4j.test.PluginManifest; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.Arrays; import java.util.jar.Manifest; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -46,25 +45,25 @@ class ManifestPluginDescriptorFinderTest { @BeforeEach void setUp() throws IOException { Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1")); - storeManifestToPath(getPlugin1Manifest(), pluginPath); + storeManifestToPath(createManifestPlugin1(), pluginPath); pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-2")); - storeManifestToPath(getPlugin2Manifest(), pluginPath); + storeManifestToPath(createManifestPlugin2(), pluginPath); // empty plugin Files.createDirectories(pluginsPath.resolve("test-plugin-3")); // no plugin class pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-4")); - storeManifestToPath(getPlugin4Manifest(), pluginPath); + storeManifestToPath(createManifestPlugin4(), pluginPath); // no plugin version pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-5")); - storeManifestToPath(getPlugin5Manifest(), pluginPath); + storeManifestToPath(createManifestPlugin5(), pluginPath); // no plugin id pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-6")); - storeManifestToPath(getPlugin6Manifest(), pluginPath); + storeManifestToPath(createManifestPlugin6(), pluginPath); versionManager = new DefaultVersionManager(); } @@ -73,7 +72,7 @@ class ManifestPluginDescriptorFinderTest { * Test of {@link ManifestPluginDescriptorFinder#find(Path)} method. */ @Test - void find() throws Exception { + void find() { PluginDescriptorFinder descriptorFinder = new ManifestPluginDescriptorFinder(); PluginDescriptor plugin1 = descriptorFinder.find(pluginsPath.resolve("test-plugin-1")); @@ -106,58 +105,54 @@ class ManifestPluginDescriptorFinderTest { @Test void findNotFound() { PluginDescriptorFinder descriptorFinder = new ManifestPluginDescriptorFinder(); - assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); + Path pluginPath = pluginsPath.resolve("test-plugin-3"); + assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginPath)); } - private Manifest getPlugin1Manifest() { - Map map = new LinkedHashMap<>(8); - map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_DESCRIPTION, "Test Plugin 1"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "test-plugin-2,test-plugin-3@~1.0"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_LICENSE, "Apache-2.0"); - - return PluginJar.createManifest(map); + private Manifest createManifestPlugin1() { + return new PluginManifest.Builder("test-plugin-1") + .pluginClass("org.pf4j.plugin.TestPlugin") + .pluginVersion("0.0.1") + .pluginDescription("Test Plugin 1") + .pluginProvider("Decebal Suiu") + .pluginDependencies(Arrays.asList("test-plugin-2", "test-plugin-3@~1.0")) + .pluginRequires("*") + .pluginLicense("Apache-2.0") + .build() + .manifest(); } - private Manifest getPlugin2Manifest() { - Map map = new LinkedHashMap<>(5); - map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - - return PluginJar.createManifest(map); + private Manifest createManifestPlugin2() { + return new PluginManifest.Builder("test-plugin-2") + .pluginClass("org.pf4j.plugin.TestPlugin") + .pluginVersion("0.0.1") + .pluginProvider("Decebal Suiu") + .build() + .manifest(); } - private Manifest getPlugin4Manifest() { - Map map = new LinkedHashMap<>(3); - map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - - return PluginJar.createManifest(map); + private Manifest createManifestPlugin4() { + return new PluginManifest.Builder("test-plugin-4") + .pluginVersion("0.0.1") + .pluginProvider("Decebal Suiu") + .build() + .manifest(); } - private Manifest getPlugin5Manifest() { - Map map = new LinkedHashMap<>(3); - map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - - return PluginJar.createManifest(map); + private Manifest createManifestPlugin5() { + return new PluginManifest.Builder("test-plugin-5") + .pluginClass("org.pf4j.plugin.TestPlugin") + .pluginProvider("Decebal Suiu") + .build() + .manifest(); } - private Manifest getPlugin6Manifest() { - Map map = new LinkedHashMap<>(2); - map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); - map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - - return PluginJar.createManifest(map); + private Manifest createManifestPlugin6() { + return new PluginManifest.Builder("test-plugin-6") + .pluginClass("org.pf4j.plugin.TestPlugin") + .pluginProvider("Decebal Suiu") + .build() + .manifest(); } private void storeManifestToPath(Manifest manifest, Path pluginPath) throws IOException { diff --git a/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java b/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java index f97da55..a4d5e30 100644 --- a/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java +++ b/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.pf4j.test.PluginProperties; import org.pf4j.test.PluginZip; import org.pf4j.util.FileUtils; @@ -103,10 +104,12 @@ class PluginClassLoaderTest { pluginDependencyDescriptor.setProvider("Me"); pluginDependencyDescriptor.setRequires("5.0.0"); + PluginProperties pluginProperties = new PluginProperties.Builder(pluginDependencyDescriptor.getPluginId()) + .pluginVersion(pluginDependencyDescriptor.getVersion()) + .build(); Path pluginDependencyPath = pluginsPath.resolve(pluginDependencyDescriptor.getPluginId() + "-" + pluginDependencyDescriptor.getVersion() + ".zip"); - PluginZip pluginDependencyZip = new PluginZip.Builder(pluginDependencyPath, pluginDependencyDescriptor.getPluginId()) - .pluginVersion(pluginDependencyDescriptor.getVersion()) + PluginZip pluginDependencyZip = new PluginZip.Builder(pluginDependencyPath, pluginProperties) .addFile(Paths.get("classes/META-INF/dependency-file"), "dependency") .addFile(Paths.get("classes/META-INF/file-in-both-parent-and-dependency-and-plugin"), "dependency") .addFile(Paths.get("classes/META-INF/file-in-both-parent-and-dependency"), "dependency") @@ -147,8 +150,7 @@ class PluginClassLoaderTest { pluginDescriptor.setRequires("5.0.0"); Path pluginPath = pluginsPath.resolve(pluginDescriptor.getPluginId() + "-" + pluginDescriptor.getVersion() + ".zip"); - PluginZip pluginZip = new PluginZip.Builder(pluginPath, pluginDescriptor.getPluginId()) - .pluginVersion(pluginDescriptor.getVersion()) + PluginZip pluginZip = new PluginZip.Builder(pluginPath, pluginProperties) .addFile(Paths.get("classes/META-INF/plugin-file"), "plugin") .addFile(Paths.get("classes/META-INF/file-in-both-parent-and-dependency-and-plugin"), "plugin") .addFile(Paths.get("classes/META-INF/file-in-both-parent-and-plugin"), "plugin") diff --git a/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java b/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java index 75a9adf..3aa1251 100644 --- a/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java +++ b/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java @@ -18,6 +18,7 @@ package org.pf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.pf4j.test.PluginProperties; import org.pf4j.test.PluginZip; import java.nio.file.Path; @@ -94,12 +95,18 @@ class PluginDependencyTest { @Test void dependentStop() throws Exception { // B depends on A - PluginZip pluginA = new PluginZip.Builder(pluginsPath.resolve("A-plugin-1.2.3.zip"), "plugin.a") - .pluginVersion("1.2.3").build(); - - PluginZip pluginB = new PluginZip.Builder(pluginsPath.resolve("B-plugin-1.2.3.zip"), "plugin.b") - .pluginDependencies("plugin.a") - .pluginVersion("1.2.3").build(); + PluginProperties pluginAProperties = new PluginProperties.Builder("plugin.a") + .pluginVersion("1.2.3") + .build(); + PluginZip pluginA = new PluginZip.Builder(pluginsPath.resolve("A-plugin-1.2.3.zip"), pluginAProperties) + .build(); + + PluginProperties pluginBProperties = new PluginProperties.Builder("plugin.b") + .pluginVersion("1.2.3") + .pluginDependency("plugin.a") + .build(); + PluginZip pluginB = new PluginZip.Builder(pluginsPath.resolve("B-plugin-1.2.3.zip"), pluginBProperties) + .build(); pluginManager.loadPlugins(); assertEquals(2, pluginManager.getPlugins().size()); @@ -123,12 +130,18 @@ class PluginDependencyTest { @Test void dependentUnload() throws Exception { // B depends on A - PluginZip pluginA = new PluginZip.Builder(pluginsPath.resolve("A-plugin-1.2.3.zip"), "plugin.a") - .pluginVersion("1.2.3").build(); - - PluginZip pluginB = new PluginZip.Builder(pluginsPath.resolve("B-plugin-1.2.3.zip"), "plugin.b") - .pluginDependencies("plugin.a") - .pluginVersion("1.2.3").build(); + PluginProperties pluginAProperties = new PluginProperties.Builder("plugin.a") + .pluginVersion("1.2.3") + .build(); + PluginZip pluginA = new PluginZip.Builder(pluginsPath.resolve("A-plugin-1.2.3.zip"), pluginAProperties) + .build(); + + PluginProperties pluginBProperties = new PluginProperties.Builder("plugin.b") + .pluginVersion("1.2.3") + .pluginDependency("plugin.a") + .build(); + PluginZip pluginB = new PluginZip.Builder(pluginsPath.resolve("B-plugin-1.2.3.zip"), pluginBProperties) + .build(); pluginManager.loadPlugins(); assertEquals(2, pluginManager.getPlugins().size()); diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index 4513b04..04281a7 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -18,7 +18,7 @@ package org.pf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.pf4j.test.PluginZip; +import org.pf4j.test.PluginProperties; import org.pf4j.test.TestPlugin; import java.io.IOException; @@ -26,8 +26,7 @@ import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.Arrays; import java.util.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -45,31 +44,31 @@ class PropertiesPluginDescriptorFinderTest { @BeforeEach void setUp() throws IOException { Path pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-1")); - storePropertiesToPath(getPlugin1Properties(), pluginPath); + storePropertiesToPath(createPropertiesPlugin1(), pluginPath); pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-2")); - storePropertiesToPath(getPlugin2Properties(), pluginPath); + storePropertiesToPath(createPropertiesPlugin2(), pluginPath); // empty plugin Files.createDirectories(pluginsPath.resolve("test-plugin-3")); // no plugin class pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-4")); - storePropertiesToPath(getPlugin4Properties(), pluginPath); + storePropertiesToPath(createPropertiesPlugin4(), pluginPath); // no plugin version pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-5")); - storePropertiesToPath(getPlugin5Properties(), pluginPath); + storePropertiesToPath(createPropertiesPlugin5(), pluginPath); // no plugin id pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-6")); - storePropertiesToPath(getPlugin6Properties(), pluginPath); + storePropertiesToPath(createPropertiesPlugin6(), pluginPath); versionManager = new DefaultVersionManager(); } @Test - void find() throws Exception { + void find() { PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder(); PluginDescriptor plugin1 = descriptorFinder.find(pluginsPath.resolve("test-plugin-1")); @@ -102,65 +101,59 @@ class PropertiesPluginDescriptorFinderTest { @Test void notFound() { PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder(); - assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); + Path pluginPath = pluginsPath.resolve("test-plugin-3"); + assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginPath)); } - private Properties getPlugin1Properties() { - Map map = new LinkedHashMap<>(8); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName()); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_DESCRIPTION, "Test Plugin 1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "test-plugin-2,test-plugin-3@~1.0"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, ">=1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_LICENSE, "Apache-2.0"); - - return PluginZip.createProperties(map); + private Properties createPropertiesPlugin1() { + return new PluginProperties.Builder("test-plugin-1") + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("0.0.1") + .pluginDescription("Test Plugin 1") + .pluginProvider("Decebal Suiu") + .pluginDependencies(Arrays.asList("test-plugin-2", "test-plugin-3@~1.0")) + .pluginRequires(">=1") + .pluginLicense("Apache-2.0") + .build() + .properties(); } - private Properties getPlugin2Properties() { - Map map = new LinkedHashMap<>(5); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName()); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - - return PluginZip.createProperties(map); + private Properties createPropertiesPlugin2() { + return new PluginProperties.Builder("test-plugin-2") + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("0.0.1") + .pluginProvider("Decebal Suiu") + .build() + .properties(); } - private Properties getPlugin4Properties() { - Map map = new LinkedHashMap<>(5); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); - - return PluginZip.createProperties(map); + private Properties createPropertiesPlugin4() { + return new PluginProperties.Builder("test-plugin-4") + .pluginClass("org.pf4j.plugin.TestPlugin") + .pluginVersion("0.0.1") + .pluginProvider("Decebal Suiu") + .pluginRequires("*") + .build() + .properties(); } - private Properties getPlugin5Properties() { - Map map = new LinkedHashMap<>(5); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName()); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); - - return PluginZip.createProperties(map); + private Properties createPropertiesPlugin5() { + return new PluginProperties.Builder("test-plugin-5") + .pluginClass(TestPlugin.class.getName()) + .pluginProvider("Decebal Suiu") + .pluginRequires("*") + .build() + .properties(); } - private Properties getPlugin6Properties() { - Map map = new LinkedHashMap<>(5); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName()); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); - - return PluginZip.createProperties(map); + private Properties createPropertiesPlugin6() { + return new PluginProperties.Builder("test-plugin-6") + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("0.0.1") + .pluginProvider("Decebal Suiu") + .pluginRequires("*") + .build() + .properties(); } private void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException { diff --git a/pf4j/src/test/java/org/pf4j/SecurePluginManagerWrapperTest.java b/pf4j/src/test/java/org/pf4j/SecurePluginManagerWrapperTest.java index eca280a..c066ddd 100644 --- a/pf4j/src/test/java/org/pf4j/SecurePluginManagerWrapperTest.java +++ b/pf4j/src/test/java/org/pf4j/SecurePluginManagerWrapperTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.test.PluginJar; +import org.pf4j.test.PluginManifest; import org.pf4j.test.TestExtension; import org.pf4j.test.TestExtensionPoint; import org.pf4j.test.TestPlugin; @@ -36,8 +37,21 @@ class SecurePluginManagerWrapperTest { void setUp() throws IOException { pluginManagerEvents = 0; wrappedPluginManagerEvents = 0; - thisPlugin = new PluginJar.Builder(pluginsPath.resolve("test-plugin1.jar"), THIS_PLUGIN_ID).pluginClass(TestPlugin.class.getName()).pluginVersion("1.2.3").extension(TestExtension.class.getName()).build(); - otherPlugin = new PluginJar.Builder(pluginsPath.resolve("test-plugin2.jar"), OTHER_PLUGIN_ID).pluginClass(TestPlugin.class.getName()).pluginVersion("1.2.3").extension(TestExtension.class.getName()).build(); + PluginManifest plugin1Manifest = new PluginManifest.Builder(THIS_PLUGIN_ID) + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("1.2.3") + .build(); + + PluginManifest plugin2Manifest = new PluginManifest.Builder(OTHER_PLUGIN_ID) + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("1.2.3") + .build(); + thisPlugin = new PluginJar.Builder(pluginsPath.resolve("test-plugin1.jar"), plugin1Manifest) + .extension(TestExtension.class.getName()) + .build(); + otherPlugin = new PluginJar.Builder(pluginsPath.resolve("test-plugin2.jar"), plugin2Manifest) + .extension(TestExtension.class.getName()) + .build(); pluginManager = new JarPluginManager(pluginsPath); wrappedPluginManager = new SecurePluginManagerWrapper(pluginManager, THIS_PLUGIN_ID); diff --git a/pf4j/src/test/java/org/pf4j/test/PluginJar.java b/pf4j/src/test/java/org/pf4j/test/PluginJar.java index c23605a..51bde23 100644 --- a/pf4j/src/test/java/org/pf4j/test/PluginJar.java +++ b/pf4j/src/test/java/org/pf4j/test/PluginJar.java @@ -15,22 +15,16 @@ */ package org.pf4j.test; -import org.pf4j.ManifestPluginDescriptorFinder; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; -import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.Map; import java.util.Set; -import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; -import java.util.jar.Manifest; /** * Represents a plugin {@code jar} file. @@ -41,90 +35,44 @@ import java.util.jar.Manifest; public class PluginJar { private final Path path; - private final String pluginId; - private final String pluginClass; - private final String pluginVersion; + private final PluginManifest manifest; protected PluginJar(Builder builder) { this.path = builder.path; - this.pluginId = builder.pluginId; - this.pluginClass = builder.pluginClass; - this.pluginVersion = builder.pluginVersion; + this.manifest = builder.manifest; } public Path path() { return path; } + public PluginManifest manifest() { + return manifest; + } + public String pluginClass() { - return pluginClass; + return manifest.pluginClass(); } public String pluginId() { - return pluginId; + return manifest.pluginId(); } public String pluginVersion() { - return pluginVersion; - } - - public static Manifest createManifest(Map map) { - Manifest manifest = new Manifest(); - Attributes attributes = manifest.getMainAttributes(); - attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0"); - for (Map.Entry entry : map.entrySet()) { - attributes.put(new Attributes.Name(entry.getKey()), entry.getValue()); - } - - return manifest; + return manifest.pluginVersion(); } public static class Builder { private final Path path; - private final String pluginId; + private final PluginManifest manifest; - private String pluginClass; - private String pluginVersion; - private Map manifestAttributes = new LinkedHashMap<>(); private Set extensions = new LinkedHashSet<>(); private ClassDataProvider classDataProvider = new DefaultClassDataProvider(); - public Builder(Path path, String pluginId) { + public Builder(Path path, PluginManifest manifest) { this.path = path; - this.pluginId = pluginId; - } - - public Builder pluginClass(String pluginClass) { - this.pluginClass = pluginClass; - - return this; - } - - public Builder pluginVersion(String pluginVersion) { - this.pluginVersion = pluginVersion; - - return this; - } - - /** - * Add extra attributes to the {@code manifest} file. - * As possible attribute name please see {@link ManifestPluginDescriptorFinder}. - */ - public Builder manifestAttributes(Map manifestAttributes) { - this.manifestAttributes.putAll(manifestAttributes); - - return this; - } - - /** - * Add extra attribute to the {@code manifest} file. - * As possible attribute name please see {@link ManifestPluginDescriptorFinder}. - */ - public Builder manifestAttribute(String name, String value) { - manifestAttributes.put(name, value); - - return this; + this.manifest = manifest; } public Builder extension(String extensionClassName) { @@ -140,9 +88,8 @@ public class PluginJar { } public PluginJar build() throws IOException { - Manifest manifest = createManifest(); try (OutputStream outputStream = Files.newOutputStream(path); - JarOutputStream jarOutputStream = new JarOutputStream(outputStream, manifest)) { + JarOutputStream jarOutputStream = new JarOutputStream(outputStream, manifest.manifest())) { if (!extensions.isEmpty()) { // add extensions.idx JarEntry jarEntry = new JarEntry("META-INF/extensions.idx"); @@ -163,20 +110,6 @@ public class PluginJar { return new PluginJar(this); } - private Manifest createManifest() { - Map map = new LinkedHashMap<>(); - map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, pluginId); - map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); - if (pluginClass != null) { - map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); - } - if (manifestAttributes != null) { - map.putAll(manifestAttributes); - } - - return PluginJar.createManifest(map); - } - private byte[] extensionsAsByteArray() throws IOException { try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { PrintWriter writer = new PrintWriter(outputStream); diff --git a/pf4j/src/test/java/org/pf4j/test/PluginManifest.java b/pf4j/src/test/java/org/pf4j/test/PluginManifest.java new file mode 100644 index 0000000..fb3d38d --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/PluginManifest.java @@ -0,0 +1,195 @@ +package org.pf4j.test; + +import org.pf4j.ManifestPluginDescriptorFinder; +import org.pf4j.util.StringUtils; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +/** + * @author Decebal Suiu + */ +public class PluginManifest { + + private final String pluginId; + private final String pluginClass; + private final String pluginVersion; + private final String pluginDescription; + private final String pluginProvider; + private final List pluginDependencies; + private final String pluginRequires; + private final String pluginLicense; + + private Manifest manifest; + + protected PluginManifest(Builder builder) { + this.pluginId = builder.pluginId; + this.pluginClass = builder.pluginClass; + this.pluginVersion = builder.pluginVersion; + this.pluginDescription = builder.pluginDescription; + this.pluginProvider = builder.pluginProvider; + this.pluginDependencies = builder.pluginDependencies; + this.pluginRequires = builder.pluginRequires; + this.pluginLicense = builder.pluginLicense; + } + + public String pluginId() { + return pluginId; + } + + public String pluginClass() { + return pluginClass; + } + + public String pluginVersion() { + return pluginVersion; + } + + public String pluginDescription() { + return pluginDescription; + } + + public String pluginProvider() { + return pluginProvider; + } + + public List pluginDependencies() { + return pluginDependencies; + } + + public String pluginRequires() { + return pluginRequires; + } + + public String pluginLicense() { + return pluginLicense; + } + + public Manifest manifest() { + if (manifest == null) { + Map map = new LinkedHashMap<>(); + map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, pluginId); + + if (StringUtils.isNotNullOrEmpty(pluginVersion)) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); + } + + if (StringUtils.isNotNullOrEmpty(pluginClass)) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); + } + + if (StringUtils.isNotNullOrEmpty(pluginDescription)) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_DESCRIPTION, pluginDescription); + } + + if (StringUtils.isNotNullOrEmpty(pluginProvider)) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, pluginProvider); + } + + if (StringUtils.isNotNullOrEmpty(pluginProvider)) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, pluginProvider); + } + + if (pluginDependencies != null && !pluginDependencies.isEmpty()) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_DEPENDENCIES, String.join(",", pluginDependencies)); + } + + if (StringUtils.isNotNullOrEmpty(pluginRequires)) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_REQUIRES, pluginRequires); + } + + + if (StringUtils.isNotNullOrEmpty(pluginLicense)) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_LICENSE, pluginLicense); + } + + manifest = new Manifest(); + Attributes attributes = manifest.getMainAttributes(); + attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0"); + for (Map.Entry entry : map.entrySet()) { + attributes.put(new Attributes.Name(entry.getKey()), entry.getValue()); + } + } + + return manifest; + } + + public static class Builder { + + private final String pluginId; + + private String pluginClass; + private String pluginVersion; + private String pluginDescription; + private String pluginProvider; + private List pluginDependencies; + private String pluginRequires; + private String pluginLicense; + + public Builder(String pluginId) { + this.pluginId = pluginId; + } + + public Builder pluginClass(String pluginClass) { + this.pluginClass = pluginClass; + + return this; + } + + public Builder pluginVersion(String pluginVersion) { + this.pluginVersion = pluginVersion; + + return this; + } + + public Builder pluginDescription(String pluginDescription) { + this.pluginDescription = pluginDescription; + + return this; + } + + public Builder pluginProvider(String pluginProvider) { + this.pluginProvider = pluginProvider; + + return this; + } + + public Builder pluginDependencies(List pluginDependencies) { + this.pluginDependencies = pluginDependencies; + + return this; + } + + public Builder pluginDependency(String pluginDependency) { + if (pluginDependencies == null) { + pluginDependencies = new LinkedList<>(); + } + + pluginDependencies.add(pluginDependency); + + return this; + } + + public Builder pluginRequires(String pluginRequires) { + this.pluginRequires = pluginRequires; + + return this; + } + + public Builder pluginLicense(String pluginLicense) { + this.pluginLicense = pluginLicense; + + return this; + } + + public PluginManifest build() { + return new PluginManifest(this); + } + + } + +} diff --git a/pf4j/src/test/java/org/pf4j/test/PluginProperties.java b/pf4j/src/test/java/org/pf4j/test/PluginProperties.java new file mode 100644 index 0000000..a7b6296 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/PluginProperties.java @@ -0,0 +1,186 @@ +package org.pf4j.test; + +import org.pf4j.PropertiesPluginDescriptorFinder; +import org.pf4j.util.StringUtils; + +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +/** + * @author Decebal Suiu + */ +public class PluginProperties { + + private final String pluginId; + private final String pluginClass; + private final String pluginVersion; + private final String pluginDescription; + private final String pluginProvider; + private final List pluginDependencies; + private final String pluginRequires; + private final String pluginLicense; + + private Properties properties; + + protected PluginProperties(Builder builder) { + this.pluginId = builder.pluginId; + this.pluginClass = builder.pluginClass; + this.pluginVersion = builder.pluginVersion; + this.pluginDescription = builder.pluginDescription; + this.pluginProvider = builder.pluginProvider; + this.pluginDependencies = builder.pluginDependencies; + this.pluginRequires = builder.pluginRequires; + this.pluginLicense = builder.pluginLicense; + } + + public String pluginId() { + return pluginId; + } + + public String pluginClass() { + return pluginClass; + } + + public String pluginVersion() { + return pluginVersion; + } + + public String pluginDescription() { + return pluginDescription; + } + + public String pluginProvider() { + return pluginProvider; + } + + public List pluginDependencies() { + return pluginDependencies; + } + + public String pluginRequires() { + return pluginRequires; + } + + public String pluginLicense() { + return pluginLicense; + } + + public Properties properties() { + if (properties == null) { + properties = new Properties(); + + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, pluginId); + + if (StringUtils.isNotNullOrEmpty(pluginVersion)) { + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); + } + + if (StringUtils.isNotNullOrEmpty(pluginClass)) { + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); + } + + if (StringUtils.isNotNullOrEmpty(pluginDescription)) { + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_DESCRIPTION, pluginDescription); + } + + if (StringUtils.isNotNullOrEmpty(pluginProvider)) { + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, pluginProvider); + } + + if (StringUtils.isNotNullOrEmpty(pluginProvider)) { + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, pluginProvider); + } + + if (pluginDependencies != null && !pluginDependencies.isEmpty()) { + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, String.join(",", pluginDependencies)); + } + + if (StringUtils.isNotNullOrEmpty(pluginRequires)) { + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, pluginRequires); + } + + + if (StringUtils.isNotNullOrEmpty(pluginLicense)) { + properties.put(PropertiesPluginDescriptorFinder.PLUGIN_LICENSE, pluginLicense); + } + } + + return properties; + } + + public static class Builder { + + private final String pluginId; + + private String pluginClass; + private String pluginVersion; + private String pluginDescription; + private String pluginProvider; + private List pluginDependencies; + private String pluginRequires; + private String pluginLicense; + + public Builder(String pluginId) { + this.pluginId = pluginId; + } + + public Builder pluginClass(String pluginClass) { + this.pluginClass = pluginClass; + + return this; + } + + public Builder pluginVersion(String pluginVersion) { + this.pluginVersion = pluginVersion; + + return this; + } + + public Builder pluginDescription(String pluginDescription) { + this.pluginDescription = pluginDescription; + + return this; + } + + public Builder pluginProvider(String pluginProvider) { + this.pluginProvider = pluginProvider; + + return this; + } + + public Builder pluginDependencies(List pluginDependencies) { + this.pluginDependencies = pluginDependencies; + + return this; + } + + public Builder pluginDependency(String pluginDependency) { + if (pluginDependencies == null) { + pluginDependencies = new LinkedList<>(); + } + + pluginDependencies.add(pluginDependency); + + return this; + } + + public Builder pluginRequires(String pluginRequires) { + this.pluginRequires = pluginRequires; + + return this; + } + + public Builder pluginLicense(String pluginLicense) { + this.pluginLicense = pluginLicense; + + return this; + } + + public PluginProperties build() { + return new PluginProperties(this); + } + + } + +} diff --git a/pf4j/src/test/java/org/pf4j/test/PluginZip.java b/pf4j/src/test/java/org/pf4j/test/PluginZip.java index 1f20fe2..d22705a 100644 --- a/pf4j/src/test/java/org/pf4j/test/PluginZip.java +++ b/pf4j/src/test/java/org/pf4j/test/PluginZip.java @@ -22,7 +22,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -35,17 +34,11 @@ import java.util.zip.ZipOutputStream; public class PluginZip { private final Path path; - private final String pluginId; - private final String pluginClass; - private final String pluginVersion; - private final String pluginDependencies; + private final PluginProperties properties; protected PluginZip(Builder builder) { this.path = builder.path; - this.pluginId = builder.pluginId; - this.pluginClass = builder.pluginClass; - this.pluginVersion = builder.pluginVersion; - this.pluginDependencies = builder.pluginDependencies; + this.properties = builder.properties; } public Path path() { @@ -53,19 +46,17 @@ public class PluginZip { } public String pluginId() { - return pluginId; + return properties.pluginId(); } public String pluginClass() { - return pluginClass; + return properties.pluginClass(); } public String pluginVersion() { - return pluginVersion; + return properties.pluginVersion(); } - public String pluginDependencies() { return pluginDependencies; } - public Path unzippedPath() { Path path = path(); String fileName = path.getFileName().toString(); @@ -73,65 +64,16 @@ public class PluginZip { return path.getParent().resolve(fileName.substring(0, fileName.length() - 4)); // without ".zip" suffix } - public static Properties createProperties(Map map) { - Properties properties = new Properties(); - properties.putAll(map); - - return properties; - } - public static class Builder { private final Path path; - private final String pluginId; + private final PluginProperties properties; - private String pluginClass; - private String pluginVersion; - private String pluginDependencies; - private Map properties = new LinkedHashMap<>(); private Map files = new LinkedHashMap<>(); - public Builder(Path path, String pluginId) { + public Builder(Path path, PluginProperties properties) { this.path = path; - this.pluginId = pluginId; - } - - public Builder pluginClass(String pluginClass) { - this.pluginClass = pluginClass; - - return this; - } - - public Builder pluginVersion(String pluginVersion) { - this.pluginVersion = pluginVersion; - - return this; - } - - public Builder pluginDependencies(String pluginDependencies) { - this.pluginDependencies = pluginDependencies; - - return this; - } - - /** - * Add extra properties to the {@code properties} file. - * As possible attribute name please see {@link PropertiesPluginDescriptorFinder}. - */ - public Builder properties(Map properties) { - this.properties.putAll(properties); - - return this; - } - - /** - * Add extra property to the {@code properties} file. - * As possible property name please see {@link PropertiesPluginDescriptorFinder}. - */ - public Builder property(String name, String value) { - properties.put(name, value); - - return this; + this.properties = properties; } /** @@ -165,23 +107,10 @@ public class PluginZip { } protected void createPropertiesFile() throws IOException { - Map map = new LinkedHashMap<>(); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, pluginId); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); - if (pluginDependencies != null) { - map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, pluginDependencies); - } - if (pluginClass != null) { - map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); - } - if (properties != null) { - map.putAll(properties); - } - try (ZipOutputStream outputStream = new ZipOutputStream(Files.newOutputStream(path))) { ZipEntry propertiesFile = new ZipEntry(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); outputStream.putNextEntry(propertiesFile); - createProperties(map).store(outputStream, ""); + properties.properties().store(outputStream, ""); outputStream.closeEntry(); for (Map.Entry fileEntry : files.entrySet()) { diff --git a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java index 078e946..1a9de22 100644 --- a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java +++ b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java @@ -17,6 +17,7 @@ package org.pf4j.util; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.pf4j.test.PluginProperties; import org.pf4j.test.PluginZip; import org.pf4j.util.io.ZipPathFilter; @@ -37,8 +38,8 @@ class FileUtilsTest { @Test void expandIfZipForZipWithOnlyModuleDescriptor() throws IOException { - PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") - .pluginVersion("1.2.3") + PluginProperties pluginProperties = createPluginProperties(); + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); Path unzipped = FileUtils.expandIfZip(pluginZip.path()); @@ -48,8 +49,8 @@ class FileUtilsTest { @Test void expandIfZipForZipWithResourceFile() throws IOException { - PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-second-plugin-1.2.3.zip"), "myPlugin") - .pluginVersion("1.2.3") + PluginProperties pluginProperties = createPluginProperties(); + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-second-plugin-1.2.3.zip"), pluginProperties) .addFile(Paths.get("classes/META-INF/plugin-file"), "plugin") .build(); @@ -71,8 +72,8 @@ class FileUtilsTest { @Test void findPaths() throws IOException { - PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") - .pluginVersion("1.2.3") + PluginProperties pluginProperties = createPluginProperties(); + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginProperties) .build(); Path unzipped = FileUtils.expandIfZip(pluginZip.path()); @@ -83,4 +84,10 @@ class FileUtilsTest { assertEquals(1, zipPaths.size()); } + private PluginProperties createPluginProperties() { + return new PluginProperties.Builder("myPlugin") + .pluginVersion("1.2.3") + .build(); + } + }