From 4eeaf8ab558da4a6974e4cb5deccc57c32d620f9 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Tue, 12 Mar 2019 20:28:47 +0200 Subject: [PATCH 01/54] Resolve #294 --- .../main/java/org/pf4j/DefaultPluginManager.java | 8 ++++---- pf4j/src/test/java/org/pf4j/LoadPluginsTest.java | 14 +++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java index 96a4104..7e90388 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java @@ -89,15 +89,15 @@ public class DefaultPluginManager extends AbstractPluginManager { @Override protected PluginRepository createPluginRepository() { return new CompoundPluginRepository() - .add(new DefaultPluginRepository(getPluginsRoot(), isDevelopment())) - .add(new JarPluginRepository(getPluginsRoot())); + .add(new JarPluginRepository(getPluginsRoot())) + .add(new DefaultPluginRepository(getPluginsRoot(), isDevelopment())); } @Override protected PluginLoader createPluginLoader() { return new CompoundPluginLoader() - .add(new DefaultPluginLoader(this, pluginClasspath)) - .add(new JarPluginLoader(this)); + .add(new JarPluginLoader(this)) + .add(new DefaultPluginLoader(this, pluginClasspath)); } @Override diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java index c2917e8..46980bc 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java @@ -45,7 +45,19 @@ public class LoadPluginsTest { @Before public void setUp() { - pluginManager = new DefaultPluginManager(pluginsFolder.getRoot().toPath()); + pluginManager = new DefaultPluginManager(pluginsFolder.getRoot().toPath()) { + + @Override + protected PluginRepository createPluginRepository() { + return new DefaultPluginRepository(getPluginsRoot(), isDevelopment()); + } + + @Override + protected PluginLoader createPluginLoader() { + return new DefaultPluginLoader(this, pluginClasspath); + } + + }; } @Test From ce81809c526926799a3ac323b7f6ee509c3ee3b8 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Wed, 13 Mar 2019 22:35:35 +0200 Subject: [PATCH 02/54] Development is done on Java 11 (OpenJDK) --- .travis.yml | 4 ---- pom.xml | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 90b2770..b2e4fb7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,5 @@ language: java jdk: - - openjdk7 -# JDK7 is not supported anymore; https://github.com/travis-ci/travis-ci/issues/7884#issuecomment-308451879 -# - oraclejdk7 - - oraclejdk8 - openjdk11 after_success: - mvn clean cobertura:cobertura coveralls:report diff --git a/pom.xml b/pom.xml index d4540d7..d3904e2 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,9 @@ UTF-8 - 1.7 + 1.8 + 1.8 + 1.7.25 7.1 @@ -66,8 +68,6 @@ 3.8.0 true - ${java.version} - ${java.version} From 4ad1f4fe2a45ffc059b1bf1ff17cfb0e6d1daec3 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Wed, 13 Mar 2019 22:37:05 +0200 Subject: [PATCH 03/54] Fix deprecated class --- .../ServiceProviderExtensionStorageTest.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java b/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java index 2c450a0..d152081 100644 --- a/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java +++ b/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java @@ -23,12 +23,16 @@ import javax.tools.FileObject; import javax.tools.StandardLocation; import java.io.IOException; import java.io.StringReader; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; /** @@ -46,7 +50,6 @@ public class ServiceProviderExtensionStorageTest { assertThat(entries.contains("World"), is(true)); } - @Test public void ensureReadingExtensionsProducesCorrectListOfExtensions() { final StringReader file = new StringReader("#hello\n World"); @@ -56,6 +59,7 @@ public class ServiceProviderExtensionStorageTest { given(processor.getExtensions()).willReturn(extensions); ServiceProviderExtensionStorage extensionStorage = new ServiceProviderExtensionStorage(processor) { + @Override protected Filer getFiler() { try { @@ -72,6 +76,7 @@ public class ServiceProviderExtensionStorageTest { throw new IllegalStateException("Shouldn't have gotten here"); } } + }; Map> read = extensionStorage.read(); From e025d6704c59ef94e810860f9974f9c424958165 Mon Sep 17 00:00:00 2001 From: Andreas Rudolph Date: Tue, 19 Mar 2019 19:19:53 +0100 Subject: [PATCH 04/54] Provide a module descriptor for Java 9+ (#300) --- pf4j/pom.xml | 49 ++++++++++++++++++++--------- pf4j/src/main/java/module-info.java | 47 +++++++++++++++++++++++++++ pom.xml | 3 +- 3 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 pf4j/src/main/java/module-info.java diff --git a/pf4j/pom.xml b/pf4j/pom.xml index 061412d..8995e5a 100644 --- a/pf4j/pom.xml +++ b/pf4j/pom.xml @@ -22,17 +22,35 @@ -proc:none - - - org.apache.maven.plugins - maven-jar-plugin - - - - org.pf4j - - - + + + + default-compile + + compile + + + + module-info.java + + + + + + + java9-compile + + compile + + + 9 + true + + module-info.java + + + + @@ -69,11 +87,12 @@ - + See http://hamcrest.org/JavaHamcrest/distributables#upgrading-from-hamcrest-1x + --> org.hamcrest hamcrest-core ${hamcrest.version} diff --git a/pf4j/src/main/java/module-info.java b/pf4j/src/main/java/module-info.java new file mode 100644 index 0000000..754b9b8 --- /dev/null +++ b/pf4j/src/main/java/module-info.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Module descriptor for PF4J. + * + * @author Decebal Suiu + * @author Andreas Rudolph + */ +module org.pf4j { + requires java.base; + + // provides javax.annotation + requires java.compiler; + + // provided by the ASM library + requires org.objectweb.asm; + + // The SLF4J library currently does not provide a module. + // Version 1.8 provides a module called "org.slf4j". But this version is + // currently in beta stage. Therefore I'm not sure, if we already like to + // use it. + requires slf4j.api; + + // The java-semver library currently does not provide a module. + // Maybe we should send them a pull request, that at least they provide an + // automatic module name in their MANIFEST file. + requires java.semver; + + // Maybe we should reconsider the package hierarchy, that only classes are + // exported, which are required by 3rd party developers. + exports org.pf4j; + exports org.pf4j.processor; +} diff --git a/pom.xml b/pom.xml index d3904e2..ef5f937 100644 --- a/pom.xml +++ b/pom.xml @@ -43,8 +43,7 @@ UTF-8 - 1.8 - 1.8 + 8 1.7.25 7.1 From 45689ff80f2324595b3226eb7590ebc4b9e13871 Mon Sep 17 00:00:00 2001 From: Andreas Rudolph Date: Tue, 19 Mar 2019 19:20:24 +0100 Subject: [PATCH 05/54] set version number to 3.0.0-SNAPSHOT (#301) --- demo/api/pom.xml | 4 ++-- demo/app/pom.xml | 4 ++-- demo/plugins/plugin1/pom.xml | 4 ++-- demo/plugins/plugin2/pom.xml | 4 ++-- demo/plugins/pom.xml | 4 ++-- demo/pom.xml | 4 ++-- pf4j/pom.xml | 4 ++-- pom.xml | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/demo/api/pom.xml b/demo/api/pom.xml index 723e602..9a5f33f 100644 --- a/demo/api/pom.xml +++ b/demo/api/pom.xml @@ -4,12 +4,12 @@ org.pf4j.demo pf4j-demo-parent - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT 4.0.0 pf4j-demo-api - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT jar Demo Api diff --git a/demo/app/pom.xml b/demo/app/pom.xml index 3335fbe..4cb624c 100644 --- a/demo/app/pom.xml +++ b/demo/app/pom.xml @@ -4,12 +4,12 @@ org.pf4j.demo pf4j-demo-parent - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT 4.0.0 pf4j-demo-app - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT jar Demo App diff --git a/demo/plugins/plugin1/pom.xml b/demo/plugins/plugin1/pom.xml index 4695489..51e4ff9 100644 --- a/demo/plugins/plugin1/pom.xml +++ b/demo/plugins/plugin1/pom.xml @@ -4,12 +4,12 @@ org.pf4j.demo pf4j-demo-plugins - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT 4.0.0 pf4j-demo-plugin1 - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT jar Demo Plugin #1 diff --git a/demo/plugins/plugin2/pom.xml b/demo/plugins/plugin2/pom.xml index 40e19b1..db67c4b 100644 --- a/demo/plugins/plugin2/pom.xml +++ b/demo/plugins/plugin2/pom.xml @@ -4,12 +4,12 @@ org.pf4j.demo pf4j-demo-plugins - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT 4.0.0 pf4j-demo-plugin2 - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT jar Demo Plugin #2 diff --git a/demo/plugins/pom.xml b/demo/plugins/pom.xml index 4460964..f3197ea 100644 --- a/demo/plugins/pom.xml +++ b/demo/plugins/pom.xml @@ -4,12 +4,12 @@ org.pf4j.demo pf4j-demo-parent - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT 4.0.0 pf4j-demo-plugins - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT pom Demo Plugins Parent diff --git a/demo/pom.xml b/demo/pom.xml index 2d046b5..fc182e5 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -4,13 +4,13 @@ org.pf4j pf4j-parent - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT 4.0.0 org.pf4j.demo pf4j-demo-parent - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT pom Demo Parent diff --git a/pf4j/pom.xml b/pf4j/pom.xml index 8995e5a..1d07836 100644 --- a/pf4j/pom.xml +++ b/pf4j/pom.xml @@ -4,12 +4,12 @@ org.pf4j pf4j-parent - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT 4.0.0 pf4j - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT jar PF4J Plugin Framework for Java diff --git a/pom.xml b/pom.xml index ef5f937..ddfde0f 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 org.pf4j pf4j-parent - 2.7.0-SNAPSHOT + 3.0.0-SNAPSHOT pom PF4J Parent Plugin Framework for Java From 9137bff8bd45d84cd22a34b65026bc9de7cf9d4e Mon Sep 17 00:00:00 2001 From: Andreas Rudolph Date: Wed, 20 Mar 2019 19:01:24 +0100 Subject: [PATCH 06/54] compile demo plugins for Java 8 (#302) --- demo/plugins/pom.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/demo/plugins/pom.xml b/demo/plugins/pom.xml index f3197ea..589951a 100644 --- a/demo/plugins/pom.xml +++ b/demo/plugins/pom.xml @@ -16,7 +16,6 @@ UTF-8 UTF-8 - 1.7 @@ -28,14 +27,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - - ${java.version} - ${java.version} - - org.apache.maven.plugins maven-assembly-plugin From e1fb3f7bc411cdfc3eee0cacedc8f7b1a238b7cd Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Wed, 20 Mar 2019 22:53:20 +0200 Subject: [PATCH 07/54] Migrate to JUnit 5 --- pf4j/pom.xml | 5 +- .../org/pf4j/AbstractExtensionFinderTest.java | 12 +-- .../CompoundPluginDescriptorFinderTest.java | 30 ++++--- .../org/pf4j/DefaultExtensionFactoryTest.java | 7 +- .../org/pf4j/DefaultPluginFactoryTest.java | 8 +- .../org/pf4j/DefaultPluginManagerTest.java | 42 +++++----- .../org/pf4j/DefaultPluginRepositoryTest.java | 42 +++++----- .../pf4j/DefaultPluginStatusProviderTest.java | 30 +++---- .../org/pf4j/DefaultVersionManagerTest.java | 18 +++-- .../java/org/pf4j/DependencyResolverTest.java | 10 ++- .../ExtensionAnnotationProcessorTest.java | 6 +- .../org/pf4j/LegacyExtensionStorageTest.java | 4 +- .../test/java/org/pf4j/LoadPluginsTest.java | 79 ++++++++++--------- .../ManifestPluginDescriptorFinderTest.java | 39 +++++---- .../java/org/pf4j/PluginDependencyTest.java | 19 +++-- .../PropertiesPluginDescriptorFinderTest.java | 42 +++++----- .../pf4j/SingletonExtensionFactoryTest.java | 5 +- .../test/java/org/pf4j/plugin/PluginZip.java | 19 ++--- .../ServiceProviderExtensionStorageTest.java | 4 +- .../java/org/pf4j/util/FileUtilsTest.java | 18 ++--- pom.xml | 2 +- 21 files changed, 213 insertions(+), 228 deletions(-) diff --git a/pf4j/pom.xml b/pf4j/pom.xml index 1d07836..0a78ed2 100644 --- a/pf4j/pom.xml +++ b/pf4j/pom.xml @@ -100,11 +100,12 @@ - junit - junit + org.junit.jupiter + junit-jupiter-engine ${junit.version} test + org.mockito mockito-core diff --git a/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java index 2acabee..6383756 100644 --- a/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java @@ -15,9 +15,9 @@ */ package org.pf4j; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.pf4j.plugin.FailTestPlugin; import org.pf4j.plugin.TestExtensionPoint; @@ -28,7 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Set; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -40,7 +40,7 @@ public class AbstractExtensionFinderTest { private PluginManager pluginManager; - @Before + @BeforeEach public void setUp() { PluginWrapper pluginStarted = mock(PluginWrapper.class); when(pluginStarted.getPluginClassLoader()).thenReturn(getClass().getClassLoader()); @@ -57,7 +57,7 @@ public class AbstractExtensionFinderTest { when(pluginManager.getExtensionFactory()).thenReturn(new DefaultExtensionFactory()); } - @After + @AfterEach public void tearDown() { pluginManager = null; } diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java index a30a4ff..518ba1e 100644 --- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java @@ -15,28 +15,27 @@ */ package org.pf4j; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.pf4j.plugin.PluginZip; -import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.List; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * @author Decebal Suiu */ public class CompoundPluginDescriptorFinderTest { - @Rule - public TemporaryFolder pluginsFolder = new TemporaryFolder(); + @TempDir + Path pluginsPath; @Test public void add() { @@ -49,7 +48,8 @@ public class CompoundPluginDescriptorFinderTest { @Test public void find() throws Exception { - Path pluginPath = pluginsFolder.newFolder("test-plugin-1").toPath(); + Path pluginPath = pluginsPath.resolve("test-plugin-1"); + Files.createDirectories(pluginPath); Files.write(pluginPath.resolve("plugin.properties"), getPlugin1Properties(), StandardCharsets.UTF_8); PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder() @@ -66,7 +66,7 @@ public class CompoundPluginDescriptorFinderTest { PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder() .add(new PropertiesPluginDescriptorFinder()); - PluginZip pluginJar = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.jar"), "myPlugin") + PluginZip pluginJar = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin") .pluginVersion("1.2.3") .build(); @@ -76,19 +76,17 @@ public class CompoundPluginDescriptorFinderTest { assertEquals("1.2.3", pluginJar.pluginVersion()); } - @Test(expected = PluginException.class) - public void testNotFound() throws Exception { + @Test + public void testNotFound() { PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder(); - Path pluginsPath = pluginsFolder.getRoot().toPath(); - descriptorFinder.find(pluginsPath.resolve("test-plugin-3")); + assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } @Test public void testSpaceCharacterInFileName() throws Exception { PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder(); - File jar = pluginsFolder.newFile("my plugin-1.2.3.jar"); - PluginZip pluginJar = new PluginZip.Builder(jar, "myPlugin") + PluginZip pluginJar = new PluginZip.Builder(pluginsPath.resolve("my plugin-1.2.3.jar"), "myPlugin") .pluginVersion("1.2.3") .build(); diff --git a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java index 71ffa93..13327cc 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java @@ -15,11 +15,12 @@ */ package org.pf4j; -import org.junit.Test; -import org.pf4j.plugin.TestExtension; +import org.junit.jupiter.api.Test; import org.pf4j.plugin.FailTestExtension; +import org.pf4j.plugin.TestExtension; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; /** * diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java index f105aa8..eccfca2 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java @@ -15,15 +15,15 @@ */ package org.pf4j; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.pf4j.plugin.AnotherFailTestPlugin; import org.pf4j.plugin.FailTestPlugin; import org.pf4j.plugin.TestPlugin; import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java index 3e6fd04..ced9b4e 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java @@ -15,21 +15,21 @@ */ package org.pf4j; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.pf4j.plugin.PluginZip; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -38,14 +38,12 @@ public class DefaultPluginManagerTest { private DefaultPluginManager pluginManager; private DefaultPluginDescriptor pluginDescriptor; private PluginWrapper pluginWrapper; - private Path pluginsPath; - @Rule - public TemporaryFolder pluginsFolder = new TemporaryFolder(); + @TempDir + Path pluginsPath; - @Before + @BeforeEach public void setUp() throws IOException { - pluginsPath = pluginsFolder.getRoot().toPath(); pluginManager = new DefaultPluginManager(pluginsPath); pluginDescriptor = new DefaultPluginDescriptor(); @@ -59,7 +57,7 @@ public class DefaultPluginManagerTest { pluginWrapper = new PluginWrapper(pluginManager, pluginDescriptor, Files.createTempDirectory("test"), getClass().getClassLoader()); } - @After + @AfterEach public void tearDown() { pluginManager = null; pluginDescriptor = null; @@ -71,16 +69,16 @@ public class DefaultPluginManagerTest { pluginManager.validatePluginDescriptor(pluginDescriptor); } - @Test(expected = PluginException.class) - public void validateFailsOnId() throws PluginException { + @Test + public void validateFailsOnId() { pluginDescriptor.setPluginId(""); - pluginManager.validatePluginDescriptor(pluginDescriptor); + assertThrows(PluginException.class, () -> pluginManager.validatePluginDescriptor(pluginDescriptor)); } - @Test(expected = PluginException.class) - public void validateFailsOnVersion() throws PluginException { + @Test + public void validateFailsOnVersion() { pluginDescriptor.setPluginVersion(null); - pluginManager.validatePluginDescriptor(pluginDescriptor); + assertThrows(PluginException.class, () -> pluginManager.validatePluginDescriptor(pluginDescriptor)); } @Test @@ -132,7 +130,7 @@ public class DefaultPluginManagerTest { */ @Test public void testPluginDisabledNoStart() throws IOException { - new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin") + new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "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 4f39f24..91a35f5 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -15,20 +15,18 @@ */ package org.pf4j; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Mario Franco @@ -36,25 +34,21 @@ import static org.junit.Assert.assertTrue; */ public class DefaultPluginRepositoryTest { - private Path pluginsPath; + @TempDir + Path pluginsPath; - @Rule - public TemporaryFolder pluginsFolder = new TemporaryFolder(); - - @Before + @BeforeEach public void setUp() throws IOException { - pluginsPath = pluginsFolder.getRoot().toPath(); - - pluginsFolder.newFolder("plugin-1"); + Path plugin1Path = Files.createDirectories(pluginsPath.resolve("plugin-1")); // Prove that we can delete a folder with a file inside - Files.createFile(Paths.get(pluginsFolder.getRoot().getAbsolutePath()).resolve("plugin-1").resolve("myfile")); + Files.createFile(plugin1Path.resolve("myfile")); // Create a zip file for plugin-1 to test that it is deleted when plugin is deleted - Files.createFile(Paths.get(pluginsFolder.getRoot().getAbsolutePath()).resolve("plugin-1.zip")); - pluginsFolder.newFolder("plugin-2"); - pluginsFolder.newFolder("plugin-3"); + Files.createFile(pluginsPath.resolve("plugin-1.zip")); + Files.createDirectories(pluginsPath.resolve("plugin-2")); + Files.createDirectories(pluginsPath.resolve("plugin-3")); // standard maven/gradle bin folder - these should be skipped in development mode because the cause errors - pluginsFolder.newFolder("target"); - pluginsFolder.newFolder("build"); + Files.createDirectories(pluginsPath.resolve("target")); + Files.createDirectories(pluginsPath.resolve("build")); } /** @@ -109,11 +103,11 @@ public class DefaultPluginRepositoryTest { } private void assertPathExists(List paths, Path path) { - assertTrue("The directory must contain the file " + path, paths.contains(path)); + assertTrue(paths.contains(path), "The directory must contain the file " + path); } private void assertPathDoesNotExists(List paths, Path path) { - assertFalse("The directory must not contain the file " + path, paths.contains(path)); + assertFalse(paths.contains(path), "The directory must not contain the file " + path); } } diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java index b3f8d2b..635e41c 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java @@ -15,20 +15,17 @@ */ package org.pf4j; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.pf4j.util.FileUtils; -import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Mario Franco @@ -36,15 +33,8 @@ import static org.junit.Assert.assertTrue; */ public class DefaultPluginStatusProviderTest { - private Path pluginsPath; - - @Rule - public TemporaryFolder pluginsFolder = new TemporaryFolder(); - - @Before - public void setUp() { - pluginsPath = pluginsFolder.getRoot().toPath(); - } + @TempDir + Path pluginsPath; @Test public void testIsPluginDisabled() throws IOException { @@ -129,8 +119,8 @@ public class DefaultPluginStatusProviderTest { List disabledPlugins = new ArrayList<>(); disabledPlugins.add("plugin-2"); - File disabledFile = pluginsFolder.newFile("disabled.txt"); - FileUtils.writeLines(disabledPlugins, disabledFile); + Path disabledPath = pluginsPath.resolve("disabled.txt"); + FileUtils.writeLines(disabledPlugins, disabledPath.toFile()); } private void createEnabledFile() throws IOException { @@ -138,8 +128,8 @@ public class DefaultPluginStatusProviderTest { enabledPlugins.add("plugin-1"); enabledPlugins.add("plugin-2"); - File enabledFile = pluginsFolder.newFile("enabled.txt"); - FileUtils.writeLines(enabledPlugins, enabledFile); + Path enabledPath = pluginsPath.resolve("enabled.txt"); + FileUtils.writeLines(enabledPlugins, enabledPath.toFile()); } } diff --git a/pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java index 795d3cf..3a277db 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java @@ -16,10 +16,12 @@ package org.pf4j; import com.github.zafarkhaja.semver.ParseException; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Decebal Suiu @@ -28,7 +30,7 @@ public class DefaultVersionManagerTest { private VersionManager versionManager; - @Before + @BeforeEach public void init() { versionManager = new DefaultVersionManager(); } @@ -39,14 +41,14 @@ public class DefaultVersionManagerTest { assertTrue(versionManager.checkVersionConstraint("1.4.3", ">=1.4.0 & <1.6.0")); // range } - @Test(expected = IllegalArgumentException.class) + @Test public void nullOrEmptyVersion() { - assertFalse(versionManager.checkVersionConstraint(null, ">2.0.0")); + assertThrows(IllegalArgumentException.class, () -> versionManager.checkVersionConstraint(null, ">2.0.0")); } - @Test(expected = ParseException.class) + @Test public void invalidVersion() { - assertFalse(versionManager.checkVersionConstraint("1.0", ">2.0.0")); + assertThrows(ParseException.class, () -> versionManager.checkVersionConstraint("1.0", ">2.0.0")); } @Test diff --git a/pf4j/src/test/java/org/pf4j/DependencyResolverTest.java b/pf4j/src/test/java/org/pf4j/DependencyResolverTest.java index f7752d4..6e35780 100644 --- a/pf4j/src/test/java/org/pf4j/DependencyResolverTest.java +++ b/pf4j/src/test/java/org/pf4j/DependencyResolverTest.java @@ -15,14 +15,16 @@ */ package org.pf4j; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Decebal Suiu @@ -31,7 +33,7 @@ public class DependencyResolverTest { private DependencyResolver resolver; - @Before + @BeforeEach public void init() { VersionManager versionManager = new DefaultVersionManager(); resolver = new DependencyResolver(versionManager); diff --git a/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java b/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java index 9edd6b9..47efca8 100644 --- a/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java +++ b/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java @@ -15,13 +15,13 @@ */ package org.pf4j; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.pf4j.processor.ExtensionAnnotationProcessor; import java.util.Set; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Mario Franco diff --git a/pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java b/pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java index 57125bd..1acc567 100644 --- a/pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java +++ b/pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java @@ -15,7 +15,7 @@ */ package org.pf4j; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.pf4j.processor.LegacyExtensionStorage; import java.io.IOException; @@ -24,7 +24,7 @@ import java.io.StringReader; import java.util.HashSet; import java.util.Set; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; /** * @author Decebal Suiu diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java index 46980bc..f86cee4 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java @@ -15,37 +15,37 @@ */ package org.pf4j; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.startsWith; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.File; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.pf4j.plugin.PluginZip; + import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.pf4j.plugin.PluginZip; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; public class LoadPluginsTest { private DefaultPluginManager pluginManager; - @Rule - public TemporaryFolder pluginsFolder = new TemporaryFolder(); + @TempDir + Path pluginsPath; - @Before + @BeforeEach public void setUp() { - pluginManager = new DefaultPluginManager(pluginsFolder.getRoot().toPath()) { + pluginManager = new DefaultPluginManager(pluginsPath) { @Override protected PluginRepository createPluginRepository() { @@ -62,7 +62,7 @@ public class LoadPluginsTest { @Test public void load() throws Exception { - PluginZip pluginZip = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin") + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); @@ -76,31 +76,32 @@ public class LoadPluginsTest { assertEquals(pluginZip.pluginId(), pluginManager.idForPath(pluginZip.unzippedPath())); } - @Test(expected = IllegalArgumentException.class) + @Test public void loadNonExisting() { - pluginManager.loadPlugin(Paths.get("nonexisting")); + assertThrows(IllegalArgumentException.class, () -> pluginManager.loadPlugin(Paths.get("nonexisting"))); } - @Test(expected = PluginAlreadyLoadedException.class) + @Test public void loadTwiceFails() throws Exception { - PluginZip pluginZip = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin") + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); assertNotNull(pluginManager.loadPluginFromPath(pluginZip.path())); - assertNull(pluginManager.loadPluginFromPath(pluginZip.path())); + + assertThrows(PluginAlreadyLoadedException.class, () -> pluginManager.loadPluginFromPath(pluginZip.path())); } @Test public void loadPluginWithSameIdDifferentPathFails() throws Exception { String pluginId = "myPlugin"; String pluginVersion = "1.2.3"; - File plugin1Path = pluginsFolder.newFile("my-plugin-1.2.3.zip"); + Path plugin1Path = pluginsPath.resolve("my-plugin-1.2.3.zip"); PluginZip plugin1 = new PluginZip.Builder(plugin1Path, pluginId) .pluginVersion(pluginVersion) .build(); - File plugin2Path = pluginsFolder.newFile("my-plugin-1.2.3-renamed.zip"); + Path plugin2Path = pluginsPath.resolve("my-plugin-1.2.3-renamed.zip"); PluginZip plugin2 = new PluginZip.Builder(plugin2Path, pluginId) .pluginVersion(pluginVersion) .build(); @@ -134,13 +135,13 @@ public class LoadPluginsTest { public void loadPluginWithSameIdDifferentVersionsFails() throws Exception { String pluginId = "myPlugin"; String plugin1Version = "1.2.3"; - File plugin1Path = pluginsFolder.newFile("my-plugin-1.2.3.zip"); + Path plugin1Path = pluginsPath.resolve("my-plugin-1.2.3.zip"); PluginZip plugin1 = new PluginZip.Builder(plugin1Path, pluginId) .pluginVersion(plugin1Version) .build(); String plugin2Version = "2.0.0"; - File plugin2Path = pluginsFolder.newFile("my-plugin-2.0.0.zip"); + Path plugin2Path = pluginsPath.resolve("my-plugin-2.0.0.zip"); PluginZip plugin2 = new PluginZip.Builder(plugin2Path, pluginId) .pluginVersion(plugin2Version) .build(); @@ -162,7 +163,7 @@ public class LoadPluginsTest { @Test public void loadUnloadLoad() throws Exception { - PluginZip pluginZip = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin") + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); @@ -181,7 +182,7 @@ public class LoadPluginsTest { public void upgrade() throws Exception { String pluginId = "myPlugin"; - new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), pluginId) + new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginId) .pluginVersion("1.2.3") .build(); @@ -191,7 +192,7 @@ public class LoadPluginsTest { assertEquals(1, pluginManager.getPlugins().size()); assertEquals(1, pluginManager.getStartedPlugins().size()); - PluginZip pluginZip2 = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-2.0.0.ZIP"), pluginId) + PluginZip pluginZip2 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-2.0.0.ZIP"), pluginId) .pluginVersion("2.0.0") .build(); @@ -208,12 +209,12 @@ public class LoadPluginsTest { @Test public void getRoot() { - assertEquals(pluginsFolder.getRoot().toPath(), pluginManager.getPluginsRoot()); + assertEquals(pluginsPath, pluginManager.getPluginsRoot()); } @Test - public void notAPlugin() throws Exception { - pluginsFolder.newFile("not-a-zip"); + public void notAPlugin() { + pluginsPath.resolve("not-a-zip"); pluginManager.loadPlugins(); @@ -222,11 +223,11 @@ public class LoadPluginsTest { @Test public void deletePlugin() throws Exception { - PluginZip pluginZip1 = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin") + PluginZip pluginZip1 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); - PluginZip pluginZip3 = new PluginZip.Builder(pluginsFolder.newFile("other-3.0.0.Zip"), "other") + PluginZip pluginZip3 = new PluginZip.Builder(pluginsPath.resolve("other-3.0.0.Zip"), "other") .pluginVersion("3.0.0") .build(); diff --git a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java index bc4eb5f..1d83c9f 100644 --- a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java @@ -15,19 +15,21 @@ */ package org.pf4j; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Mario Franco @@ -36,40 +38,37 @@ import static org.junit.Assert.*; public class ManifestPluginDescriptorFinderTest { private VersionManager versionManager; - private Path pluginsPath; - @Rule - public TemporaryFolder pluginsFolder = new TemporaryFolder(); + @TempDir + Path pluginsPath; - @Before + @BeforeEach public void setUp() throws IOException { - pluginsPath = pluginsFolder.getRoot().toPath(); - Charset charset = Charset.forName("UTF-8"); - Path pluginPath = pluginsFolder.newFolder("test-plugin-1", "classes", "META-INF").toPath(); + Path pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-1", "classes", "META-INF"))); Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin1Manifest(), charset); - pluginPath = pluginsFolder.newFolder("test-plugin-2", "classes", "META-INF").toPath(); + pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-2", "classes", "META-INF"))); Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin2Manifest(), charset); // empty plugin - pluginsFolder.newFolder("test-plugin-3"); + Files.createDirectories(pluginsPath.resolve("test-plugin-3")); // no plugin class - pluginPath = pluginsFolder.newFolder("test-plugin-4", "classes", "META-INF").toPath(); + pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-4", "classes", "META-INF"))); Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin4Manifest(), charset); // no plugin version - pluginPath = pluginsFolder.newFolder("test-plugin-5", "classes", "META-INF").toPath(); + pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-5", "classes", "META-INF"))); Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin5Manifest(), charset); // no plugin id - pluginPath = pluginsFolder.newFolder("test-plugin-6", "classes", "META-INF").toPath(); + pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-6", "classes", "META-INF"))); Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin6Manifest(), charset); @@ -110,10 +109,10 @@ public class ManifestPluginDescriptorFinderTest { /** * Test of {@link ManifestPluginDescriptorFinder#find(Path)} method. */ - @Test(expected = PluginException.class) - public void testFindNotFound() throws Exception { + @Test + public void testFindNotFound() { PluginDescriptorFinder descriptorFinder = new ManifestPluginDescriptorFinder(); - descriptorFinder.find(pluginsPath.resolve("test-plugin-3")); + assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } private List getPlugin1Manifest() { diff --git a/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java b/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java index dbd5fd9..a351c4b 100644 --- a/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java +++ b/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java @@ -15,9 +15,12 @@ */ package org.pf4j; -import org.junit.Test; -import static org.junit.Assert.*; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Mario Franco @@ -32,33 +35,33 @@ public class PluginDependencyTest { PluginDependency instance = new PluginDependency("test"); assertEquals("test", instance.getPluginId()); assertEquals("*", instance.getPluginVersionSupport()); - assertEquals(false, instance.isOptional()); + assertFalse(instance.isOptional()); instance = new PluginDependency("test@"); assertEquals("test", instance.getPluginId()); assertEquals("*", instance.getPluginVersionSupport()); - assertEquals(false, instance.isOptional()); + assertFalse(instance.isOptional()); instance = new PluginDependency("test?"); assertEquals("test", instance.getPluginId()); assertEquals("*", instance.getPluginVersionSupport()); - assertEquals(true, instance.isOptional()); + assertTrue(instance.isOptional()); instance = new PluginDependency("test?@"); assertEquals("test", instance.getPluginId()); assertEquals("*", instance.getPluginVersionSupport()); - assertEquals(true, instance.isOptional()); + assertTrue(instance.isOptional()); instance = new PluginDependency("test@1.0"); assertEquals("test", instance.getPluginId()); assertEquals("1.0", instance.getPluginVersionSupport()); - assertEquals(false, instance.isOptional()); + assertFalse(instance.isOptional()); assertEquals("PluginDependency [pluginId=test, pluginVersionSupport=1.0, optional=false]", instance.toString()); instance = new PluginDependency("test?@1.0"); assertEquals("test", instance.getPluginId()); assertEquals("1.0", instance.getPluginVersionSupport()); - assertEquals(true, instance.isOptional()); + assertTrue(instance.isOptional()); assertEquals("PluginDependency [pluginId=test, pluginVersionSupport=1.0, optional=true]", instance.toString()); } diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index 377d5ca..7845952 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -15,10 +15,9 @@ */ package org.pf4j; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.pf4j.plugin.PluginZip; import java.io.IOException; @@ -28,41 +27,42 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.List; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public class PropertiesPluginDescriptorFinderTest { private VersionManager versionManager; - private Path pluginsPath; - @Rule - public TemporaryFolder pluginsFolder = new TemporaryFolder(); + @TempDir + Path pluginsPath; - @Before + @BeforeEach public void setUp() throws IOException { - pluginsPath = pluginsFolder.getRoot().toPath(); - Charset charset = Charset.forName("UTF-8"); - Path pluginPath = pluginsFolder.newFolder("test-plugin-1").toPath(); + Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1")); Files.write(pluginPath.resolve("plugin.properties"), getPlugin1Properties(), charset); - pluginPath = pluginsFolder.newFolder("test-plugin-2").toPath(); + pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-2")); Files.write(pluginPath.resolve("plugin.properties"), getPlugin2Properties(), charset); // empty plugin - pluginsFolder.newFolder("test-plugin-3"); + Files.createDirectories(pluginsPath.resolve("test-plugin-3")); // no plugin class - pluginPath = pluginsFolder.newFolder("test-plugin-4").toPath(); + pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-4")); Files.write(pluginPath.resolve("plugin.properties"), getPlugin4Properties(), charset); // no plugin version - pluginPath = pluginsFolder.newFolder("test-plugin-5").toPath(); + pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-5")); Files.write(pluginPath.resolve("plugin.properties"), getPlugin5Properties(), charset); // no plugin id - pluginPath = pluginsFolder.newFolder("test-plugin-6").toPath(); + pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-6")); Files.write(pluginPath.resolve("plugin.properties"), getPlugin6Properties(), charset); versionManager = new DefaultVersionManager(); @@ -99,15 +99,15 @@ public class PropertiesPluginDescriptorFinderTest { assertTrue(versionManager.checkVersionConstraint("1.0.0", plugin2.getRequires())); } - @Test(expected = PluginException.class) - public void testNotFound() throws Exception { + @Test + public void testNotFound() { PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder(); - descriptorFinder.find(pluginsPath.resolve("test-plugin-3")); + assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } @Test public void findInJar() throws Exception { - PluginZip pluginJar = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.jar"), "myPlugin") + PluginZip pluginJar = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin") .pluginVersion("1.2.3") .build(); diff --git a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java index 500dd84..80e7ab0 100644 --- a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java @@ -15,11 +15,12 @@ */ package org.pf4j; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.pf4j.plugin.FailTestExtension; import org.pf4j.plugin.TestExtension; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; /** * @author Decebal Suiu diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java index f069365..72e3241 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java @@ -15,7 +15,6 @@ */ package org.pf4j.plugin; -import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; @@ -31,22 +30,18 @@ import java.util.zip.ZipOutputStream; */ public class PluginZip { - private final File file; + private final Path path; private final String pluginId; private final String pluginVersion; protected PluginZip(Builder builder) { - this.file = builder.file; + this.path = builder.path; this.pluginId = builder.pluginId; this.pluginVersion = builder.pluginVersion; } - public File file() { - return file; - } - public Path path() { - return file.toPath(); + return path; } public String pluginId() { @@ -66,13 +61,13 @@ public class PluginZip { public static class Builder { - private final File file; + private final Path path; private final String pluginId; private String pluginVersion; - public Builder(File file, String pluginId) { - this.file = file; + public Builder(Path path, String pluginId) { + this.path = path; this.pluginId = pluginId; } @@ -94,7 +89,7 @@ public class PluginZip { properties.setProperty("plugin.version", pluginVersion); properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); - ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(file)); + ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(path.toFile())); ZipEntry propertiesFile = new ZipEntry("plugin.properties"); outputStream.putNextEntry(propertiesFile); properties.store(outputStream, ""); diff --git a/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java b/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java index d152081..ac16b23 100644 --- a/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java +++ b/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java @@ -16,7 +16,7 @@ package org.pf4j.processor; -import org.junit.Test; +import org.junit.jupiter.api.Test; import javax.annotation.processing.Filer; import javax.tools.FileObject; @@ -29,8 +29,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; diff --git a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java index 76d0c2e..5f9a3a7 100644 --- a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java +++ b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java @@ -15,24 +15,24 @@ */ package org.pf4j.util; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.pf4j.plugin.PluginZip; import java.nio.file.Files; import java.nio.file.Path; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class FileUtilsTest { - @Rule - public TemporaryFolder testFolder = new TemporaryFolder(); + @TempDir + Path pluginsPath; @Test public void expandIfZip() throws Exception { - PluginZip pluginZip = new PluginZip.Builder(testFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin") + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); @@ -41,10 +41,10 @@ public class FileUtilsTest { assertTrue(Files.exists(unzipped.resolve("plugin.properties"))); // File without .suffix - Path extra = testFolder.newFile("extra").toPath(); + Path extra = pluginsPath.resolve("extra"); assertEquals(extra, FileUtils.expandIfZip(extra)); // Folder - Path folder = testFolder.newFile("folder").toPath(); + Path folder = pluginsPath.resolve("folder"); assertEquals(folder, FileUtils.expandIfZip(folder)); } diff --git a/pom.xml b/pom.xml index ddfde0f..46a432d 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 1.7.25 7.1 - 4.12 + 5.4.0 2.1 2.24.0 2.7 From f38605432b9ad9d91dbb479dcf08a5f53f0fc285 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Wed, 20 Mar 2019 23:05:33 +0200 Subject: [PATCH 08/54] Fix warning --- pf4j/src/main/java/org/pf4j/util/FileUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/util/FileUtils.java b/pf4j/src/main/java/org/pf4j/util/FileUtils.java index a3e955e..5c84b2a 100644 --- a/pf4j/src/main/java/org/pf4j/util/FileUtils.java +++ b/pf4j/src/main/java/org/pf4j/util/FileUtils.java @@ -77,7 +77,7 @@ public class FileUtils { * @throws IOException if something goes wrong */ public static void delete(Path path) throws IOException { - Files.walkFileTree(path, new SimpleFileVisitor() { + Files.walkFileTree(path, new SimpleFileVisitor<>() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { @@ -172,7 +172,8 @@ public class FileUtils { FileTime pluginZipDate = Files.getLastModifiedTime(filePath); String fileName = filePath.getFileName().toString(); - Path pluginDirectory = filePath.resolveSibling(fileName.substring(0, fileName.lastIndexOf("."))); + String directoryName = fileName.substring(0, fileName.lastIndexOf(".")); + Path pluginDirectory = filePath.resolveSibling(directoryName); if (!Files.exists(pluginDirectory) || pluginZipDate.compareTo(Files.getLastModifiedTime(pluginDirectory)) > 0) { // do not overwrite an old version, remove it From 3ffde097b376cfd5f4ce0c9ae4bc44732c0c4d08 Mon Sep 17 00:00:00 2001 From: decebals Date: Thu, 21 Mar 2019 10:56:49 +0200 Subject: [PATCH 09/54] Fix the compilation error introduced by the previous commit --- pf4j/src/main/java/org/pf4j/util/FileUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pf4j/src/main/java/org/pf4j/util/FileUtils.java b/pf4j/src/main/java/org/pf4j/util/FileUtils.java index 5c84b2a..7bd7abe 100644 --- a/pf4j/src/main/java/org/pf4j/util/FileUtils.java +++ b/pf4j/src/main/java/org/pf4j/util/FileUtils.java @@ -77,7 +77,7 @@ public class FileUtils { * @throws IOException if something goes wrong */ public static void delete(Path path) throws IOException { - Files.walkFileTree(path, new SimpleFileVisitor<>() { + Files.walkFileTree(path, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException { From b808c2da4d1378b2adeb64320745752378ff21ac Mon Sep 17 00:00:00 2001 From: Andreas Rudolph Date: Mon, 25 Mar 2019 19:42:20 +0100 Subject: [PATCH 10/54] mark pf4j.jar as multi release library (#305) --- pf4j/pom.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pf4j/pom.xml b/pf4j/pom.xml index 0a78ed2..c38eae8 100644 --- a/pf4j/pom.xml +++ b/pf4j/pom.xml @@ -52,6 +52,17 @@ + + org.apache.maven.plugins + maven-jar-plugin + + + + true + + + + From 6f2f72195943ae2bd5dfcdc7cd6e1a54235257f0 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 29 Mar 2019 19:55:17 +0200 Subject: [PATCH 11/54] Resolve #292 --- .../java/org/pf4j/AbstractPluginManager.java | 16 +++++----------- pf4j/src/main/java/org/pf4j/PluginManager.java | 5 +++-- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index c17fdab..ba12eef 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -173,25 +173,19 @@ public abstract class AbstractPluginManager implements PluginManager { } @Override - public String loadPlugin(Path pluginPath) { + public String loadPlugin(Path pluginPath) throws PluginException { if ((pluginPath == null) || Files.notExists(pluginPath)) { throw new IllegalArgumentException(String.format("Specified plugin %s does not exist!", pluginPath)); } log.debug("Loading plugin from '{}'", pluginPath); - try { - PluginWrapper pluginWrapper = loadPluginFromPath(pluginPath); + PluginWrapper pluginWrapper = loadPluginFromPath(pluginPath); - // try to resolve the loaded plugin together with other possible plugins that depend on this plugin - resolvePlugins(); + // try to resolve the loaded plugin together with other possible plugins that depend on this plugin + resolvePlugins(); - return pluginWrapper.getDescriptor().getPluginId(); - } catch (PluginException e) { - log.error(e.getMessage(), e); - } - - return null; + return pluginWrapper.getDescriptor().getPluginId(); } /** diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java index 6bb6085..c2cbacc 100644 --- a/pf4j/src/main/java/org/pf4j/PluginManager.java +++ b/pf4j/src/main/java/org/pf4j/PluginManager.java @@ -70,9 +70,10 @@ public interface PluginManager { * * @param pluginPath the plugin location * @return the pluginId of the installed plugin as specified in - * its {@linkplain PluginDescriptor metadata}; or {@code null} + * its {@linkplain PluginDescriptor metadata} + * @throws PluginException if load of plugin fails */ - String loadPlugin(Path pluginPath); + String loadPlugin(Path pluginPath) throws PluginException; /** * Start all active plugins. From 6addff34e21dbcd784d38f8b8c5c6259a42b2613 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 1 Apr 2019 22:19:05 +0300 Subject: [PATCH 12/54] Fix warnings --- .../src/main/java/org/pf4j/BasePluginRepository.java | 9 +-------- .../org/pf4j/ManifestPluginDescriptorFinder.java | 2 +- pf4j/src/main/java/org/pf4j/PluginWrapper.java | 6 ++---- .../pf4j/processor/ExtensionAnnotationProcessor.java | 6 +----- pf4j/src/main/java/org/pf4j/util/AndFileFilter.java | 12 +++++------- pf4j/src/main/java/org/pf4j/util/DirectedGraph.java | 10 +++++----- pf4j/src/main/java/org/pf4j/util/OrFileFilter.java | 12 +++++------- 7 files changed, 20 insertions(+), 37 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java index a353756..381059c 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java @@ -48,14 +48,7 @@ public class BasePluginRepository implements PluginRepository { this.filter = filter; // last modified file is first - this.comparator = new Comparator() { - - @Override - public int compare(File o1, File o2) { - return (int) (o2.lastModified() - o1.lastModified()); - } - - }; + this.comparator = (o1, o2) -> (int) (o2.lastModified() - o1.lastModified()); } public void setFilter(FileFilter filter) { diff --git a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java index 74cd0f3..6401f21 100644 --- a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java @@ -78,7 +78,7 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { } } - protected Path getManifestPath(Path pluginPath) throws PluginException { + protected Path getManifestPath(Path pluginPath) { if (Files.isDirectory(pluginPath)) { // legacy (the path is something like "classes/META-INF/MANIFEST.MF") return FileUtils.findFile(pluginPath,"MANIFEST.MF"); diff --git a/pf4j/src/main/java/org/pf4j/PluginWrapper.java b/pf4j/src/main/java/org/pf4j/PluginWrapper.java index c7d93ca..209afb9 100644 --- a/pf4j/src/main/java/org/pf4j/PluginWrapper.java +++ b/pf4j/src/main/java/org/pf4j/PluginWrapper.java @@ -120,11 +120,9 @@ public class PluginWrapper { } PluginWrapper other = (PluginWrapper) obj; - if (!descriptor.getPluginId().equals(other.descriptor.getPluginId())) { - return false; - } - return true; + return descriptor.getPluginId().equals(other.descriptor.getPluginId()); + } @Override diff --git a/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java b/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java index e0f3513..55bbbc2 100644 --- a/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java +++ b/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java @@ -109,11 +109,7 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor { String extension = getBinaryName(extensionElement); for (TypeElement extensionPointElement : extensionPointElements) { String extensionPoint = getBinaryName(extensionPointElement); - Set extensionPoints = extensions.get(extensionPoint); - if (extensionPoints == null) { - extensionPoints = new TreeSet<>(); - extensions.put(extensionPoint, extensionPoints); - } + Set extensionPoints = extensions.computeIfAbsent(extensionPoint, k -> new TreeSet<>()); extensionPoints.add(extension); } } diff --git a/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java b/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java index cc74da4..76a17ec 100644 --- a/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java @@ -23,11 +23,9 @@ import java.util.Collections; import java.util.List; /** - * This filter providing conditional AND logic across a list of - * file filters. This filter returns true if all filters in the - * list return true. Otherwise, it returns false. - * Checking of the file filter list stops when the first filter returns - * false. + * This filter providing conditional AND logic across a list of file filters. + * This filter returns {@code true} if all filters in the list return {@code true}. Otherwise, it returns {@code false}. + * Checking of the file filter list stops when the first filter returns {@code false}. * * @author Decebal Suiu */ @@ -37,7 +35,7 @@ public class AndFileFilter implements FileFilter { private List fileFilters; public AndFileFilter() { - this(new ArrayList()); + this(new ArrayList<>()); } public AndFileFilter(FileFilter... fileFilters) { @@ -68,7 +66,7 @@ public class AndFileFilter implements FileFilter { @Override public boolean accept(File file) { - if (this.fileFilters.size() == 0) { + if (this.fileFilters.isEmpty()) { return false; } diff --git a/pf4j/src/main/java/org/pf4j/util/DirectedGraph.java b/pf4j/src/main/java/org/pf4j/util/DirectedGraph.java index 076d67c..1163f91 100644 --- a/pf4j/src/main/java/org/pf4j/util/DirectedGraph.java +++ b/pf4j/src/main/java/org/pf4j/util/DirectedGraph.java @@ -44,7 +44,7 @@ public class DirectedGraph { return; } - neighbors.put(vertex, new ArrayList()); + neighbors.put(vertex, new ArrayList<>()); } /** @@ -85,7 +85,7 @@ public class DirectedGraph { } public List getNeighbors(V vertex) { - return containsVertex(vertex) ? neighbors.get(vertex) : new ArrayList(); + return containsVertex(vertex) ? neighbors.get(vertex) : new ArrayList<>(); } /** @@ -101,7 +101,7 @@ public class DirectedGraph { } /** - * Report (as a Map) the in-degree (the number of head ends adjacent to a vertex) of each vertex. + * Report (as a {@link Map}) the in-degree (the number of head ends adjacent to a vertex) of each vertex. */ public Map inDegree() { Map result = new HashMap<>(); @@ -181,9 +181,9 @@ public class DirectedGraph { */ @Override public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (V vertex : neighbors.keySet()) { - sb.append("\n " + vertex + " -> " + neighbors.get(vertex)); + sb.append("\n ").append(vertex).append(" -> ").append(neighbors.get(vertex)); } return sb.toString(); diff --git a/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java b/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java index fccfb7b..5798249 100644 --- a/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java +++ b/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java @@ -23,11 +23,9 @@ import java.util.Collections; import java.util.List; /** - * This filter providing conditional OR logic across a list of - * file filters. This filter returns true if one filter in the - * list return true. Otherwise, it returns false. - * Checking of the file filter list stops when the first filter returns - * true. + * This filter providing conditional OR logic across a list of file filters. + * This filter returns {@code true} if one filter in the list return {@code true}. Otherwise, it returns {@code false}. + * Checking of the file filter list stops when the first filter returns {@code true}. * * @author Decebal Suiu */ @@ -37,7 +35,7 @@ public class OrFileFilter implements FileFilter { private List fileFilters; public OrFileFilter() { - this(new ArrayList()); + this(new ArrayList<>()); } public OrFileFilter(FileFilter... fileFilters) { @@ -68,7 +66,7 @@ public class OrFileFilter implements FileFilter { @Override public boolean accept(File file) { - if (this.fileFilters.size() == 0) { + if (this.fileFilters.isEmpty()) { return true; } From ce4c79380398d0c2280f784cd523dfe31026d671 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 1 Apr 2019 22:50:04 +0300 Subject: [PATCH 13/54] Add JarPluginManager and ZipPluginManager --- .../java/org/pf4j/DefaultPluginManager.java | 2 + .../main/java/org/pf4j/JarPluginManager.java | 42 ++++++++++++++++++ .../main/java/org/pf4j/ZipPluginManager.java | 43 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 pf4j/src/main/java/org/pf4j/JarPluginManager.java create mode 100644 pf4j/src/main/java/org/pf4j/ZipPluginManager.java diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java index 7e90388..956afeb 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java @@ -25,6 +25,8 @@ import java.nio.file.Paths; /** * Default implementation of the {@link PluginManager} interface. + * In essence it is a {@link ZipPluginManager} plus a {@link JarPluginManager}. + * So, it can load plugins from jar and zip, simultaneous. * *

This class is not thread-safe. * diff --git a/pf4j/src/main/java/org/pf4j/JarPluginManager.java b/pf4j/src/main/java/org/pf4j/JarPluginManager.java new file mode 100644 index 0000000..68c50db --- /dev/null +++ b/pf4j/src/main/java/org/pf4j/JarPluginManager.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +/** + * It's a {@link PluginManager} that loads each plugin from a {@code jar} file. + * Actually, a plugin is a fat jar, a jar which contains classes from all the libraries, + * on which your project depends and, of course, the classes of current project. + * + * @author Decebal Suiu + */ +public class JarPluginManager extends DefaultPluginManager { + + @Override + protected PluginDescriptorFinder createPluginDescriptorFinder() { + return new ManifestPluginDescriptorFinder(); + } + + @Override + protected PluginLoader createPluginLoader() { + return new JarPluginLoader(this); + } + + @Override + protected PluginRepository createPluginRepository() { + return new JarPluginRepository(getPluginsRoot()); + } + +} diff --git a/pf4j/src/main/java/org/pf4j/ZipPluginManager.java b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java new file mode 100644 index 0000000..ed2ea7e --- /dev/null +++ b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +/** + * It's a {@link PluginManager} that loads each plugin from a {@code zip} file. + * The structure of the zip file is: + * - {@code lib} directory that contains all dependencies (as jar files); it's optional (no dependencies) + * - {@code classes} directory that contains all plugin's classes + * + * @author Decebal Suiu + */ +public class ZipPluginManager extends DefaultPluginManager { + + @Override + protected PluginDescriptorFinder createPluginDescriptorFinder() { + return new PropertiesPluginDescriptorFinder(); + } + + @Override + protected PluginLoader createPluginLoader() { + return new DefaultPluginLoader(this, pluginClasspath); + } + + @Override + protected PluginRepository createPluginRepository() { + return new DefaultPluginRepository(getPluginsRoot(), isDevelopment()); + } + +} From 9ae845b56d686ea4d4d6db4faa9d0231bfd318a6 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 1 Apr 2019 23:10:29 +0300 Subject: [PATCH 14/54] Remove deprecated constructor --- pf4j/src/main/java/org/pf4j/DefaultPluginManager.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java index 7e90388..bed6c25 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java @@ -19,7 +19,6 @@ import org.pf4j.util.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; @@ -40,16 +39,6 @@ public class DefaultPluginManager extends AbstractPluginManager { super(); } - /** - * Use {@link DefaultPluginManager#DefaultPluginManager(Path)}. - * - * @param pluginsDir - */ - @Deprecated - public DefaultPluginManager(File pluginsDir) { - this(pluginsDir.toPath()); - } - public DefaultPluginManager(Path pluginsRoot) { super(pluginsRoot); } From 08dc162b426865e0555c34b59e54f8d6c28a61bc Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 1 Apr 2019 23:15:47 +0300 Subject: [PATCH 15/54] Resolve TODO (add isDevelopment method as default method in PluginManager) --- pf4j/src/main/java/org/pf4j/AbstractPluginManager.java | 5 ----- pf4j/src/main/java/org/pf4j/PluginManager.java | 7 +++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index ba12eef..5803a62 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -913,11 +913,6 @@ public abstract class AbstractPluginManager implements PluginManager { } } - // TODO add this method in PluginManager as default method for Java 8. - protected boolean isDevelopment() { - return RuntimeMode.DEVELOPMENT.equals(getRuntimeMode()); - } - /** * @return true if exact versions in requires is allowed */ diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java index c2cbacc..11d3eac 100644 --- a/pf4j/src/main/java/org/pf4j/PluginManager.java +++ b/pf4j/src/main/java/org/pf4j/PluginManager.java @@ -154,6 +154,13 @@ public interface PluginManager { */ RuntimeMode getRuntimeMode(); + /** + * Returns {@code true} id the runtime mode is {@code RuntimeMode.DEVELOPMENT}. + */ + default boolean isDevelopment() { + return RuntimeMode.DEVELOPMENT.equals(getRuntimeMode()); + } + /** * Retrieves the {@link PluginWrapper} that loaded the given class 'clazz'. */ From 298465d436c34ad181ae00125f44cdbf7ededdc6 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 1 Apr 2019 23:16:05 +0300 Subject: [PATCH 16/54] Fix warning --- pf4j/src/main/java/org/pf4j/RuntimeMode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pf4j/src/main/java/org/pf4j/RuntimeMode.java b/pf4j/src/main/java/org/pf4j/RuntimeMode.java index 1fa9cbd..909cc38 100644 --- a/pf4j/src/main/java/org/pf4j/RuntimeMode.java +++ b/pf4j/src/main/java/org/pf4j/RuntimeMode.java @@ -41,7 +41,7 @@ public enum RuntimeMode { } } - private RuntimeMode(final String name, final String... aliases) { + RuntimeMode(final String name, final String... aliases) { this.name = name; this.aliases = aliases; } From 293b020dee0f63f1f7c23f1db4e34b6415f1e32f Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 12 Apr 2019 21:26:07 +0300 Subject: [PATCH 17/54] Fix javadoc formatting --- pf4j/src/main/java/module-info.java.new | 47 +++++++++++++++++++ .../main/java/org/pf4j/ZipPluginManager.java | 6 ++- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 pf4j/src/main/java/module-info.java.new diff --git a/pf4j/src/main/java/module-info.java.new b/pf4j/src/main/java/module-info.java.new new file mode 100644 index 0000000..754b9b8 --- /dev/null +++ b/pf4j/src/main/java/module-info.java.new @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Module descriptor for PF4J. + * + * @author Decebal Suiu + * @author Andreas Rudolph + */ +module org.pf4j { + requires java.base; + + // provides javax.annotation + requires java.compiler; + + // provided by the ASM library + requires org.objectweb.asm; + + // The SLF4J library currently does not provide a module. + // Version 1.8 provides a module called "org.slf4j". But this version is + // currently in beta stage. Therefore I'm not sure, if we already like to + // use it. + requires slf4j.api; + + // The java-semver library currently does not provide a module. + // Maybe we should send them a pull request, that at least they provide an + // automatic module name in their MANIFEST file. + requires java.semver; + + // Maybe we should reconsider the package hierarchy, that only classes are + // exported, which are required by 3rd party developers. + exports org.pf4j; + exports org.pf4j.processor; +} diff --git a/pf4j/src/main/java/org/pf4j/ZipPluginManager.java b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java index ed2ea7e..ab17fc9 100644 --- a/pf4j/src/main/java/org/pf4j/ZipPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java @@ -18,8 +18,10 @@ package org.pf4j; /** * It's a {@link PluginManager} that loads each plugin from a {@code zip} file. * The structure of the zip file is: - * - {@code lib} directory that contains all dependencies (as jar files); it's optional (no dependencies) - * - {@code classes} directory that contains all plugin's classes + *

    + *
  • {@code lib} directory that contains all dependencies (as jar files); it's optional (no dependencies) + *
  • {@code classes} directory that contains all plugin's classes + *
* * @author Decebal Suiu */ From 363fdc85afe47b3d878511c33f693681769e8d35 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 12 Apr 2019 21:28:08 +0300 Subject: [PATCH 18/54] Add constants for manifest's attributes names --- .../pf4j/ManifestPluginDescriptorFinder.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java index 6401f21..20810ba 100644 --- a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java @@ -37,6 +37,15 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { private static final Logger log = LoggerFactory.getLogger(ManifestPluginDescriptorFinder.class); + public static final String PLUGIN_ID = "Plugin-Id"; + public static final String PLUGIN_DESCRIPTION = "Plugin-Description"; + public static final String PLUGIN_CLASS = "Plugin-Class"; + public static final String PLUGIN_VERSION = "Plugin-Version"; + public static final String PLUGIN_PROVIDER = "Plugin-Provider"; + public static final String PLUGIN_DEPENDENCIES = "Plugin-Dependencies"; + public static final String PLUGIN_REQUIRES = "Plugin-Requires"; + public static final String PLUGIN_LICENSE = "Plugin-License"; + @Override public boolean isApplicable(Path pluginPath) { return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isJarFile(pluginPath)); @@ -92,37 +101,37 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { // TODO validate !!! Attributes attributes = manifest.getMainAttributes(); - String id = attributes.getValue("Plugin-Id"); + String id = attributes.getValue(PLUGIN_ID); pluginDescriptor.setPluginId(id); - String description = attributes.getValue("Plugin-Description"); + String description = attributes.getValue(PLUGIN_DESCRIPTION); if (StringUtils.isNullOrEmpty(description)) { pluginDescriptor.setPluginDescription(""); } else { pluginDescriptor.setPluginDescription(description); } - String clazz = attributes.getValue("Plugin-Class"); + String clazz = attributes.getValue(PLUGIN_CLASS); if (StringUtils.isNotNullOrEmpty(clazz)) { pluginDescriptor.setPluginClass(clazz); } - String version = attributes.getValue("Plugin-Version"); + String version = attributes.getValue(PLUGIN_VERSION); if (StringUtils.isNotNullOrEmpty(version)) { pluginDescriptor.setPluginVersion(version); } - String provider = attributes.getValue("Plugin-Provider"); + String provider = attributes.getValue(PLUGIN_PROVIDER); pluginDescriptor.setProvider(provider); - String dependencies = attributes.getValue("Plugin-Dependencies"); + String dependencies = attributes.getValue(PLUGIN_DEPENDENCIES); pluginDescriptor.setDependencies(dependencies); - String requires = attributes.getValue("Plugin-Requires"); + String requires = attributes.getValue(PLUGIN_REQUIRES); if (StringUtils.isNotNullOrEmpty(requires)) { pluginDescriptor.setRequires(requires); } - pluginDescriptor.setLicense(attributes.getValue("Plugin-License")); + pluginDescriptor.setLicense(attributes.getValue(PLUGIN_LICENSE)); return pluginDescriptor; } From 78a7802793806c84546a1f3b874e70b91b025829 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 12 Apr 2019 21:29:50 +0300 Subject: [PATCH 19/54] Add possibility to add extra properties --- .../test/java/org/pf4j/plugin/PluginZip.java | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java index 72e3241..ee665d7 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java @@ -18,13 +18,14 @@ package org.pf4j.plugin; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; +import java.util.Map; import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** - * Represents a plugin zip/jar file. - * The "plugin.properties" file is created on the fly from the information supplied in Builder. + * Represents a plugin {@code zip} file. + * The {@code plugin.properties} file is created on the fly from the information supplied in {@link Builder}. * * @author Decebal Suiu */ @@ -65,6 +66,7 @@ public class PluginZip { private final String pluginId; private String pluginVersion; + private Map properties; public Builder(Path path, String pluginId) { this.path = path; @@ -77,6 +79,15 @@ public class PluginZip { return this; } + /** + * Add extra properties to the {@code properties} file. + */ + public Builder properties(Map properties) { + this.properties = properties; + + return this; + } + public PluginZip build() throws IOException { createPropertiesFile(); @@ -84,15 +95,18 @@ public class PluginZip { } protected void createPropertiesFile() throws IOException { - Properties properties = new Properties(); - properties.setProperty("plugin.id", pluginId); - properties.setProperty("plugin.version", pluginVersion); - properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); + Properties props = new Properties(); + props.setProperty("plugin.id", pluginId); + props.setProperty("plugin.version", pluginVersion); + props.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); + if (properties != null) { + props.putAll(properties); + } ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(path.toFile())); ZipEntry propertiesFile = new ZipEntry("plugin.properties"); outputStream.putNextEntry(propertiesFile); - properties.store(outputStream, ""); + props.store(outputStream, ""); outputStream.closeEntry(); outputStream.close(); } From fabecb360f8f4f34d1cb263720afd995a6063d20 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 12 Apr 2019 21:41:56 +0300 Subject: [PATCH 20/54] Fix mistake add file --- pf4j/src/main/java/module-info.java.new | 47 ------------------------- 1 file changed, 47 deletions(-) delete mode 100644 pf4j/src/main/java/module-info.java.new diff --git a/pf4j/src/main/java/module-info.java.new b/pf4j/src/main/java/module-info.java.new deleted file mode 100644 index 754b9b8..0000000 --- a/pf4j/src/main/java/module-info.java.new +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2012-present the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Module descriptor for PF4J. - * - * @author Decebal Suiu - * @author Andreas Rudolph - */ -module org.pf4j { - requires java.base; - - // provides javax.annotation - requires java.compiler; - - // provided by the ASM library - requires org.objectweb.asm; - - // The SLF4J library currently does not provide a module. - // Version 1.8 provides a module called "org.slf4j". But this version is - // currently in beta stage. Therefore I'm not sure, if we already like to - // use it. - requires slf4j.api; - - // The java-semver library currently does not provide a module. - // Maybe we should send them a pull request, that at least they provide an - // automatic module name in their MANIFEST file. - requires java.semver; - - // Maybe we should reconsider the package hierarchy, that only classes are - // exported, which are required by 3rd party developers. - exports org.pf4j; - exports org.pf4j.processor; -} From 76e8acce91fa11a3492191168be746d75022be10 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 12 Apr 2019 21:44:44 +0300 Subject: [PATCH 21/54] Add PluginJar --- .../test/java/org/pf4j/plugin/PluginJar.java | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 pf4j/src/test/java/org/pf4j/plugin/PluginJar.java diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java new file mode 100644 index 0000000..30b3c26 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j.plugin; + +import org.pf4j.ManifestPluginDescriptorFinder; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +/** + /** + * Represents a plugin {@code jar} file. + * The {@code MANIFEST.MF} file is created on the fly from the information supplied in {@link Builder}. + * + * @author Decebal Suiu + */ +public class PluginJar { + + private final Path path; + private final String pluginId; + private final String pluginVersion; + + protected PluginJar(Builder builder) { + this.path = builder.path; + this.pluginId = builder.pluginId; + this.pluginVersion = builder.pluginVersion; + } + + public Path path() { + return path; + } + + public String pluginId() { + return pluginId; + } + + public String pluginVersion() { + return pluginVersion; + } + + public static class Builder { + + private final Path path; + private final String pluginId; + + private String pluginVersion; + private Map attributes; + + public Builder(Path path, String pluginId) { + this.path = path; + this.pluginId = pluginId; + } + + public Builder pluginVersion(String pluginVersion) { + this.pluginVersion = pluginVersion; + + return this; + } + + /** + * Add extra attributes to the {@code manifest} file. + */ + public Builder attributes(Map attributes) { + this.attributes = attributes; + + return this; + } + + public PluginJar build() throws IOException { + createManifestFile(); + + return new PluginJar(this); + } + + protected void createManifestFile() throws IOException { + Manifest manifest = new Manifest(); + Attributes attrs = manifest.getMainAttributes(); + attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0"); + attrs.put(new Attributes.Name(ManifestPluginDescriptorFinder.PLUGIN_ID), pluginId); + attrs.put(new Attributes.Name(ManifestPluginDescriptorFinder.PLUGIN_VERSION), pluginVersion); + attrs.put(new Attributes.Name(ManifestPluginDescriptorFinder.PLUGIN_CLASS), "org.pf4j.plugin.TestPlugin"); + if (attributes != null) { + Set names = attributes.keySet(); + for (String name : names) { + attrs.put(new Attributes.Name(name), attributes.get(name)); + } + } + + JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(path.toFile()), manifest); + outputStream.close(); + } + + } + +} From 4907d01093b447044d24b158daaaded0f4757948 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 12 Apr 2019 21:52:52 +0300 Subject: [PATCH 22/54] Clean tests --- .../CompoundPluginDescriptorFinderTest.java | 9 +++++---- .../PropertiesPluginDescriptorFinderTest.java | 17 ----------------- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java index 518ba1e..a24ff44 100644 --- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java @@ -17,6 +17,7 @@ package org.pf4j; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.pf4j.plugin.PluginJar; import org.pf4j.plugin.PluginZip; import java.nio.charset.StandardCharsets; @@ -64,9 +65,9 @@ public class CompoundPluginDescriptorFinderTest { @Test public void findInJar() throws Exception { PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder() - .add(new PropertiesPluginDescriptorFinder()); + .add(new ManifestPluginDescriptorFinder()); - PluginZip pluginJar = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin") + PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin") .pluginVersion("1.2.3") .build(); @@ -86,11 +87,11 @@ public class CompoundPluginDescriptorFinderTest { public void testSpaceCharacterInFileName() throws Exception { PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder(); - PluginZip pluginJar = new PluginZip.Builder(pluginsPath.resolve("my plugin-1.2.3.jar"), "myPlugin") + PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my plugin-1.2.3.jar"), "myPlugin") .pluginVersion("1.2.3") .build(); - PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginJar.path()); + PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginZip.path()); assertNotNull(pluginDescriptor); } diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index 7845952..8b484b4 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -18,7 +18,6 @@ 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.plugin.PluginZip; import java.io.IOException; import java.nio.charset.Charset; @@ -29,7 +28,6 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -105,21 +103,6 @@ public class PropertiesPluginDescriptorFinderTest { assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } - @Test - public void findInJar() throws Exception { - PluginZip pluginJar = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin") - .pluginVersion("1.2.3") - .build(); - - assertTrue(Files.exists(pluginJar.path())); - - PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder(); - PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginJar.path()); - assertNotNull(pluginDescriptor); - assertEquals("myPlugin", pluginJar.pluginId()); - assertEquals("1.2.3", pluginJar.pluginVersion()); - } - private List getPlugin1Properties() { String[] lines = new String[] { "plugin.id=test-plugin-1\n" From f149b2e8ae37e7d3f41187221011f2419fd3c2b6 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 12 Apr 2019 22:26:55 +0300 Subject: [PATCH 23/54] Improve readability of PropertiesPluginDescriptorFinderTest --- .../PropertiesPluginDescriptorFinderTest.java | 137 ++++++++---------- 1 file changed, 64 insertions(+), 73 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index 8b484b4..a65c84e 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -19,12 +19,14 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import java.io.FileOutputStream; import java.io.IOException; -import java.nio.charset.Charset; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; +import java.util.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -40,28 +42,26 @@ public class PropertiesPluginDescriptorFinderTest { @BeforeEach public void setUp() throws IOException { - Charset charset = Charset.forName("UTF-8"); - Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1")); - Files.write(pluginPath.resolve("plugin.properties"), getPlugin1Properties(), charset); + storePropertiesToPath(getPlugin1Properties(), pluginPath.resolve("plugin.properties")); pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-2")); - Files.write(pluginPath.resolve("plugin.properties"), getPlugin2Properties(), charset); + storePropertiesToPath(getPlugin2Properties(), pluginPath.resolve("plugin.properties")); // empty plugin Files.createDirectories(pluginsPath.resolve("test-plugin-3")); // no plugin class pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-4")); - Files.write(pluginPath.resolve("plugin.properties"), getPlugin4Properties(), charset); + storePropertiesToPath(getPlugin4Properties(), pluginPath.resolve("plugin.properties")); // no plugin version pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-5")); - Files.write(pluginPath.resolve("plugin.properties"), getPlugin5Properties(), charset); + storePropertiesToPath(getPlugin5Properties(), pluginPath.resolve("plugin.properties")); // no plugin id pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-6")); - Files.write(pluginPath.resolve("plugin.properties"), getPlugin6Properties(), charset); + storePropertiesToPath(getPlugin6Properties(), pluginPath.resolve("plugin.properties")); versionManager = new DefaultVersionManager(); } @@ -103,77 +103,68 @@ public class PropertiesPluginDescriptorFinderTest { assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } - private List getPlugin1Properties() { - String[] lines = new String[] { - "plugin.id=test-plugin-1\n" - + "plugin.version=0.0.1\n" - + "plugin.description=Test Plugin 1\n" - + "plugin.provider=Decebal Suiu\n" - + "plugin.class=org.pf4j.plugin.TestPlugin\n" - + "plugin.dependencies=test-plugin-2,test-plugin-3@~1.0\n" - + "plugin.requires=>=1\n" - + "plugin.license=Apache-2.0\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + private Properties getPlugin1Properties() { + Properties properties = new Properties(); + properties.setProperty("plugin.id", "test-plugin-1"); + properties.setProperty("plugin.version", "0.0.1"); + properties.setProperty("plugin.description", "Test Plugin 1"); + properties.setProperty("plugin.provider", "Decebal Suiu"); + properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); + properties.setProperty("plugin.dependencies", "test-plugin-2,test-plugin-3@~1.0"); + properties.setProperty("plugin.requires", ">=1"); + properties.setProperty("plugin.license", "Apache-2.0"); + + return properties; } - private List getPlugin2Properties() { - String[] lines = new String[] { - "plugin.id=test-plugin-2\n" - + "plugin.version=0.0.1\n" - + "plugin.provider=Decebal Suiu\n" - + "plugin.class=org.pf4j.plugin.TestPlugin\n" - + "plugin.dependencies=\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + private Properties getPlugin2Properties() { + Properties properties = new Properties(); + properties.setProperty("plugin.id", "test-plugin-2"); + properties.setProperty("plugin.version", "0.0.1"); + properties.setProperty("plugin.provider", "Decebal Suiu"); + properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); + properties.setProperty("plugin.dependencies", ""); + + return properties; } - private List getPlugin4Properties() { - String[] lines = new String[] { - "plugin.id=test-plugin-2\n" - + "plugin.version=0.0.1\n" - + "plugin.provider=Decebal Suiu\n" - + "plugin.dependencies=\n" - + "plugin.requires=*\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + private Properties getPlugin4Properties() { + Properties properties = new Properties(); + properties.setProperty("plugin.id", "test-plugin-2"); + properties.setProperty("plugin.version", "0.0.1"); + properties.setProperty("plugin.provider", "Decebal Suiu"); + properties.setProperty("plugin.dependencies", ""); + properties.setProperty("plugin.requires", "*"); + + return properties; } - private List getPlugin5Properties() { - String[] lines = new String[] { - "plugin.id=test-plugin-2\n" - + "plugin.provider=Decebal Suiu\n" - + "plugin.class=org.pf4j.plugin.TestPlugin\n" - + "plugin.dependencies=\n" - + "plugin.requires=*\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + private Properties getPlugin5Properties() { + Properties properties = new Properties(); + properties.setProperty("plugin.id", "test-plugin-2"); + properties.setProperty("plugin.provider", "Decebal Suiu"); + properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); + properties.setProperty("plugin.dependencies", ""); + properties.setProperty("plugin.requires", "*"); + + return properties; + } + + private Properties getPlugin6Properties() { + Properties properties = new Properties(); + properties.setProperty("plugin.version", "0.0.1"); + properties.setProperty("plugin.provider", "Decebal Suiu"); + properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); + properties.setProperty("plugin.dependencies", ""); + properties.setProperty("plugin.requires", "*"); + + return properties; } - private List getPlugin6Properties() { - String[] lines = new String[] { - "plugin.version=0.0.1\n" - + "plugin.provider=Decebal Suiu\n" - + "plugin.class=org.pf4j.plugin.TestPlugin\n" - + "plugin.dependencies=\n" - + "plugin.requires=*\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + private void storePropertiesToPath(Properties properties, Path path) throws IOException { + try (Writer writer = new OutputStreamWriter(new FileOutputStream(path.toFile()), StandardCharsets.UTF_8)) { + properties.store(writer, ""); + } } } From 44ed78f1c2a69ea9db37bc1170fb6e83722e87b6 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 12 Apr 2019 22:43:39 +0300 Subject: [PATCH 24/54] Add constants for properties names --- .../PropertiesPluginDescriptorFinder.java | 27 +++++--- .../PropertiesPluginDescriptorFinderTest.java | 69 ++++++++++--------- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java index 3e9e1c1..31afee9 100644 --- a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java @@ -36,7 +36,16 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder private static final Logger log = LoggerFactory.getLogger(PropertiesPluginDescriptorFinder.class); - private static final String DEFAULT_PROPERTIES_FILE_NAME = "plugin.properties"; + public static final String DEFAULT_PROPERTIES_FILE_NAME = "plugin.properties"; + + public static final String PLUGIN_ID = "plugin.id"; + public static final String PLUGIN_DESCRIPTION = "plugin.description"; + public static final String PLUGIN_CLASS = "plugin.class"; + public static final String PLUGIN_VERSION = "plugin.version"; + public static final String PLUGIN_PROVIDER = "plugin.provider"; + public static final String PLUGIN_DEPENDENCIES = "plugin.dependencies"; + public static final String PLUGIN_REQUIRES = "plugin.requires"; + public static final String PLUGIN_LICENSE = "plugin.license"; protected String propertiesFileName; @@ -98,38 +107,38 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder DefaultPluginDescriptor pluginDescriptor = createPluginDescriptorInstance(); // TODO validate !!! - String id = properties.getProperty("plugin.id"); + String id = properties.getProperty(PLUGIN_ID); pluginDescriptor.setPluginId(id); - String description = properties.getProperty("plugin.description"); + String description = properties.getProperty(PLUGIN_DESCRIPTION); if (StringUtils.isNullOrEmpty(description)) { pluginDescriptor.setPluginDescription(""); } else { pluginDescriptor.setPluginDescription(description); } - String clazz = properties.getProperty("plugin.class"); + String clazz = properties.getProperty(PLUGIN_CLASS); if (StringUtils.isNotNullOrEmpty(clazz)) { pluginDescriptor.setPluginClass(clazz); } - String version = properties.getProperty("plugin.version"); + String version = properties.getProperty(PLUGIN_VERSION); if (StringUtils.isNotNullOrEmpty(version)) { pluginDescriptor.setPluginVersion(version); } - String provider = properties.getProperty("plugin.provider"); + String provider = properties.getProperty(PLUGIN_PROVIDER); pluginDescriptor.setProvider(provider); - String dependencies = properties.getProperty("plugin.dependencies"); + String dependencies = properties.getProperty(PLUGIN_DEPENDENCIES); pluginDescriptor.setDependencies(dependencies); - String requires = properties.getProperty("plugin.requires"); + String requires = properties.getProperty(PLUGIN_REQUIRES); if (StringUtils.isNotNullOrEmpty(requires)) { pluginDescriptor.setRequires(requires); } - pluginDescriptor.setLicense(properties.getProperty("plugin.license")); + pluginDescriptor.setLicense(properties.getProperty(PLUGIN_LICENSE)); return pluginDescriptor; } diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index a65c84e..2be2eb8 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -43,25 +43,25 @@ public class PropertiesPluginDescriptorFinderTest { @BeforeEach public void setUp() throws IOException { Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1")); - storePropertiesToPath(getPlugin1Properties(), pluginPath.resolve("plugin.properties")); + storePropertiesToPath(getPlugin1Properties(), pluginPath); pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-2")); - storePropertiesToPath(getPlugin2Properties(), pluginPath.resolve("plugin.properties")); + storePropertiesToPath(getPlugin2Properties(), pluginPath); // empty plugin Files.createDirectories(pluginsPath.resolve("test-plugin-3")); // no plugin class pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-4")); - storePropertiesToPath(getPlugin4Properties(), pluginPath.resolve("plugin.properties")); + storePropertiesToPath(getPlugin4Properties(), pluginPath); // no plugin version pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-5")); - storePropertiesToPath(getPlugin5Properties(), pluginPath.resolve("plugin.properties")); + storePropertiesToPath(getPlugin5Properties(), pluginPath); // no plugin id pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-6")); - storePropertiesToPath(getPlugin6Properties(), pluginPath.resolve("plugin.properties")); + storePropertiesToPath(getPlugin6Properties(), pluginPath); versionManager = new DefaultVersionManager(); } @@ -105,63 +105,64 @@ public class PropertiesPluginDescriptorFinderTest { private Properties getPlugin1Properties() { Properties properties = new Properties(); - properties.setProperty("plugin.id", "test-plugin-1"); - properties.setProperty("plugin.version", "0.0.1"); - properties.setProperty("plugin.description", "Test Plugin 1"); - properties.setProperty("plugin.provider", "Decebal Suiu"); - properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); - properties.setProperty("plugin.dependencies", "test-plugin-2,test-plugin-3@~1.0"); - properties.setProperty("plugin.requires", ">=1"); - properties.setProperty("plugin.license", "Apache-2.0"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DESCRIPTION, "Test Plugin 1"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "test-plugin-2,test-plugin-3@~1.0"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, ">=1"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_LICENSE, "Apache-2.0"); return properties; } private Properties getPlugin2Properties() { Properties properties = new Properties(); - properties.setProperty("plugin.id", "test-plugin-2"); - properties.setProperty("plugin.version", "0.0.1"); - properties.setProperty("plugin.provider", "Decebal Suiu"); - properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); - properties.setProperty("plugin.dependencies", ""); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); return properties; } private Properties getPlugin4Properties() { Properties properties = new Properties(); - properties.setProperty("plugin.id", "test-plugin-2"); - properties.setProperty("plugin.version", "0.0.1"); - properties.setProperty("plugin.provider", "Decebal Suiu"); - properties.setProperty("plugin.dependencies", ""); - properties.setProperty("plugin.requires", "*"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); return properties; } private Properties getPlugin5Properties() { Properties properties = new Properties(); - properties.setProperty("plugin.id", "test-plugin-2"); - properties.setProperty("plugin.provider", "Decebal Suiu"); - properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); - properties.setProperty("plugin.dependencies", ""); - properties.setProperty("plugin.requires", "*"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); return properties; } private Properties getPlugin6Properties() { Properties properties = new Properties(); - properties.setProperty("plugin.version", "0.0.1"); - properties.setProperty("plugin.provider", "Decebal Suiu"); - properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); - properties.setProperty("plugin.dependencies", ""); - properties.setProperty("plugin.requires", "*"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); + properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); return properties; } - private void storePropertiesToPath(Properties properties, Path path) throws IOException { + private void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException { + Path path = pluginPath.resolve(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); try (Writer writer = new OutputStreamWriter(new FileOutputStream(path.toFile()), StandardCharsets.UTF_8)) { properties.store(writer, ""); } From 6b92361aad38d2628111eada57c56f4af625b374 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 13 Apr 2019 23:23:19 +0300 Subject: [PATCH 25/54] Add javadoc --- pf4j/src/main/java/org/pf4j/util/Unzip.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pf4j/src/main/java/org/pf4j/util/Unzip.java b/pf4j/src/main/java/org/pf4j/util/Unzip.java index 7762e47..afde37a 100644 --- a/pf4j/src/main/java/org/pf4j/util/Unzip.java +++ b/pf4j/src/main/java/org/pf4j/util/Unzip.java @@ -63,10 +63,14 @@ public class Unzip { this.destination = destination; } + /** + * Extract the content of zip file ({@code source}) to destination directory. + * If destination directory already exists it will be deleted before. + */ public void extract() throws IOException { log.debug("Extract content of '{}' to '{}'", source, destination); - // delete destination file if exists + // delete destination directory if exists if (destination.exists() && destination.isDirectory()) { FileUtils.delete(destination.toPath()); } From dd45a1e6dcfdcc39b3fe182417d48a2e801f7d28 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 13 Apr 2019 23:25:04 +0300 Subject: [PATCH 26/54] Fix issue (the plugin directory will be deleted anyway in unzip extract method) --- pf4j/src/main/java/org/pf4j/util/FileUtils.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/util/FileUtils.java b/pf4j/src/main/java/org/pf4j/util/FileUtils.java index 7bd7abe..0cb8784 100644 --- a/pf4j/src/main/java/org/pf4j/util/FileUtils.java +++ b/pf4j/src/main/java/org/pf4j/util/FileUtils.java @@ -176,14 +176,6 @@ public class FileUtils { Path pluginDirectory = filePath.resolveSibling(directoryName); if (!Files.exists(pluginDirectory) || pluginZipDate.compareTo(Files.getLastModifiedTime(pluginDirectory)) > 0) { - // do not overwrite an old version, remove it - if (Files.exists(pluginDirectory)) { - FileUtils.delete(pluginDirectory); - } - - // create root for plugin - Files.createDirectories(pluginDirectory); - // expand '.zip' file Unzip unzip = new Unzip(); unzip.setSource(filePath.toFile()); From c1062e7cc77a87068ce63e0443524da98bc0ae64 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 13 Apr 2019 23:26:28 +0300 Subject: [PATCH 27/54] Improve readability --- .../org/pf4j/DefaultPluginRepositoryTest.java | 10 +- .../ManifestPluginDescriptorFinderTest.java | 191 ++++++------------ .../PropertiesPluginDescriptorFinderTest.java | 99 ++++----- .../test/java/org/pf4j/plugin/PluginJar.java | 30 +-- .../test/java/org/pf4j/plugin/PluginZip.java | 24 ++- 5 files changed, 155 insertions(+), 199 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java index 91a35f5..4f13bac 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -39,16 +39,16 @@ public class DefaultPluginRepositoryTest { @BeforeEach public void setUp() throws IOException { - Path plugin1Path = Files.createDirectories(pluginsPath.resolve("plugin-1")); + Path plugin1Path = Files.createDirectory(pluginsPath.resolve("plugin-1")); // 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 Files.createFile(pluginsPath.resolve("plugin-1.zip")); - Files.createDirectories(pluginsPath.resolve("plugin-2")); - Files.createDirectories(pluginsPath.resolve("plugin-3")); + Files.createDirectory(pluginsPath.resolve("plugin-2")); + Files.createDirectory(pluginsPath.resolve("plugin-3")); // standard maven/gradle bin folder - these should be skipped in development mode because the cause errors - Files.createDirectories(pluginsPath.resolve("target")); - Files.createDirectories(pluginsPath.resolve("build")); + Files.createDirectory(pluginsPath.resolve("target")); + Files.createDirectory(pluginsPath.resolve("build")); } /** diff --git a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java index 1d83c9f..2ffe01b 100644 --- a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java @@ -18,14 +18,16 @@ 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.plugin.PluginJar; +import java.io.FileOutputStream; import java.io.IOException; -import java.nio.charset.Charset; +import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.List; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.jar.Manifest; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -44,33 +46,26 @@ public class ManifestPluginDescriptorFinderTest { @BeforeEach public void setUp() throws IOException { - Charset charset = Charset.forName("UTF-8"); + Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1")); + storeManifestToPath(getPlugin1Manifest(), pluginPath); - Path pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-1", "classes", "META-INF"))); - Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); - Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin1Manifest(), charset); - - pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-2", "classes", "META-INF"))); - Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); - Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin2Manifest(), charset); + pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-2")); + storeManifestToPath(getPlugin2Manifest(), pluginPath); // empty plugin Files.createDirectories(pluginsPath.resolve("test-plugin-3")); // no plugin class - pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-4", "classes", "META-INF"))); - Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); - Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin4Manifest(), charset); + pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-4")); + storeManifestToPath(getPlugin4Manifest(), pluginPath); // no plugin version - pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-5", "classes", "META-INF"))); - Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); - Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin5Manifest(), charset); + pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-5")); + storeManifestToPath(getPlugin5Manifest(), pluginPath); // no plugin id - pluginPath = Files.createDirectories(pluginsPath.resolve(Paths.get("test-plugin-6", "classes", "META-INF"))); - Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes()); - Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin6Manifest(), charset); + pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-6")); + storeManifestToPath(getPlugin6Manifest(), pluginPath); versionManager = new DefaultVersionManager(); } @@ -115,120 +110,62 @@ public class ManifestPluginDescriptorFinderTest { assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } - private List getPlugin1Manifest() { - String[] lines = new String[] { - "Manifest-Version: 1.0\n" - + "Implementation-Title: Test Plugin #1\n" - + "Implementation-Version: 0.10.0-SNAPSHOT\n" - + "Archiver-Version: Plexus Archiver\n" - + "Built-By: Mario Franco\n" - + "Specification-Title: Test Plugin #1\n" - + "Implementation-Vendor-Id: org.pf4j.demo\n" - + "Plugin-Version: 0.0.1\n" - + "Plugin-Id: test-plugin-1\n" - + "Plugin-Description: Test Plugin 1\n" - + "Plugin-Provider: Decebal Suiu\n" - + "Plugin-Class: org.pf4j.plugin.TestPlugin\n" - + "Plugin-Dependencies: test-plugin-2,test-plugin-3@~1.0\n" - + "Plugin-Requires: *\n" - + "Plugin-License: Apache-2.0\n" - + "Created-By: Apache Maven 3.0.5\n" - + "Build-Jdk: 1.8.0_45\n" - + "Specification-Version: 0.10.0-SNAPSHOT\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + 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 List getPlugin2Manifest() { - String[] lines = new String[] { - "Manifest-Version: 1.0\n" - + "Plugin-Dependencies: \n" - + "Implementation-Title: Test Plugin #2\n" - + "Implementation-Version: 0.10.0-SNAPSHOT\n" - + "Archiver-Version: Plexus Archiver\n" - + "Built-By: Mario Franco\n" - + "Specification-Title: Test Plugin #2\n" - + "Implementation-Vendor-Id: org.pf4j.demo\n" - + "Plugin-Version: 0.0.1\n" - + "Plugin-Id: test-plugin-2\n" - + "Plugin-Provider: Decebal Suiu\n" - + "Plugin-Class: org.pf4j.plugin.TestPlugin\n" - + "Created-By: Apache Maven 3.0.5\n" - + "Build-Jdk: 1.8.0_45\n" - + "Specification-Version: 0.10.0-SNAPSHOT\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + 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 List getPlugin4Manifest() { - String[] lines = new String[] { - "Manifest-Version: 1.0\n" - + "Implementation-Title: Test Plugin #4\n" - + "Implementation-Version: 0.10.0-SNAPSHOT\n" - + "Archiver-Version: Plexus Archiver\n" - + "Built-By: Mario Franco\n" - + "Specification-Title: Test Plugin #4\n" - + "Implementation-Vendor-Id: org.pf4j.demo\n" - + "Plugin-Version: 0.0.1\n" - + "Plugin-Id: test-plugin-2\n" - + "Plugin-Provider: Decebal Suiu\n" - + "Created-By: Apache Maven 3.0.5\n" - + "Build-Jdk: 1.8.0_45\n" - + "Specification-Version: 0.10.0-SNAPSHOT\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + 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 List getPlugin5Manifest() { - String[] lines = new String[] { - "Manifest-Version: 1.0\n" - + "Implementation-Title: Test Plugin #5\n" - + "Implementation-Version: 0.10.0-SNAPSHOT\n" - + "Archiver-Version: Plexus Archiver\n" - + "Built-By: Mario Franco\n" - + "Specification-Title: Test Plugin #5\n" - + "Implementation-Vendor-Id: org.pf4j.demo\n" - + "Plugin-Id: test-plugin-2\n" - + "Plugin-Provider: Decebal Suiu\n" - + "Plugin-Class: org.pf4j.plugin.TestPlugin\n" - + "Created-By: Apache Maven 3.0.5\n" - + "Build-Jdk: 1.8.0_45\n" - + "Specification-Version: 0.10.0-SNAPSHOT\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + 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 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 List getPlugin6Manifest() { - String[] lines = new String[] { - "Manifest-Version: 1.0\n" - + "Implementation-Title: Test Plugin #6\n" - + "Implementation-Version: 0.10.0-SNAPSHOT\n" - + "Archiver-Version: Plexus Archiver\n" - + "Built-By: Mario Franco\n" - + "Specification-Title: Test Plugin #6\n" - + "Implementation-Vendor-Id: org.pf4j.demo\n" - + "Plugin-Provider: Decebal Suiu\n" - + "Plugin-Class: org.pf4j.plugin.TestPlugin\n" - + "Created-By: Apache Maven 3.0.5\n" - + "Build-Jdk: 1.8.0_45\n" - + "Specification-Version: 0.10.0-SNAPSHOT\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + private void storeManifestToPath(Manifest manifest, Path pluginPath) throws IOException { + Path path = Files.createDirectory(pluginPath.resolve("META-INF")); + try (OutputStream output = new FileOutputStream(path.resolve("MANIFEST.MF").toFile())) { + manifest.write(output); + } } } diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index 2be2eb8..efb326e 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.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.plugin.PluginZip; import java.io.FileOutputStream; import java.io.IOException; @@ -26,6 +27,8 @@ 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.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -42,25 +45,25 @@ public class PropertiesPluginDescriptorFinderTest { @BeforeEach public void setUp() throws IOException { - Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1")); + Path pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-1")); storePropertiesToPath(getPlugin1Properties(), pluginPath); - pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-2")); + pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-2")); storePropertiesToPath(getPlugin2Properties(), pluginPath); // empty plugin Files.createDirectories(pluginsPath.resolve("test-plugin-3")); // no plugin class - pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-4")); + pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-4")); storePropertiesToPath(getPlugin4Properties(), pluginPath); // no plugin version - pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-5")); + pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-5")); storePropertiesToPath(getPlugin5Properties(), pluginPath); // no plugin id - pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-6")); + pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-6")); storePropertiesToPath(getPlugin6Properties(), pluginPath); versionManager = new DefaultVersionManager(); @@ -104,61 +107,61 @@ public class PropertiesPluginDescriptorFinderTest { } private Properties getPlugin1Properties() { - Properties properties = new Properties(); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DESCRIPTION, "Test Plugin 1"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "test-plugin-2,test-plugin-3@~1.0"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, ">=1"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_LICENSE, "Apache-2.0"); - - return properties; + Map map = new LinkedHashMap<>(8); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1"); + 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_CLASS, "org.pf4j.plugin.TestPlugin"); + 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 getPlugin2Properties() { - Properties properties = new Properties(); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - - return properties; + 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_CLASS, "org.pf4j.plugin.TestPlugin"); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); + + return PluginZip.createProperties(map); } private Properties getPlugin4Properties() { - Properties properties = new Properties(); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); - - return properties; + 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 getPlugin5Properties() { - Properties properties = new Properties(); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); - - return properties; + Map map = new LinkedHashMap<>(5); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2"); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); + + return PluginZip.createProperties(map); } private Properties getPlugin6Properties() { - Properties properties = new Properties(); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); - properties.setProperty(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); - - return properties; + Map map = new LinkedHashMap<>(5); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1"); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu"); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); + + return PluginZip.createProperties(map); } private void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException { diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java index 30b3c26..2301285 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java @@ -20,8 +20,8 @@ import org.pf4j.ManifestPluginDescriptorFinder; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; +import java.util.LinkedHashMap; import java.util.Map; -import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; @@ -57,6 +57,17 @@ public class PluginJar { 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; + } + public static class Builder { private final Path path; @@ -92,20 +103,15 @@ public class PluginJar { } protected void createManifestFile() throws IOException { - Manifest manifest = new Manifest(); - Attributes attrs = manifest.getMainAttributes(); - attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0"); - attrs.put(new Attributes.Name(ManifestPluginDescriptorFinder.PLUGIN_ID), pluginId); - attrs.put(new Attributes.Name(ManifestPluginDescriptorFinder.PLUGIN_VERSION), pluginVersion); - attrs.put(new Attributes.Name(ManifestPluginDescriptorFinder.PLUGIN_CLASS), "org.pf4j.plugin.TestPlugin"); + Map map = new LinkedHashMap<>(); + map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, pluginId); + map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); + map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); if (attributes != null) { - Set names = attributes.keySet(); - for (String name : names) { - attrs.put(new Attributes.Name(name), attributes.get(name)); - } + map.putAll(attributes); } - JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(path.toFile()), manifest); + JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(path.toFile()), createManifest(map)); outputStream.close(); } diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java index ee665d7..8e610c1 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java @@ -15,9 +15,12 @@ */ package org.pf4j.plugin; +import org.pf4j.PropertiesPluginDescriptorFinder; + import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; import java.util.zip.ZipEntry; @@ -60,6 +63,13 @@ 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; @@ -95,18 +105,18 @@ public class PluginZip { } protected void createPropertiesFile() throws IOException { - Properties props = new Properties(); - props.setProperty("plugin.id", pluginId); - props.setProperty("plugin.version", pluginVersion); - props.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin"); + Map map = new LinkedHashMap<>(); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, pluginId); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); if (properties != null) { - props.putAll(properties); + map.putAll(properties); } ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(path.toFile())); - ZipEntry propertiesFile = new ZipEntry("plugin.properties"); + ZipEntry propertiesFile = new ZipEntry(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); outputStream.putNextEntry(propertiesFile); - props.store(outputStream, ""); + createProperties(map).store(outputStream, ""); outputStream.closeEntry(); outputStream.close(); } From 40846fa1864da287690ef01402d5b5ccccbf351f Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sun, 14 Apr 2019 00:06:47 +0300 Subject: [PATCH 28/54] Rename PluginRepository.getPluginPaths to getPluginsPaths --- .../java/org/pf4j/AbstractPluginManager.java | 10 +++---- .../java/org/pf4j/BasePluginRepository.java | 4 +-- .../org/pf4j/CompoundPluginRepository.java | 4 +-- .../org/pf4j/DefaultPluginRepository.java | 4 +-- .../main/java/org/pf4j/PluginRepository.java | 8 ++--- .../org/pf4j/DefaultPluginRepositoryTest.java | 30 +++++++++---------- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 5803a62..33130a3 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -200,19 +200,19 @@ public abstract class AbstractPluginManager implements PluginManager { return; } - // get all plugin paths from repository - List pluginPaths = pluginRepository.getPluginPaths(); + // get all plugins paths from repository + List pluginsPaths = pluginRepository.getPluginsPaths(); // check for no plugins - if (pluginPaths.isEmpty()) { + if (pluginsPaths.isEmpty()) { log.info("No plugins"); return; } - log.debug("Found {} possible plugins: {}", pluginPaths.size(), pluginPaths); + log.debug("Found {} possible plugins: {}", pluginsPaths.size(), pluginsPaths); // load plugins from plugin paths - for (Path pluginPath : pluginPaths) { + for (Path pluginPath : pluginsPaths) { try { loadPluginFromPath(pluginPath); } catch (PluginException e) { diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java index 381059c..0bf6e6c 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java @@ -57,7 +57,7 @@ public class BasePluginRepository implements PluginRepository { /** * Set a {@link File} {@link Comparator} used to sort the listed files from {@code pluginsRoot}. - * This comparator is used in {@link #getPluginPaths()} method. + * This comparator is used in {@link #getPluginsPaths()} method. * By default is used a file comparator that returns the last modified files first. * If you don't want a file comparator, then call this method with {@code null}. */ @@ -66,7 +66,7 @@ public class BasePluginRepository implements PluginRepository { } @Override - public List getPluginPaths() { + public List getPluginsPaths() { File[] files = pluginsRoot.toFile().listFiles(filter); if ((files == null) || files.length == 0) { diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java index 09bc5ce..705b912 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java @@ -38,10 +38,10 @@ public class CompoundPluginRepository implements PluginRepository { } @Override - public List getPluginPaths() { + public List getPluginsPaths() { List paths = new ArrayList<>(); for (PluginRepository repository : repositories) { - paths.addAll(repository.getPluginPaths()); + paths.addAll(repository.getPluginsPaths()); } return paths; diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java index 78ea43c..6bc8d49 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java @@ -48,7 +48,7 @@ public class DefaultPluginRepository extends BasePluginRepository { } @Override - public List getPluginPaths() { + public List getPluginsPaths() { // expand plugins zip files File[] pluginZips = pluginsRoot.toFile().listFiles(new ZipFileFilter()); if ((pluginZips != null) && pluginZips.length > 0) { @@ -62,7 +62,7 @@ public class DefaultPluginRepository extends BasePluginRepository { } } - return super.getPluginPaths(); + return super.getPluginsPaths(); } @Override diff --git a/pf4j/src/main/java/org/pf4j/PluginRepository.java b/pf4j/src/main/java/org/pf4j/PluginRepository.java index f3617cd..d0b2125 100644 --- a/pf4j/src/main/java/org/pf4j/PluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/PluginRepository.java @@ -19,7 +19,7 @@ import java.nio.file.Path; import java.util.List; /** - * Directory that contains plugins. A plugin could be a zip file. + * Directory that contains plugins. A plugin could be a {@code directory}, @code zip} or {@code jar} file. * * @author Decebal Suiu * @author Mário Franco @@ -27,11 +27,11 @@ import java.util.List; public interface PluginRepository { /** - * List all plugin paths. + * List all plugins paths. * - * @return a list of files + * @return a list with paths */ - List getPluginPaths(); + List getPluginsPaths(); /** * Removes a plugin from the repository. diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java index 4f13bac..3aaba8f 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -52,33 +52,33 @@ public class DefaultPluginRepositoryTest { } /** - * Test of {@link DefaultPluginRepository#getPluginPaths()} method. + * Test of {@link DefaultPluginRepository#getPluginsPaths()} method. */ @Test public void testGetPluginArchives() { PluginRepository repository = new DefaultPluginRepository(pluginsPath, false); - List pluginPaths = repository.getPluginPaths(); + List pluginsPaths = repository.getPluginsPaths(); - assertEquals(5, pluginPaths.size()); - assertPathExists(pluginPaths, pluginsPath.resolve("plugin-1")); - assertPathExists(pluginPaths, pluginsPath.resolve("plugin-2")); - assertPathExists(pluginPaths, pluginsPath.resolve("plugin-3")); + assertEquals(5, pluginsPaths.size()); + assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-1")); + assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-2")); + assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-3")); // when not in development mode we will honor these folders - assertPathExists(pluginPaths, pluginsPath.resolve("target")); - assertPathExists(pluginPaths, pluginsPath.resolve("build")); + assertPathExists(pluginsPaths, pluginsPath.resolve("target")); + assertPathExists(pluginsPaths, pluginsPath.resolve("build")); } @Test public void testGetPluginArchivesInDevelopmentMode() { PluginRepository repository = new DefaultPluginRepository(pluginsPath, true); - List pluginPaths = repository.getPluginPaths(); + List pluginsPaths = repository.getPluginsPaths(); // target and build should be ignored - assertEquals(3, pluginPaths.size()); - assertPathDoesNotExists(pluginPaths, pluginsPath.resolve("target")); - assertPathDoesNotExists(pluginPaths, pluginsPath.resolve("build")); + assertEquals(3, pluginsPaths.size()); + assertPathDoesNotExists(pluginsPaths, pluginsPath.resolve("target")); + assertPathDoesNotExists(pluginsPaths, pluginsPath.resolve("build")); } /** @@ -96,10 +96,10 @@ public class DefaultPluginRepositoryTest { assertTrue(repository.deletePluginPath(pluginsPath.resolve("target"))); assertTrue(repository.deletePluginPath(pluginsPath.resolve("build"))); - List pluginPaths = repository.getPluginPaths(); + List pluginsPaths = repository.getPluginsPaths(); - assertEquals(1, pluginPaths.size()); - assertEquals(pluginsPath.relativize(pluginPaths.get(0)).toString(), "plugin-2"); + assertEquals(1, pluginsPaths.size()); + assertEquals(pluginsPath.relativize(pluginsPaths.get(0)).toString(), "plugin-2"); } private void assertPathExists(List paths, Path path) { From 3199b5f043ad533429b7834ce06e9d4129e6b596 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 15 Apr 2019 20:28:30 +0300 Subject: [PATCH 29/54] Resolve #309 --- pf4j/src/main/java/org/pf4j/AbstractPluginManager.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 33130a3..3833588 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -287,19 +287,25 @@ public abstract class AbstractPluginManager implements PluginManager { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); + // stop the plugin if it's started PluginState pluginState = stopPlugin(pluginId); if (PluginState.STARTED == pluginState) { log.error("Failed to stop plugin '{}' on delete", pluginId); return false; } + // get an instance of plugin before the plugin is unloaded + // for reason see https://github.com/pf4j/pf4j/issues/309 + Plugin plugin = pluginWrapper.getPlugin(); + if (!unloadPlugin(pluginId)) { log.error("Failed to unload plugin '{}' on delete", pluginId); return false; } + // notify the plugin as it's deleted try { - pluginWrapper.getPlugin().delete(); + plugin.delete(); } catch (PluginException e) { log.error(e.getMessage(), e); return false; From 70963ea174976051d586f0bb2829596de1c507b7 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 15 Apr 2019 20:51:02 +0300 Subject: [PATCH 30/54] Resolve #311 --- .../java/org/pf4j/BasePluginRepository.java | 8 ++- .../org/pf4j/JarPluginRepositoryTest.java | 59 +++++++++++++++++++ .../test/java/org/pf4j/LoadPluginsTest.java | 14 +---- 3 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java index 0bf6e6c..aa152be 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java @@ -87,11 +87,15 @@ public class BasePluginRepository implements PluginRepository { @Override public boolean deletePluginPath(Path pluginPath) { + if (!filter.accept(pluginPath.toFile())) { + return false; + } + try { FileUtils.delete(pluginPath); return true; - } catch (NoSuchFileException nsf) { - return false; // Return false on not found to be compatible with previous API + } catch (NoSuchFileException e) { + return false; // Return false on not found to be compatible with previous API (#135) } catch (IOException e) { throw new RuntimeException(e); } diff --git a/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java new file mode 100644 index 0000000..2260680 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Decebal Suiu + */ +public class JarPluginRepositoryTest { + + @TempDir + Path pluginsPath; + + /** + * Test of {@link JarPluginRepository#deletePluginPath(Path)} method. + */ + @Test + public void testDeletePluginPath() throws IOException { + PluginRepository repository = new JarPluginRepository(pluginsPath); + + Path plugin1Path = Files.createDirectory(pluginsPath.resolve("plugin-1")); + Path plugin1JarPath = Files.createFile(pluginsPath.resolve("plugin-1.jar")); + + assertFalse(repository.deletePluginPath(plugin1Path)); + + List pluginsPaths = repository.getPluginsPaths(); + assertEquals(1, pluginsPaths.size()); + + assertTrue(repository.deletePluginPath(plugin1JarPath)); + + pluginsPaths = repository.getPluginsPaths(); + assertEquals(0, pluginsPaths.size()); + } + +} diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java index f86cee4..d2a7e25 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java @@ -45,19 +45,7 @@ public class LoadPluginsTest { @BeforeEach public void setUp() { - pluginManager = new DefaultPluginManager(pluginsPath) { - - @Override - protected PluginRepository createPluginRepository() { - return new DefaultPluginRepository(getPluginsRoot(), isDevelopment()); - } - - @Override - protected PluginLoader createPluginLoader() { - return new DefaultPluginLoader(this, pluginClasspath); - } - - }; + pluginManager = new DefaultPluginManager(pluginsPath); } @Test From d10b0a944741c627db5064bdf181ba93d8324b6c Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 15 Apr 2019 20:51:20 +0300 Subject: [PATCH 31/54] Improve readability --- .../org/pf4j/DefaultPluginRepository.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java index 6bc8d49..da456eb 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java @@ -49,19 +49,7 @@ public class DefaultPluginRepository extends BasePluginRepository { @Override public List getPluginsPaths() { - // expand plugins zip files - File[] pluginZips = pluginsRoot.toFile().listFiles(new ZipFileFilter()); - if ((pluginZips != null) && pluginZips.length > 0) { - for (File pluginZip : pluginZips) { - try { - FileUtils.expandIfZip(pluginZip.toPath()); - } catch (IOException e) { - log.error("Cannot expand plugin zip '{}'", pluginZip); - log.error(e.getMessage(), e); - } - } - } - + extractZipFiles(); return super.getPluginsPaths(); } @@ -83,4 +71,20 @@ public class DefaultPluginRepository extends BasePluginRepository { return hiddenPluginFilter; } + + private void extractZipFiles() { + // expand plugins zip files + File[] zipFiles = pluginsRoot.toFile().listFiles(new ZipFileFilter()); + if ((zipFiles != null) && zipFiles.length > 0) { + for (File pluginZip : zipFiles) { + try { + FileUtils.expandIfZip(pluginZip.toPath()); + } catch (IOException e) { + log.error("Cannot expand plugin zip '{}'", pluginZip); + log.error(e.getMessage(), e); + } + } + } + } + } From 642f6343c95ec8481a919238c15d56944b86e1b8 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 15 Apr 2019 22:45:35 +0300 Subject: [PATCH 32/54] Add pluginClass getter in PluginZip and PluginJar --- .../CompoundPluginDescriptorFinderTest.java | 50 +++++++++++-------- .../PropertiesPluginDescriptorFinderTest.java | 13 ++--- .../test/java/org/pf4j/plugin/PluginJar.java | 17 ++++++- .../test/java/org/pf4j/plugin/PluginZip.java | 17 ++++++- 4 files changed, 69 insertions(+), 28 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java index a24ff44..7e6043b 100644 --- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java @@ -19,12 +19,18 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.plugin.PluginJar; import org.pf4j.plugin.PluginZip; +import org.pf4j.plugin.TestPlugin; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -49,9 +55,8 @@ public class CompoundPluginDescriptorFinderTest { @Test public void find() throws Exception { - Path pluginPath = pluginsPath.resolve("test-plugin-1"); - Files.createDirectories(pluginPath); - Files.write(pluginPath.resolve("plugin.properties"), getPlugin1Properties(), StandardCharsets.UTF_8); + Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1")); + storePropertiesToPath(getPlugin1Properties(), pluginPath); PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder() .add(new PropertiesPluginDescriptorFinder()); @@ -68,12 +73,14 @@ public class CompoundPluginDescriptorFinderTest { .add(new ManifestPluginDescriptorFinder()); PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin") + .pluginClass(TestPlugin.class.getName()) .pluginVersion("1.2.3") .build(); PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginJar.path()); assertNotNull(pluginDescriptor); assertEquals("myPlugin", pluginJar.pluginId()); + assertEquals(TestPlugin.class.getName(), pluginJar.pluginClass()); assertEquals("1.2.3", pluginJar.pluginVersion()); } @@ -95,21 +102,24 @@ public class CompoundPluginDescriptorFinderTest { assertNotNull(pluginDescriptor); } - private List getPlugin1Properties() { - String[] lines = new String[] { - "plugin.id=test-plugin-1\n" - + "plugin.version=0.0.1\n" - + "plugin.description=Test Plugin 1\n" - + "plugin.provider=Decebal Suiu\n" - + "plugin.class=org.pf4j.plugin.TestPlugin\n" - + "plugin.dependencies=test-plugin-2,test-plugin-3@~1.0\n" - + "plugin.requires=>=1\n" - + "plugin.license=Apache-2.0\n" - + "\n" - + "" - }; - - return Arrays.asList(lines); + 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 void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException { + Path path = pluginPath.resolve(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); + try (Writer writer = new OutputStreamWriter(new FileOutputStream(path.toFile()), StandardCharsets.UTF_8)) { + properties.store(writer, ""); + } } } diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index efb326e..1f51e95 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.plugin.PluginZip; +import org.pf4j.plugin.TestPlugin; import java.io.FileOutputStream; import java.io.IOException; @@ -78,7 +79,7 @@ public class PropertiesPluginDescriptorFinderTest { assertEquals("test-plugin-1", plugin1.getPluginId()); assertEquals("Test Plugin 1", plugin1.getPluginDescription()); - assertEquals("org.pf4j.plugin.TestPlugin", plugin1.getPluginClass()); + assertEquals(TestPlugin.class.getName(), plugin1.getPluginClass()); assertEquals("0.0.1", plugin1.getVersion()); assertEquals("Decebal Suiu", plugin1.getProvider()); assertEquals(2, plugin1.getDependencies().size()); @@ -92,7 +93,7 @@ public class PropertiesPluginDescriptorFinderTest { assertEquals("test-plugin-2", plugin2.getPluginId()); assertEquals("", plugin2.getPluginDescription()); - assertEquals("org.pf4j.plugin.TestPlugin", plugin2.getPluginClass()); + assertEquals(TestPlugin.class.getName(), plugin2.getPluginClass()); assertEquals("0.0.1", plugin2.getVersion()); assertEquals("Decebal Suiu", plugin2.getProvider()); assertEquals(0, plugin2.getDependencies().size()); @@ -109,10 +110,10 @@ public class PropertiesPluginDescriptorFinderTest { 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_CLASS, "org.pf4j.plugin.TestPlugin"); 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"); @@ -123,9 +124,9 @@ public class PropertiesPluginDescriptorFinderTest { 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_CLASS, "org.pf4j.plugin.TestPlugin"); map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); return PluginZip.createProperties(map); @@ -145,8 +146,8 @@ public class PropertiesPluginDescriptorFinderTest { 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_CLASS, "org.pf4j.plugin.TestPlugin"); map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); @@ -155,9 +156,9 @@ public class PropertiesPluginDescriptorFinderTest { 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_CLASS, "org.pf4j.plugin.TestPlugin"); map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, ""); map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*"); diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java index 2301285..d486ef8 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java @@ -37,11 +37,13 @@ public class PluginJar { private final Path path; private final String pluginId; + private final String pluginClass; private final String pluginVersion; protected PluginJar(Builder builder) { this.path = builder.path; this.pluginId = builder.pluginId; + this.pluginClass = builder.pluginClass; this.pluginVersion = builder.pluginVersion; } @@ -49,6 +51,10 @@ public class PluginJar { return path; } + public String pluginClass() { + return pluginClass; + } + public String pluginId() { return pluginId; } @@ -73,6 +79,7 @@ public class PluginJar { private final Path path; private final String pluginId; + private String pluginClass; private String pluginVersion; private Map attributes; @@ -81,6 +88,12 @@ public class PluginJar { this.pluginId = pluginId; } + public Builder pluginClass(String pluginClass) { + this.pluginClass = pluginClass; + + return this; + } + public Builder pluginVersion(String pluginVersion) { this.pluginVersion = pluginVersion; @@ -106,7 +119,9 @@ public class PluginJar { Map map = new LinkedHashMap<>(); map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, pluginId); map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); - map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); + if (pluginClass != null) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); + } if (attributes != null) { map.putAll(attributes); } diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java index 8e610c1..5f705e1 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java @@ -36,11 +36,13 @@ public class PluginZip { private final Path path; private final String pluginId; + private final String pluginClass; private final String pluginVersion; protected PluginZip(Builder builder) { this.path = builder.path; this.pluginId = builder.pluginId; + this.pluginClass = builder.pluginClass; this.pluginVersion = builder.pluginVersion; } @@ -52,6 +54,10 @@ public class PluginZip { return pluginId; } + public String pluginClass() { + return pluginClass; + } + public String pluginVersion() { return pluginVersion; } @@ -75,6 +81,7 @@ public class PluginZip { private final Path path; private final String pluginId; + private String pluginClass; private String pluginVersion; private Map properties; @@ -83,6 +90,12 @@ public class PluginZip { this.pluginId = pluginId; } + public Builder pluginClass(String pluginClass) { + this.pluginClass = pluginClass; + + return this; + } + public Builder pluginVersion(String pluginVersion) { this.pluginVersion = pluginVersion; @@ -108,7 +121,9 @@ public class PluginZip { Map map = new LinkedHashMap<>(); map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, pluginId); map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin"); + if (pluginClass != null) { + map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); + } if (properties != null) { map.putAll(properties); } From 8a2674c5392de62a97e4d0b33e4dd94dbaae407d Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 20 Apr 2019 13:50:58 +0300 Subject: [PATCH 33/54] Improve #292 --- .../java/org/pf4j/AbstractPluginManager.java | 63 +++++++------------ .../java/org/pf4j/BasePluginRepository.java | 4 +- .../org/pf4j/CompoundPluginRepository.java | 2 +- .../org/pf4j/DefaultPluginRepository.java | 2 +- .../org/pf4j/DefaultPluginStatusProvider.java | 32 ++++------ .../src/main/java/org/pf4j/PluginManager.java | 12 ++-- .../main/java/org/pf4j/PluginRepository.java | 2 +- .../java/org/pf4j/PluginStatusProvider.java | 6 +- .../org/pf4j/DefaultPluginRepositoryTest.java | 2 +- .../pf4j/DefaultPluginStatusProviderTest.java | 21 ++++--- .../org/pf4j/JarPluginRepositoryTest.java | 3 +- 11 files changed, 60 insertions(+), 89 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 3833588..4fa1d38 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -232,11 +232,11 @@ public abstract class AbstractPluginManager implements PluginManager { * Unload the specified plugin and it's dependents. */ @Override - public boolean unloadPlugin(String pluginId) { + public boolean unloadPlugin(String pluginId) throws PluginException { return unloadPlugin(pluginId, true); } - private boolean unloadPlugin(String pluginId, boolean unloadDependents) { + private boolean unloadPlugin(String pluginId, boolean unloadDependents) throws PluginException { try { if (unloadDependents) { List dependents = dependencyResolver.getDependents(pluginId); @@ -269,7 +269,7 @@ public abstract class AbstractPluginManager implements PluginManager { try { ((Closeable) classLoader).close(); } catch (IOException e) { - log.error("Cannot close classloader", e); + throw new PluginException("Cannot close classloader", e); } } } @@ -283,7 +283,7 @@ public abstract class AbstractPluginManager implements PluginManager { } @Override - public boolean deletePlugin(String pluginId) { + public boolean deletePlugin(String pluginId) throws PluginException { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -304,12 +304,7 @@ public abstract class AbstractPluginManager implements PluginManager { } // notify the plugin as it's deleted - try { - plugin.delete(); - } catch (PluginException e) { - log.error(e.getMessage(), e); - return false; - } + plugin.delete(); Path pluginPath = pluginWrapper.getPluginPath(); @@ -342,7 +337,7 @@ public abstract class AbstractPluginManager implements PluginManager { * Start the specified plugin and its dependencies. */ @Override - public PluginState startPlugin(String pluginId) { + public PluginState startPlugin(String pluginId) throws PluginException { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -369,16 +364,12 @@ public abstract class AbstractPluginManager implements PluginManager { startPlugin(dependency.getPluginId()); } - try { - log.info("Start plugin '{}'", getPluginLabel(pluginDescriptor)); - pluginWrapper.getPlugin().start(); - pluginWrapper.setPluginState(PluginState.STARTED); - startedPlugins.add(pluginWrapper); + log.info("Start plugin '{}'", getPluginLabel(pluginDescriptor)); + pluginWrapper.getPlugin().start(); + pluginWrapper.setPluginState(PluginState.STARTED); + startedPlugins.add(pluginWrapper); - firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState)); - } catch (PluginException e) { - log.error(e.getMessage(), e); - } + firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState)); return pluginWrapper.getPluginState(); } @@ -413,11 +404,11 @@ public abstract class AbstractPluginManager implements PluginManager { * Stop the specified plugin and it's dependents. */ @Override - public PluginState stopPlugin(String pluginId) { + public PluginState stopPlugin(String pluginId) throws PluginException { return stopPlugin(pluginId, true); } - private PluginState stopPlugin(String pluginId, boolean stopDependents) { + private PluginState stopPlugin(String pluginId, boolean stopDependents) throws PluginException { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -443,16 +434,12 @@ public abstract class AbstractPluginManager implements PluginManager { } } - try { - log.info("Stop plugin '{}'", getPluginLabel(pluginDescriptor)); - pluginWrapper.getPlugin().stop(); - pluginWrapper.setPluginState(PluginState.STOPPED); - startedPlugins.remove(pluginWrapper); + log.info("Stop plugin '{}'", getPluginLabel(pluginDescriptor)); + pluginWrapper.getPlugin().stop(); + pluginWrapper.setPluginState(PluginState.STOPPED); + startedPlugins.remove(pluginWrapper); - firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState)); - } catch (PluginException e) { - log.error(e.getMessage(), e); - } + firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState)); return pluginWrapper.getPluginState(); } @@ -464,7 +451,7 @@ public abstract class AbstractPluginManager implements PluginManager { } @Override - public boolean disablePlugin(String pluginId) { + public boolean disablePlugin(String pluginId) throws PluginException { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -480,10 +467,7 @@ public abstract class AbstractPluginManager implements PluginManager { firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, PluginState.STOPPED)); - if (!pluginStatusProvider.disablePlugin(pluginId)) { - return false; - } - + pluginStatusProvider.disablePlugin(pluginId); log.info("Disabled plugin '{}'", getPluginLabel(pluginDescriptor)); return true; @@ -493,7 +477,7 @@ public abstract class AbstractPluginManager implements PluginManager { } @Override - public boolean enablePlugin(String pluginId) { + public boolean enablePlugin(String pluginId) throws PluginException { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -509,9 +493,7 @@ public abstract class AbstractPluginManager implements PluginManager { return true; } - if (!pluginStatusProvider.enablePlugin(pluginId)) { - return false; - } + pluginStatusProvider.enablePlugin(pluginId); pluginWrapper.setPluginState(PluginState.CREATED); @@ -612,7 +594,6 @@ public abstract class AbstractPluginManager implements PluginManager { return extensionFactory; } - // TODO remove public PluginLoader getPluginLoader() { return pluginLoader; } diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java index aa152be..b083994 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java @@ -86,7 +86,7 @@ public class BasePluginRepository implements PluginRepository { } @Override - public boolean deletePluginPath(Path pluginPath) { + public boolean deletePluginPath(Path pluginPath) throws PluginException { if (!filter.accept(pluginPath.toFile())) { return false; } @@ -97,7 +97,7 @@ public class BasePluginRepository implements PluginRepository { } catch (NoSuchFileException e) { return false; // Return false on not found to be compatible with previous API (#135) } catch (IOException e) { - throw new RuntimeException(e); + throw new PluginException(e); } } diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java index 705b912..c738191 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java @@ -48,7 +48,7 @@ public class CompoundPluginRepository implements PluginRepository { } @Override - public boolean deletePluginPath(Path pluginPath) { + public boolean deletePluginPath(Path pluginPath) throws PluginException { for (PluginRepository repository : repositories) { if (repository.deletePluginPath(pluginPath)) { return true; diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java index da456eb..1c031b6 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java @@ -54,7 +54,7 @@ public class DefaultPluginRepository extends BasePluginRepository { } @Override - public boolean deletePluginPath(Path pluginPath) { + public boolean deletePluginPath(Path pluginPath) throws PluginException { FileUtils.optimisticDelete(FileUtils.findWithEnding(pluginPath, ".zip", ".ZIP", ".Zip")); return super.deletePluginPath(pluginPath); } diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java b/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java index ca85407..823a29c 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java @@ -66,31 +66,23 @@ public class DefaultPluginStatusProvider implements PluginStatusProvider { } @Override - public boolean disablePlugin(String pluginId) { - if (disabledPlugins.add(pluginId)) { - try { - FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile()); - } catch (IOException e) { - log.error("Failed to disable plugin {}", pluginId, e); - return false; - } + public void disablePlugin(String pluginId) throws PluginException { + disabledPlugins.add(pluginId); + try { + FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile()); + } catch (IOException e) { + throw new PluginException(e); } - - return true; } @Override - public boolean enablePlugin(String pluginId) { - if (disabledPlugins.remove(pluginId)) { - try { - FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile()); - } catch (IOException e) { - log.error("Failed to enable plugin {}", pluginId, e); - return false; - } + public void enablePlugin(String pluginId) throws PluginException { + disabledPlugins.remove(pluginId); + try { + FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile()); + } catch (IOException e) { + throw new PluginException(e); } - - return true; } } diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java index 11d3eac..a283738 100644 --- a/pf4j/src/main/java/org/pf4j/PluginManager.java +++ b/pf4j/src/main/java/org/pf4j/PluginManager.java @@ -85,7 +85,7 @@ public interface PluginManager { * * @return the plugin state */ - PluginState startPlugin(String pluginId); + PluginState startPlugin(String pluginId) throws PluginException; /** * Stop all active plugins. @@ -97,7 +97,7 @@ public interface PluginManager { * * @return the plugin state */ - PluginState stopPlugin(String pluginId); + PluginState stopPlugin(String pluginId) throws PluginException; /** * Unload a plugin. @@ -105,7 +105,7 @@ public interface PluginManager { * @param pluginId the unique plugin identifier, specified in its metadata * @return true if the plugin was unloaded */ - boolean unloadPlugin(String pluginId); + boolean unloadPlugin(String pluginId) throws PluginException; /** * Disables a plugin from being loaded. @@ -113,7 +113,7 @@ public interface PluginManager { * @param pluginId the unique plugin identifier, specified in its metadata * @return true if plugin is disabled */ - boolean disablePlugin(String pluginId); + boolean disablePlugin(String pluginId) throws PluginException; /** * Enables a plugin that has previously been disabled. @@ -121,7 +121,7 @@ public interface PluginManager { * @param pluginId the unique plugin identifier, specified in its metadata * @return true if plugin is enabled */ - boolean enablePlugin(String pluginId); + boolean enablePlugin(String pluginId) throws PluginException; /** * Deletes a plugin. @@ -129,7 +129,7 @@ public interface PluginManager { * @param pluginId the unique plugin identifier, specified in its metadata * @return true if the plugin was deleted */ - boolean deletePlugin(String pluginId); + boolean deletePlugin(String pluginId) throws PluginException; ClassLoader getPluginClassLoader(String pluginId); diff --git a/pf4j/src/main/java/org/pf4j/PluginRepository.java b/pf4j/src/main/java/org/pf4j/PluginRepository.java index d0b2125..941d68f 100644 --- a/pf4j/src/main/java/org/pf4j/PluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/PluginRepository.java @@ -39,6 +39,6 @@ public interface PluginRepository { * @param pluginPath the plugin path * @return true if deleted */ - boolean deletePluginPath(Path pluginPath); + boolean deletePluginPath(Path pluginPath) throws PluginException; } diff --git a/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java b/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java index dda5f82..228575f 100644 --- a/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java +++ b/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java @@ -33,16 +33,14 @@ public interface PluginStatusProvider { * Disables a plugin from being loaded. * * @param pluginId the unique plugin identifier, specified in its metadata - * @return true if plugin is disabled */ - boolean disablePlugin(String pluginId); + void disablePlugin(String pluginId) throws PluginException; /** * Enables a plugin that has previously been disabled. * * @param pluginId the unique plugin identifier, specified in its metadata - * @return true if plugin is enabled */ - boolean enablePlugin(String pluginId); + void enablePlugin(String pluginId) throws PluginException; } diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java index 3aaba8f..3805c42 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -85,7 +85,7 @@ public class DefaultPluginRepositoryTest { * Test of {@link DefaultPluginRepository#deletePluginPath(Path)} method. */ @Test - public void testDeletePluginPath() { + public void testDeletePluginPath() throws PluginException { PluginRepository repository = new DefaultPluginRepository(pluginsPath, false); assertTrue(Files.exists(pluginsPath.resolve("plugin-1.zip"))); diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java index 635e41c..e766735 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java @@ -60,58 +60,59 @@ public class DefaultPluginStatusProviderTest { } @Test - public void testDisablePlugin() throws IOException { + public void testDisablePlugin() throws Exception { createEnabledFile(); createDisabledFile(); PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath); + statusProvider.disablePlugin("plugin-1"); - assertTrue(statusProvider.disablePlugin("plugin-1")); assertTrue(statusProvider.isPluginDisabled("plugin-1")); assertTrue(statusProvider.isPluginDisabled("plugin-2")); assertTrue(statusProvider.isPluginDisabled("plugin-3")); } @Test - public void testDisablePluginWithEnableEmpty() throws IOException { + public void testDisablePluginWithEnableEmpty() throws Exception { createDisabledFile(); PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath); + statusProvider.disablePlugin("plugin-1"); - assertTrue(statusProvider.disablePlugin("plugin-1")); assertTrue(statusProvider.isPluginDisabled("plugin-1")); assertTrue(statusProvider.isPluginDisabled("plugin-2")); assertFalse(statusProvider.isPluginDisabled("plugin-3")); } @Test - public void testEnablePlugin() throws IOException { + public void testEnablePlugin() throws Exception { createEnabledFile(); PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath); + statusProvider.enablePlugin("plugin-2"); - assertTrue(statusProvider.enablePlugin("plugin-2")); assertFalse(statusProvider.isPluginDisabled("plugin-1")); assertFalse(statusProvider.isPluginDisabled("plugin-2")); assertTrue(statusProvider.isPluginDisabled("plugin-3")); } @Test - public void testEnablePluginWithEnableEmpty() { + public void testEnablePluginWithEnableEmpty() throws Exception{ PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath); + statusProvider.enablePlugin("plugin-2"); - assertTrue(statusProvider.enablePlugin("plugin-2")); assertFalse(statusProvider.isPluginDisabled("plugin-1")); assertFalse(statusProvider.isPluginDisabled("plugin-2")); assertFalse(statusProvider.isPluginDisabled("plugin-3")); } @Test - public void testDisablePluginWithoutDisabledFile() { + public void testDisablePluginWithoutDisabledFile() throws Exception { PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath); assertFalse(statusProvider.isPluginDisabled("plugin-1")); - assertTrue(statusProvider.disablePlugin("plugin-1")); + + statusProvider.disablePlugin("plugin-1"); assertTrue(statusProvider.isPluginDisabled("plugin-1")); } diff --git a/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java index 2260680..02d2bcc 100644 --- a/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java @@ -18,7 +18,6 @@ package org.pf4j; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -39,7 +38,7 @@ public class JarPluginRepositoryTest { * Test of {@link JarPluginRepository#deletePluginPath(Path)} method. */ @Test - public void testDeletePluginPath() throws IOException { + public void testDeletePluginPath() throws Exception { PluginRepository repository = new JarPluginRepository(pluginsPath); Path plugin1Path = Files.createDirectory(pluginsPath.resolve("plugin-1")); From 65e8fe76c8da4049f58c263b651e77c80b375067 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 20 Apr 2019 21:30:34 +0300 Subject: [PATCH 34/54] Improve #292 --- .../java/org/pf4j/AbstractPluginManager.java | 19 ++++++++++--- .../org/pf4j/DefaultExtensionFactory.java | 10 +++---- .../main/java/org/pf4j/ExtensionFactory.java | 2 +- .../main/java/org/pf4j/ExtensionWrapper.java | 2 +- .../org/pf4j/SingletonExtensionFactory.java | 7 ++--- .../org/pf4j/DefaultExtensionFactoryTest.java | 27 ++++++++++++------- .../pf4j/SingletonExtensionFactoryTest.java | 4 +-- 7 files changed, 45 insertions(+), 26 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 4fa1d38..a7333ca 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -521,6 +521,7 @@ public abstract class AbstractPluginManager implements PluginManager { Class c = extensionWrapper.getDescriptor().extensionClass; extensionClasses.add(c); } + return extensionClasses; } @@ -555,7 +556,11 @@ public abstract class AbstractPluginManager implements PluginManager { List> extensionsWrapper = extensionFinder.find(type); List extensions = new ArrayList<>(extensionsWrapper.size()); for (ExtensionWrapper extensionWrapper : extensionsWrapper) { - extensions.add(extensionWrapper.getExtension()); + try { + extensions.add(extensionWrapper.getExtension()); + } catch (PluginException e) { + log.error("Cannot retrieve extension", e); + } } return extensions; @@ -566,7 +571,11 @@ public abstract class AbstractPluginManager implements PluginManager { List> extensionsWrapper = extensionFinder.find(type, pluginId); List extensions = new ArrayList<>(extensionsWrapper.size()); for (ExtensionWrapper extensionWrapper : extensionsWrapper) { - extensions.add(extensionWrapper.getExtension()); + try { + extensions.add(extensionWrapper.getExtension()); + } catch (PluginException e) { + log.error("Cannot retrieve extension", e); + } } return extensions; @@ -578,7 +587,11 @@ public abstract class AbstractPluginManager implements PluginManager { List extensionsWrapper = extensionFinder.find(pluginId); List extensions = new ArrayList<>(extensionsWrapper.size()); for (ExtensionWrapper extensionWrapper : extensionsWrapper) { - extensions.add(extensionWrapper.getExtension()); + try { + extensions.add(extensionWrapper.getExtension()); + } catch (PluginException e) { + log.error("Cannot retrieve extension", e); + } } return extensions; diff --git a/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java b/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java index bd67032..fbcba27 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java +++ b/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java @@ -29,20 +29,16 @@ public class DefaultExtensionFactory implements ExtensionFactory { private static final Logger log = LoggerFactory.getLogger(DefaultExtensionFactory.class); /** - * Creates an extension instance. If an error occurs than that error is logged and the method returns {@code null}. - * @param extensionClass - * @return + * Creates an extension instance. */ @Override - public Object create(Class extensionClass) { + public T create(Class extensionClass) throws PluginException { log.debug("Create instance for extension '{}'", extensionClass.getName()); try { return extensionClass.newInstance(); } catch (Exception e) { - log.error(e.getMessage(), e); + throw new PluginException(e); } - - return null; } } diff --git a/pf4j/src/main/java/org/pf4j/ExtensionFactory.java b/pf4j/src/main/java/org/pf4j/ExtensionFactory.java index 177d489..42b0de8 100644 --- a/pf4j/src/main/java/org/pf4j/ExtensionFactory.java +++ b/pf4j/src/main/java/org/pf4j/ExtensionFactory.java @@ -20,6 +20,6 @@ package org.pf4j; */ public interface ExtensionFactory { - Object create(Class extensionClass); + T create(Class extensionClass) throws PluginException; } diff --git a/pf4j/src/main/java/org/pf4j/ExtensionWrapper.java b/pf4j/src/main/java/org/pf4j/ExtensionWrapper.java index 3899d5f..85c5b91 100644 --- a/pf4j/src/main/java/org/pf4j/ExtensionWrapper.java +++ b/pf4j/src/main/java/org/pf4j/ExtensionWrapper.java @@ -32,7 +32,7 @@ public class ExtensionWrapper implements Comparable> { } @SuppressWarnings("unchecked") - public T getExtension() { + public T getExtension() throws PluginException { if (extension == null) { extension = (T) extensionFactory.create(descriptor.extensionClass); } diff --git a/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java b/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java index d339921..3da97d0 100644 --- a/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java +++ b/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java @@ -39,13 +39,14 @@ public class SingletonExtensionFactory extends DefaultExtensionFactory { } @Override - public Object create(Class extensionClass) { + @SuppressWarnings("unchecked") + public T create(Class extensionClass) throws PluginException { String extensionClassName = extensionClass.getName(); if (cache.containsKey(extensionClassName)) { - return cache.get(extensionClassName); + return (T) cache.get(extensionClassName); } - Object extension = super.create(extensionClass); + T extension = super.create(extensionClass); if (extensionClassNames.isEmpty() || extensionClassNames.contains(extensionClassName)) { cache.put(extensionClassName, extension); } diff --git a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java index 13327cc..207c178 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java @@ -15,27 +15,38 @@ */ package org.pf4j; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.pf4j.plugin.FailTestExtension; import org.pf4j.plugin.TestExtension; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; /** - * * @author Mario Franco */ public class DefaultExtensionFactoryTest { + private ExtensionFactory extensionFactory; + + @BeforeEach + public void setUp() { + extensionFactory = new DefaultExtensionFactory(); + } + + @AfterEach + public void tearDown() { + extensionFactory = null; + } + /** * Test of create method, of class DefaultExtensionFactory. */ @Test - public void testCreate() { - DefaultExtensionFactory instance = new DefaultExtensionFactory(); - Object result = instance.create(TestExtension.class); - assertNotNull(result); + public void testCreate() throws PluginException { + assertNotNull(extensionFactory.create(TestExtension.class)); } /** @@ -43,9 +54,7 @@ public class DefaultExtensionFactoryTest { */ @Test public void testCreateFailConstructor() { - DefaultExtensionFactory instance = new DefaultExtensionFactory(); - Object result = instance.create(FailTestExtension.class); - assertNull(result); + assertThrows(PluginException.class, () -> extensionFactory.create(FailTestExtension.class)); } } diff --git a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java index 80e7ab0..97e98cf 100644 --- a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java @@ -28,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.assertSame; public class SingletonExtensionFactoryTest { @Test - public void create() { + public void create() throws PluginException { ExtensionFactory extensionFactory = new SingletonExtensionFactory(); Object extensionOne = extensionFactory.create(TestExtension.class); Object extensionTwo = extensionFactory.create(TestExtension.class); @@ -36,7 +36,7 @@ public class SingletonExtensionFactoryTest { } @Test - public void createNewEachTime() { + public void createNewEachTime() throws PluginException { ExtensionFactory extensionFactory = new SingletonExtensionFactory(FailTestExtension.class.getName()); Object extensionOne = extensionFactory.create(TestExtension.class); Object extensionTwo = extensionFactory.create(TestExtension.class); From fd916791822fe3dcd83ed7a197d17f8903668049 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 20 Apr 2019 22:00:17 +0300 Subject: [PATCH 35/54] Add AbstractPluginManagerTest --- .../org/pf4j/AbstractPluginManagerTest.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java diff --git a/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java new file mode 100644 index 0000000..784d1f9 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +import org.junit.jupiter.api.Test; +import org.pf4j.plugin.TestExtension; +import org.pf4j.plugin.TestExtensionPoint; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * @author Decebal Suiu + */ +public class AbstractPluginManagerTest { + + @Test + public void getExtensionsByType() { + AbstractPluginManager pluginManager = mock(AbstractPluginManager.class, CALLS_REAL_METHODS); + + ExtensionFinder extensionFinder = mock(ExtensionFinder.class); + List> extensionList = new ArrayList<>(1); + extensionList.add(new ExtensionWrapper<>(new ExtensionDescriptor(0, TestExtension.class), new DefaultExtensionFactory())); + when(extensionFinder.find(TestExtensionPoint.class)).thenReturn(extensionList); + + pluginManager.extensionFinder = extensionFinder; + List extensions = pluginManager.getExtensions(TestExtensionPoint.class); + assertEquals(1, extensions.size()); + } + +} From a6ce0a6ace6c03a7369236350b5f8e4a61e4c381 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 20 Apr 2019 22:36:35 +0300 Subject: [PATCH 36/54] Add DirectedGraphTest --- .../java/org/pf4j/util/DirectedGraphTest.java | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 pf4j/src/test/java/org/pf4j/util/DirectedGraphTest.java diff --git a/pf4j/src/test/java/org/pf4j/util/DirectedGraphTest.java b/pf4j/src/test/java/org/pf4j/util/DirectedGraphTest.java new file mode 100644 index 0000000..44b8c54 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/util/DirectedGraphTest.java @@ -0,0 +1,98 @@ +/* + * Copyright 2015 Decebal Suiu + * + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j.util; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Decebal Suiu + */ +public class DirectedGraphTest { + + private static DirectedGraph graph; + + @BeforeAll + public static void setUp() { + graph = new DirectedGraph<>(); + + // add vertex + graph.addVertex('A'); + graph.addVertex('B'); + graph.addVertex('C'); + graph.addVertex('D'); + graph.addVertex('E'); + graph.addVertex('F'); + graph.addVertex('G'); + + // add edges + graph.addEdge('A', 'B'); + graph.addEdge('B', 'C'); + graph.addEdge('B', 'F'); + graph.addEdge('D', 'E'); + graph.addEdge('F', 'G'); + } + + @Test + public void reverseTopologicalSort() { + List result = graph.reverseTopologicalSort(); + List expected = Arrays.asList('C', 'G', 'F', 'B', 'A', 'E', 'D'); + assertEquals(expected, result); + } + + @Test + public void topologicalSort() { + List result = graph.topologicalSort(); + List expected = Arrays.asList('D', 'E', 'A', 'B', 'F', 'G', 'C'); + assertEquals(expected, result); + } + + @Test + public void inDegree() { + Map result = graph.inDegree(); + Map expected = new HashMap<>(7); + expected.put('A', 0); + expected.put('B', 1); + expected.put('C', 1); + expected.put('D', 0); + expected.put('E', 1); + expected.put('F', 1); + expected.put('G', 1); + assertEquals(expected, result); + } + + @Test + public void outDegree() { + Map result = graph.outDegree(); + Map expected = new HashMap<>(7); + expected.put('A', 1); + expected.put('B', 2); + expected.put('C', 0); + expected.put('D', 1); + expected.put('E', 0); + expected.put('F', 1); + expected.put('G', 0); + assertEquals(expected, result); + } + +} From 1d36fcff75cfe38639fc1a8a28eefc79e8e7286f Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Thu, 2 May 2019 14:11:30 +0300 Subject: [PATCH 37/54] Resolve #296 --- .../app/src/main/java/org/pf4j/demo/Boot.java | 4 +- .../java/org/pf4j/AbstractPluginManager.java | 73 ++++++++----------- .../src/main/java/org/pf4j/PluginManager.java | 4 +- 3 files changed, 35 insertions(+), 46 deletions(-) diff --git a/demo/app/src/main/java/org/pf4j/demo/Boot.java b/demo/app/src/main/java/org/pf4j/demo/Boot.java index 562f8f8..066a207 100644 --- a/demo/app/src/main/java/org/pf4j/demo/Boot.java +++ b/demo/app/src/main/java/org/pf4j/demo/Boot.java @@ -73,8 +73,8 @@ public class Boot { } System.out.println("Extension classes by classpath:"); - List> greetingsClasses = pluginManager.getExtensionClasses(Greeting.class); - for (Class greeting : greetingsClasses) { + List> greetingsClasses = pluginManager.getExtensionClasses(Greeting.class); + for (Class greeting : greetingsClasses) { System.out.println(" Class: " + greeting.getCanonicalName()); } diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index a7333ca..478149d 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -525,60 +525,25 @@ public abstract class AbstractPluginManager implements PluginManager { return extensionClasses; } - @SuppressWarnings("unchecked") - @Override - public List> getExtensionClasses(Class type) { - List> extensionsWrapper = extensionFinder.find(type); - List> extensionClasses = new ArrayList<>(extensionsWrapper.size()); - for (ExtensionWrapper extensionWrapper : extensionsWrapper) { - Class c = (Class) extensionWrapper.getDescriptor().extensionClass; - extensionClasses.add(c); - } - return extensionClasses; + @Override + public List> getExtensionClasses(Class type) { + return getExtensionClasses(extensionFinder.find(type)); } - @SuppressWarnings("unchecked") @Override - public List> getExtensionClasses(Class type, String pluginId) { - List> extensionsWrapper = extensionFinder.find(type, pluginId); - List> extensionClasses = new ArrayList<>(extensionsWrapper.size()); - for (ExtensionWrapper extensionWrapper : extensionsWrapper) { - Class c = (Class) extensionWrapper.getDescriptor().extensionClass; - extensionClasses.add(c); - } - - return extensionClasses; + public List> getExtensionClasses(Class type, String pluginId) { + return getExtensionClasses(extensionFinder.find(type, pluginId)); } @Override public List getExtensions(Class type) { - List> extensionsWrapper = extensionFinder.find(type); - List extensions = new ArrayList<>(extensionsWrapper.size()); - for (ExtensionWrapper extensionWrapper : extensionsWrapper) { - try { - extensions.add(extensionWrapper.getExtension()); - } catch (PluginException e) { - log.error("Cannot retrieve extension", e); - } - } - - return extensions; + return getExtensions(extensionFinder.find(type)); } @Override public List getExtensions(Class type, String pluginId) { - List> extensionsWrapper = extensionFinder.find(type, pluginId); - List extensions = new ArrayList<>(extensionsWrapper.size()); - for (ExtensionWrapper extensionWrapper : extensionsWrapper) { - try { - extensions.add(extensionWrapper.getExtension()); - } catch (PluginException e) { - log.error("Cannot retrieve extension", e); - } - } - - return extensions; + return getExtensions(extensionFinder.find(type, pluginId)); } @Override @@ -943,4 +908,28 @@ public abstract class AbstractPluginManager implements PluginManager { return pluginDescriptor.getPluginId() + "@" + pluginDescriptor.getVersion(); } + @SuppressWarnings("unchecked") + private List> getExtensionClasses(List> extensionsWrapper) { + List> extensionClasses = new ArrayList<>(extensionsWrapper.size()); + for (ExtensionWrapper extensionWrapper : extensionsWrapper) { + Class c = (Class) extensionWrapper.getDescriptor().extensionClass; + extensionClasses.add(c); + } + + return extensionClasses; + } + + private List getExtensions(List> extensionsWrapper) { + List extensions = new ArrayList<>(extensionsWrapper.size()); + for (ExtensionWrapper extensionWrapper : extensionsWrapper) { + try { + extensions.add(extensionWrapper.getExtension()); + } catch (PluginException e) { + log.error("Cannot retrieve extension", e); + } + } + + return extensions; + } + } diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java index a283738..badba28 100644 --- a/pf4j/src/main/java/org/pf4j/PluginManager.java +++ b/pf4j/src/main/java/org/pf4j/PluginManager.java @@ -135,9 +135,9 @@ public interface PluginManager { List> getExtensionClasses(String pluginId); - List> getExtensionClasses(Class type); + List> getExtensionClasses(Class type); - List> getExtensionClasses(Class type, String pluginId); + List> getExtensionClasses(Class type, String pluginId); List getExtensions(Class type); From 73ac9c0d2bef43362719c3857648831d59f3480f Mon Sep 17 00:00:00 2001 From: decebals Date: Thu, 2 May 2019 21:44:36 +0300 Subject: [PATCH 38/54] Extract constants for some system property namse --- pf4j/src/main/java/org/pf4j/AbstractPluginManager.java | 6 ++++-- pf4j/src/main/java/org/pf4j/DefaultPluginManager.java | 9 +++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 478149d..a940610 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -44,6 +44,8 @@ public abstract class AbstractPluginManager implements PluginManager { private static final Logger log = LoggerFactory.getLogger(AbstractPluginManager.class); + public static final String PLUGINS_DIR_PROPERTY_NAME = "pf4j.pluginsDir"; + private Path pluginsRoot; protected ExtensionFinder extensionFinder; @@ -682,14 +684,14 @@ public abstract class AbstractPluginManager implements PluginManager { /** * Add the possibility to override the plugins root. - * If a {@code pf4j.pluginsDir} system property is defined than this method returns that root. + * If a {@link #PLUGINS_DIR_PROPERTY_NAME} system property is defined than this method returns that root. * If {@link #getRuntimeMode()} returns {@link RuntimeMode#DEVELOPMENT} than {@code ../plugins} * is returned else this method returns {@code plugins}. * * @return the plugins root */ protected Path createPluginsRoot() { - String pluginsDir = System.getProperty("pf4j.pluginsDir"); + String pluginsDir = System.getProperty(PLUGINS_DIR_PROPERTY_NAME); if (pluginsDir == null) { if (isDevelopment()) { pluginsDir = "../plugins"; diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java index b64ddbb..db5678b 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java @@ -35,6 +35,8 @@ public class DefaultPluginManager extends AbstractPluginManager { private static final Logger log = LoggerFactory.getLogger(DefaultPluginManager.class); + public static final String PLUGINS_DIR_CONFIG_PROPERTY_NAME = "pf4j.pluginsConfigDir"; + protected PluginClasspath pluginClasspath; public DefaultPluginManager() { @@ -72,7 +74,7 @@ public class DefaultPluginManager extends AbstractPluginManager { @Override protected PluginStatusProvider createPluginStatusProvider() { - String configDir = System.getProperty("pf4j.pluginsConfigDir"); + String configDir = System.getProperty(PLUGINS_DIR_CONFIG_PROPERTY_NAME); Path configPath = configDir != null ? Paths.get(configDir) : getPluginsRoot(); return new DefaultPluginStatusProvider(configPath); } @@ -97,9 +99,8 @@ public class DefaultPluginManager extends AbstractPluginManager { } /** - * By default if {@link DefaultPluginManager#isDevelopment()} returns true - * than a {@link DevelopmentPluginClasspath} is returned - * else this method returns {@link DefaultPluginClasspath}. + * By default if {@link #isDevelopment()} returns {@code true} than a {@link DevelopmentPluginClasspath} + * is returned, else this method returns {@link DefaultPluginClasspath}. */ protected PluginClasspath createPluginClasspath() { return isDevelopment() ? new DevelopmentPluginClasspath() : new DefaultPluginClasspath(); From fde642e63a6a0165d0e60b80f6fc559368f712e7 Mon Sep 17 00:00:00 2001 From: decebals Date: Thu, 2 May 2019 21:51:05 +0300 Subject: [PATCH 39/54] Extract constants for some strings --- .../main/java/org/pf4j/AbstractPluginManager.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index a940610..9e86909 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -45,6 +45,8 @@ public abstract class AbstractPluginManager implements PluginManager { private static final Logger log = LoggerFactory.getLogger(AbstractPluginManager.class); public static final String PLUGINS_DIR_PROPERTY_NAME = "pf4j.pluginsDir"; + public static final String DEFAULT_PLUGINS_DIR = "plugins"; + public static final String DEVELOPMENT_PLUGINS_DIR = "../plugins"; private Path pluginsRoot; @@ -685,19 +687,15 @@ public abstract class AbstractPluginManager implements PluginManager { /** * Add the possibility to override the plugins root. * If a {@link #PLUGINS_DIR_PROPERTY_NAME} system property is defined than this method returns that root. - * If {@link #getRuntimeMode()} returns {@link RuntimeMode#DEVELOPMENT} than {@code ../plugins} - * is returned else this method returns {@code plugins}. + * If {@link #getRuntimeMode()} returns {@link RuntimeMode#DEVELOPMENT} than {@link #DEVELOPMENT_PLUGINS_DIR} + * is returned else this method returns {@link #DEFAULT_PLUGINS_DIR}. * * @return the plugins root */ protected Path createPluginsRoot() { String pluginsDir = System.getProperty(PLUGINS_DIR_PROPERTY_NAME); if (pluginsDir == null) { - if (isDevelopment()) { - pluginsDir = "../plugins"; - } else { - pluginsDir = "plugins"; - } + pluginsDir = isDevelopment() ? DEVELOPMENT_PLUGINS_DIR : DEFAULT_PLUGINS_DIR; } return Paths.get(pluginsDir); From a487cbf37a0e3c6d36113d5da7c0571398a19d43 Mon Sep 17 00:00:00 2001 From: decebals Date: Fri, 3 May 2019 01:08:02 +0300 Subject: [PATCH 40/54] Improve #307 (add support for development mode) --- .../java/org/pf4j/AbstractPluginManager.java | 4 +- .../main/java/org/pf4j/BasePluginLoader.java | 88 +++++++++++++++++++ .../java/org/pf4j/CompoundPluginLoader.java | 16 ++++ .../org/pf4j/CompoundPluginRepository.java | 22 ++++- .../java/org/pf4j/DefaultPluginClasspath.java | 9 +- .../java/org/pf4j/DefaultPluginLoader.java | 59 ++----------- .../java/org/pf4j/DefaultPluginManager.java | 23 ++--- .../org/pf4j/DefaultPluginRepository.java | 17 +--- .../org/pf4j/DevelopmentPluginClasspath.java | 8 +- .../org/pf4j/DevelopmentPluginLoader.java | 29 ++++++ .../org/pf4j/DevelopmentPluginRepository.java | 55 ++++++++++++ .../main/java/org/pf4j/JarPluginManager.java | 8 +- .../main/java/org/pf4j/PluginClasspath.java | 17 ++-- .../src/main/java/org/pf4j/PluginManager.java | 9 +- .../main/java/org/pf4j/ZipPluginManager.java | 8 +- .../CompoundPluginDescriptorFinderTest.java | 7 +- .../org/pf4j/DefaultPluginRepositoryTest.java | 30 +------ .../pf4j/DevelopmentPluginRepositoryTest.java | 61 +++++++++++++ 18 files changed, 334 insertions(+), 136 deletions(-) create mode 100644 pf4j/src/main/java/org/pf4j/BasePluginLoader.java create mode 100644 pf4j/src/main/java/org/pf4j/DevelopmentPluginLoader.java create mode 100644 pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java create mode 100644 pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 9e86909..fc0a22e 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -45,6 +45,8 @@ public abstract class AbstractPluginManager implements PluginManager { private static final Logger log = LoggerFactory.getLogger(AbstractPluginManager.class); public static final String PLUGINS_DIR_PROPERTY_NAME = "pf4j.pluginsDir"; + public static final String MODE_PROPERTY_NAME = "pf4j.mode"; + public static final String DEFAULT_PLUGINS_DIR = "plugins"; public static final String DEVELOPMENT_PLUGINS_DIR = "../plugins"; @@ -588,7 +590,7 @@ public abstract class AbstractPluginManager implements PluginManager { public RuntimeMode getRuntimeMode() { if (runtimeMode == null) { // retrieves the runtime mode from system - String modeAsString = System.getProperty("pf4j.mode", RuntimeMode.DEPLOYMENT.toString()); + String modeAsString = System.getProperty(MODE_PROPERTY_NAME, RuntimeMode.DEPLOYMENT.toString()); runtimeMode = RuntimeMode.byName(modeAsString); } diff --git a/pf4j/src/main/java/org/pf4j/BasePluginLoader.java b/pf4j/src/main/java/org/pf4j/BasePluginLoader.java new file mode 100644 index 0000000..e4f22f3 --- /dev/null +++ b/pf4j/src/main/java/org/pf4j/BasePluginLoader.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +import org.pf4j.util.FileUtils; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +/** + * Load all information needed by a plugin. + * This means add to the plugin's {@link ClassLoader} all the jar files and + * all the class files specified in the {@link PluginClasspath}. + * + * @author Decebal Suiu + */ +public class BasePluginLoader implements PluginLoader { + + protected PluginManager pluginManager; + protected PluginClasspath pluginClasspath; + + public BasePluginLoader(PluginManager pluginManager, PluginClasspath pluginClasspath) { + this.pluginManager = pluginManager; + this.pluginClasspath = pluginClasspath; + } + + @Override + public boolean isApplicable(Path pluginPath) { + return Files.exists(pluginPath); + } + + @Override + public ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor) { + PluginClassLoader pluginClassLoader = createPluginClassLoader(pluginPath, pluginDescriptor); + + loadClasses(pluginPath, pluginClassLoader); + loadJars(pluginPath, pluginClassLoader); + + return pluginClassLoader; + } + + protected PluginClassLoader createPluginClassLoader(Path pluginPath, PluginDescriptor pluginDescriptor) { + return new PluginClassLoader(pluginManager, pluginDescriptor, getClass().getClassLoader()); + } + + /** + * Add all {@code *.class} files from {@link PluginClasspath#getClassesDirectories()} + * to the plugin's {@link ClassLoader}. + */ + protected void loadClasses(Path pluginPath, PluginClassLoader pluginClassLoader) { + for (String directory : pluginClasspath.getClassesDirectories()) { + File file = pluginPath.resolve(directory).toFile(); + if (file.exists() && file.isDirectory()) { + pluginClassLoader.addFile(file); + } + } + } + + /** + * Add all {@code *.jar} files from {@link PluginClasspath#getJarsDirectories()} + * to the plugin's {@link ClassLoader}. + */ + protected void loadJars(Path pluginPath, PluginClassLoader pluginClassLoader) { + for (String jarsDirectory : pluginClasspath.getJarsDirectories()) { + Path file = pluginPath.resolve(jarsDirectory); + List jars = FileUtils.getJars(file); + for (File jar : jars) { + pluginClassLoader.addFile(jar); + } + } + } + +} diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java b/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java index fe10d68..c20e4bb 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java @@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.function.BooleanSupplier; /** * @author Decebal Suiu @@ -41,6 +42,21 @@ public class CompoundPluginLoader implements PluginLoader { return this; } + /** + * Add a {@link PluginLoader} only if the {@code condition} is satisfied. + * + * @param loader + * @param condition + * @return + */ + public CompoundPluginLoader add(PluginLoader loader, BooleanSupplier condition) { + if (condition.getAsBoolean()) { + return add(loader); + } + + return this; + } + public int size() { return loaders.size(); } diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java index c738191..aef714c 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java @@ -17,7 +17,10 @@ package org.pf4j; import java.nio.file.Path; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; +import java.util.function.BooleanSupplier; /** * @author Decebal Suiu @@ -37,14 +40,29 @@ public class CompoundPluginRepository implements PluginRepository { return this; } + /** + * Add a {@link PluginRepository} only if the {@code condition} is satisfied. + * + * @param repository + * @param condition + * @return + */ + public CompoundPluginRepository add(PluginRepository repository, BooleanSupplier condition) { + if (condition.getAsBoolean()) { + return add(repository); + } + + return this; + } + @Override public List getPluginsPaths() { - List paths = new ArrayList<>(); + Set paths = new LinkedHashSet<>(); for (PluginRepository repository : repositories) { paths.addAll(repository.getPluginsPaths()); } - return paths; + return new ArrayList<>(paths); } @Override diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java b/pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java index a78bfd3..2d64e1e 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java @@ -16,17 +16,20 @@ package org.pf4j; /** - * The default values are {@code classes} and {@code lib}. + * The default values are {@link #CLASSES_DIR} and {@code #LIB_DIR}. * * @author Decebal Suiu */ public class DefaultPluginClasspath extends PluginClasspath { + public static final String CLASSES_DIR = "classes"; + public static final String LIB_DIR = "lib"; + public DefaultPluginClasspath() { super(); - addClassesDirectories("classes"); - addLibDirectories("lib"); + addClassesDirectories(CLASSES_DIR); + addJarsDirectories(LIB_DIR); } } diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java b/pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java index 60d63be..1ee8349 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java @@ -15,72 +15,23 @@ */ package org.pf4j; -import org.pf4j.util.FileUtils; - -import java.io.File; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; /** - * Load all information needed by a plugin. - * This means add to classpath all jar files from {@code lib} directory - * and all class files from {@code classes}. + * Load all information needed by a plugin from {@link DefaultPluginClasspath}. * * @author Decebal Suiu */ -public class DefaultPluginLoader implements PluginLoader { - - protected PluginManager pluginManager; - protected PluginClasspath pluginClasspath; +public class DefaultPluginLoader extends BasePluginLoader { - public DefaultPluginLoader(PluginManager pluginManager, PluginClasspath pluginClasspath) { - this.pluginManager = pluginManager; - this.pluginClasspath = pluginClasspath; + public DefaultPluginLoader(PluginManager pluginManager) { + super(pluginManager, new DefaultPluginClasspath()); } @Override public boolean isApplicable(Path pluginPath) { - return Files.exists(pluginPath) && Files.isDirectory(pluginPath); - } - - @Override - public ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor) { - PluginClassLoader pluginClassLoader = createPluginClassLoader(pluginPath, pluginDescriptor); - - loadClasses(pluginPath, pluginClassLoader); - loadJars(pluginPath, pluginClassLoader); - - return pluginClassLoader; - } - - protected PluginClassLoader createPluginClassLoader(Path pluginPath, PluginDescriptor pluginDescriptor) { - return new PluginClassLoader(pluginManager, pluginDescriptor, getClass().getClassLoader()); - } - - /** - * Add all {@code *.class} files from {@code classes} directories to plugin class loader. - */ - protected void loadClasses(Path pluginPath, PluginClassLoader pluginClassLoader) { - for (String directory : pluginClasspath.getClassesDirectories()) { - File file = pluginPath.resolve(directory).toFile(); - if (file.exists() && file.isDirectory()) { - pluginClassLoader.addFile(file); - } - } - } - - /** - * Add all {@code *.jar} files from {@code lib} directories to plugin class loader. - */ - protected void loadJars(Path pluginPath, PluginClassLoader pluginClassLoader) { - for (String libDirectory : pluginClasspath.getLibDirectories()) { - Path file = pluginPath.resolve(libDirectory); - List jars = FileUtils.getJars(file); - for (File jar : jars) { - pluginClassLoader.addFile(jar); - } - } + return super.isApplicable(pluginPath) && Files.isDirectory(pluginPath); } } diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java index db5678b..cafdb4e 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java @@ -37,8 +37,6 @@ public class DefaultPluginManager extends AbstractPluginManager { public static final String PLUGINS_DIR_CONFIG_PROPERTY_NAME = "pf4j.pluginsConfigDir"; - protected PluginClasspath pluginClasspath; - public DefaultPluginManager() { super(); } @@ -76,21 +74,24 @@ public class DefaultPluginManager extends AbstractPluginManager { protected PluginStatusProvider createPluginStatusProvider() { String configDir = System.getProperty(PLUGINS_DIR_CONFIG_PROPERTY_NAME); Path configPath = configDir != null ? Paths.get(configDir) : getPluginsRoot(); + return new DefaultPluginStatusProvider(configPath); } @Override protected PluginRepository createPluginRepository() { return new CompoundPluginRepository() - .add(new JarPluginRepository(getPluginsRoot())) - .add(new DefaultPluginRepository(getPluginsRoot(), isDevelopment())); + .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment) + .add(new JarPluginRepository(getPluginsRoot()), this::isNotDevelopment) + .add(new DefaultPluginRepository(getPluginsRoot()), this::isNotDevelopment); } @Override protected PluginLoader createPluginLoader() { return new CompoundPluginLoader() - .add(new JarPluginLoader(this)) - .add(new DefaultPluginLoader(this, pluginClasspath)); + .add(new DevelopmentPluginLoader(this), this::isDevelopment) + .add(new JarPluginLoader(this), this::isNotDevelopment) + .add(new DefaultPluginLoader(this), this::isNotDevelopment); } @Override @@ -98,18 +99,8 @@ public class DefaultPluginManager extends AbstractPluginManager { return new DefaultVersionManager(); } - /** - * By default if {@link #isDevelopment()} returns {@code true} than a {@link DevelopmentPluginClasspath} - * is returned, else this method returns {@link DefaultPluginClasspath}. - */ - protected PluginClasspath createPluginClasspath() { - return isDevelopment() ? new DevelopmentPluginClasspath() : new DefaultPluginClasspath(); - } - @Override protected void initialize() { - pluginClasspath = createPluginClasspath(); - super.initialize(); if (isDevelopment()) { diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java index 1c031b6..f50a231 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java @@ -39,11 +39,11 @@ public class DefaultPluginRepository extends BasePluginRepository { private static final Logger log = LoggerFactory.getLogger(DefaultPluginRepository.class); - public DefaultPluginRepository(Path pluginsRoot, boolean development) { + public DefaultPluginRepository(Path pluginsRoot) { super(pluginsRoot); AndFileFilter pluginsFilter = new AndFileFilter(new DirectoryFileFilter()); - pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter(development))); + pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter())); setFilter(pluginsFilter); } @@ -59,17 +59,8 @@ public class DefaultPluginRepository extends BasePluginRepository { return super.deletePluginPath(pluginPath); } - protected FileFilter createHiddenPluginFilter(boolean development) { - OrFileFilter hiddenPluginFilter = new OrFileFilter(new HiddenFilter()); - - if (development) { - // skip default build output folders since these will cause errors in the logs - hiddenPluginFilter - .addFileFilter(new NameFileFilter("target")) // MAVEN - .addFileFilter(new NameFileFilter("build")); // GRADLE - } - - return hiddenPluginFilter; + protected FileFilter createHiddenPluginFilter() { + return new OrFileFilter(new HiddenFilter()); } private void extractZipFiles() { diff --git a/pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java b/pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java index 15da659..4d7727d 100644 --- a/pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java +++ b/pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java @@ -27,7 +27,7 @@ public class DevelopmentPluginClasspath extends PluginClasspath { * The development plugin classpath for Maven. * The classes directory is {@code target/classes} and the lib directory is {@code target/lib}. */ - public static final PluginClasspath MAVEN = new PluginClasspath().addClassesDirectories("target/classes").addLibDirectories("target/lib"); + public static final PluginClasspath MAVEN = new PluginClasspath().addClassesDirectories("target/classes").addJarsDirectories("target/lib"); /** * The development plugin classpath for Gradle. @@ -46,9 +46,9 @@ public class DevelopmentPluginClasspath extends PluginClasspath { addClassesDirectories(GRADLE.getClassesDirectories()); addClassesDirectories(KOTLIN.getClassesDirectories()); - addLibDirectories(MAVEN.getLibDirectories()); - addLibDirectories(GRADLE.getLibDirectories()); - addLibDirectories(KOTLIN.getLibDirectories()); + addJarsDirectories(MAVEN.getJarsDirectories()); + addJarsDirectories(GRADLE.getJarsDirectories()); + addJarsDirectories(KOTLIN.getJarsDirectories()); } } diff --git a/pf4j/src/main/java/org/pf4j/DevelopmentPluginLoader.java b/pf4j/src/main/java/org/pf4j/DevelopmentPluginLoader.java new file mode 100644 index 0000000..58c9473 --- /dev/null +++ b/pf4j/src/main/java/org/pf4j/DevelopmentPluginLoader.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +/** + * Load all information needed by a plugin from {@link DevelopmentPluginClasspath}. + * + * @author Decebal Suiu + */ +public class DevelopmentPluginLoader extends BasePluginLoader { + + public DevelopmentPluginLoader(PluginManager pluginManager) { + super(pluginManager, new DevelopmentPluginClasspath()); + } + +} diff --git a/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java b/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java new file mode 100644 index 0000000..e8f2c69 --- /dev/null +++ b/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +import org.pf4j.util.AndFileFilter; +import org.pf4j.util.DirectoryFileFilter; +import org.pf4j.util.HiddenFilter; +import org.pf4j.util.NameFileFilter; +import org.pf4j.util.NotFileFilter; +import org.pf4j.util.OrFileFilter; + +import java.io.FileFilter; +import java.nio.file.Path; + +/** + * @author Decebal Suiu + */ +public class DevelopmentPluginRepository extends BasePluginRepository { + + public static final String MAVEN_BUILD_DIR = "target"; + public static final String GRADLE_BUILD_DIR = "build"; + + public DevelopmentPluginRepository(Path pluginsRoot) { + super(pluginsRoot); + + AndFileFilter pluginsFilter = new AndFileFilter(new DirectoryFileFilter()); + pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter())); + setFilter(pluginsFilter); + } + + protected FileFilter createHiddenPluginFilter() { + OrFileFilter hiddenPluginFilter = new OrFileFilter(new HiddenFilter()); + + // skip default build output folders since these will cause errors in the logs + hiddenPluginFilter + .addFileFilter(new NameFileFilter(MAVEN_BUILD_DIR)) + .addFileFilter(new NameFileFilter(GRADLE_BUILD_DIR)); + + return hiddenPluginFilter; + } + +} diff --git a/pf4j/src/main/java/org/pf4j/JarPluginManager.java b/pf4j/src/main/java/org/pf4j/JarPluginManager.java index 68c50db..5921aa5 100644 --- a/pf4j/src/main/java/org/pf4j/JarPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/JarPluginManager.java @@ -31,12 +31,16 @@ public class JarPluginManager extends DefaultPluginManager { @Override protected PluginLoader createPluginLoader() { - return new JarPluginLoader(this); + return new CompoundPluginLoader() + .add(new DevelopmentPluginLoader(this), this::isDevelopment) + .add(new JarPluginLoader(this), this::isNotDevelopment); } @Override protected PluginRepository createPluginRepository() { - return new JarPluginRepository(getPluginsRoot()); + return new CompoundPluginRepository() + .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment) + .add(new JarPluginRepository(getPluginsRoot()), this::isNotDevelopment); } } diff --git a/pf4j/src/main/java/org/pf4j/PluginClasspath.java b/pf4j/src/main/java/org/pf4j/PluginClasspath.java index 57ff9bf..757740c 100644 --- a/pf4j/src/main/java/org/pf4j/PluginClasspath.java +++ b/pf4j/src/main/java/org/pf4j/PluginClasspath.java @@ -22,14 +22,15 @@ import java.util.Set; /** * The classpath of the plugin. - * It contains {@code classes} directories and {@code lib} directories (directories that contains jars). + * It contains {@code classes} directories (directories that contain classes files) + * and {@code jars} directories (directories that contain jars files). * * @author Decebal Suiu */ public class PluginClasspath { private Set classesDirectories = new HashSet<>(); - private Set libDirectories = new HashSet<>(); + private Set jarsDirectories = new HashSet<>(); public Set getClassesDirectories() { return classesDirectories; @@ -45,16 +46,16 @@ public class PluginClasspath { return this; } - public Set getLibDirectories() { - return libDirectories; + public Set getJarsDirectories() { + return jarsDirectories; } - public PluginClasspath addLibDirectories(String... libDirectories) { - return addLibDirectories(Arrays.asList(libDirectories)); + public PluginClasspath addJarsDirectories(String... jarsDirectories) { + return addJarsDirectories(Arrays.asList(jarsDirectories)); } - public PluginClasspath addLibDirectories(Collection libDirectories) { - this.libDirectories.addAll(libDirectories); + public PluginClasspath addJarsDirectories(Collection jarsDirectories) { + this.jarsDirectories.addAll(jarsDirectories); return this; } diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java index badba28..0fb9b1f 100644 --- a/pf4j/src/main/java/org/pf4j/PluginManager.java +++ b/pf4j/src/main/java/org/pf4j/PluginManager.java @@ -155,12 +155,19 @@ public interface PluginManager { RuntimeMode getRuntimeMode(); /** - * Returns {@code true} id the runtime mode is {@code RuntimeMode.DEVELOPMENT}. + * Returns {@code true} if the runtime mode is {@code RuntimeMode.DEVELOPMENT}. */ default boolean isDevelopment() { return RuntimeMode.DEVELOPMENT.equals(getRuntimeMode()); } + /** + * Returns {@code true} if the runtime mode is not {@code RuntimeMode.DEVELOPMENT}. + */ + default boolean isNotDevelopment() { + return !isDevelopment(); + } + /** * Retrieves the {@link PluginWrapper} that loaded the given class 'clazz'. */ diff --git a/pf4j/src/main/java/org/pf4j/ZipPluginManager.java b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java index ab17fc9..a32d156 100644 --- a/pf4j/src/main/java/org/pf4j/ZipPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java @@ -34,12 +34,16 @@ public class ZipPluginManager extends DefaultPluginManager { @Override protected PluginLoader createPluginLoader() { - return new DefaultPluginLoader(this, pluginClasspath); + return new CompoundPluginLoader() + .add(new DevelopmentPluginLoader(this), this::isDevelopment) + .add(new DefaultPluginLoader(this), this::isNotDevelopment); } @Override protected PluginRepository createPluginRepository() { - return new DefaultPluginRepository(getPluginsRoot(), isDevelopment()); + return new CompoundPluginRepository() + .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment) + .add(new DefaultPluginRepository(getPluginsRoot()), this::isNotDevelopment); } } diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java index 7e6043b..d74bea3 100644 --- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java @@ -92,13 +92,14 @@ public class CompoundPluginDescriptorFinderTest { @Test public void testSpaceCharacterInFileName() throws Exception { - PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder(); + PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder() + .add(new ManifestPluginDescriptorFinder()); - PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my plugin-1.2.3.jar"), "myPlugin") + PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my plugin-1.2.3.jar"), "myPlugin") .pluginVersion("1.2.3") .build(); - PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginZip.path()); + PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginJar.path()); assertNotNull(pluginDescriptor); } diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java index 3805c42..2237dfe 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -46,9 +46,6 @@ public class DefaultPluginRepositoryTest { Files.createFile(pluginsPath.resolve("plugin-1.zip")); Files.createDirectory(pluginsPath.resolve("plugin-2")); Files.createDirectory(pluginsPath.resolve("plugin-3")); - // standard maven/gradle bin folder - these should be skipped in development mode because the cause errors - Files.createDirectory(pluginsPath.resolve("target")); - Files.createDirectory(pluginsPath.resolve("build")); } /** @@ -56,29 +53,14 @@ public class DefaultPluginRepositoryTest { */ @Test public void testGetPluginArchives() { - PluginRepository repository = new DefaultPluginRepository(pluginsPath, false); + PluginRepository repository = new DefaultPluginRepository(pluginsPath); List pluginsPaths = repository.getPluginsPaths(); - assertEquals(5, pluginsPaths.size()); + assertEquals(3, pluginsPaths.size()); assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-1")); assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-2")); assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-3")); - // when not in development mode we will honor these folders - assertPathExists(pluginsPaths, pluginsPath.resolve("target")); - assertPathExists(pluginsPaths, pluginsPath.resolve("build")); - } - - @Test - public void testGetPluginArchivesInDevelopmentMode() { - PluginRepository repository = new DefaultPluginRepository(pluginsPath, true); - - List pluginsPaths = repository.getPluginsPaths(); - - // target and build should be ignored - assertEquals(3, pluginsPaths.size()); - assertPathDoesNotExists(pluginsPaths, pluginsPath.resolve("target")); - assertPathDoesNotExists(pluginsPaths, pluginsPath.resolve("build")); } /** @@ -86,15 +68,13 @@ public class DefaultPluginRepositoryTest { */ @Test public void testDeletePluginPath() throws PluginException { - PluginRepository repository = new DefaultPluginRepository(pluginsPath, false); + PluginRepository repository = new DefaultPluginRepository(pluginsPath); assertTrue(Files.exists(pluginsPath.resolve("plugin-1.zip"))); assertTrue(repository.deletePluginPath(pluginsPath.resolve("plugin-1"))); assertFalse(Files.exists(pluginsPath.resolve("plugin-1.zip"))); assertTrue(repository.deletePluginPath(pluginsPath.resolve("plugin-3"))); assertFalse(repository.deletePluginPath(pluginsPath.resolve("plugin-4"))); - assertTrue(repository.deletePluginPath(pluginsPath.resolve("target"))); - assertTrue(repository.deletePluginPath(pluginsPath.resolve("build"))); List pluginsPaths = repository.getPluginsPaths(); @@ -106,8 +86,4 @@ public class DefaultPluginRepositoryTest { assertTrue(paths.contains(path), "The directory must contain the file " + path); } - private void assertPathDoesNotExists(List paths, Path path) { - assertFalse(paths.contains(path), "The directory must not contain the file " + path); - } - } diff --git a/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java new file mode 100644 index 0000000..9e4c8da --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +/** + * @author Decebal Suiu + */ +public class DevelopmentPluginRepositoryTest { + + @TempDir + Path pluginsPath; + + @BeforeEach + public void setUp() throws IOException { + // standard maven/gradle bin folder - these should be skipped in development mode because the cause errors + Files.createDirectory(pluginsPath.resolve(DevelopmentPluginRepository.MAVEN_BUILD_DIR)); + Files.createDirectory(pluginsPath.resolve(DevelopmentPluginRepository.GRADLE_BUILD_DIR)); + } + + @Test + public void testGetPluginArchivesInDevelopmentMode() { + PluginRepository repository = new DevelopmentPluginRepository(pluginsPath); + + List pluginsPaths = repository.getPluginsPaths(); + + // target and build should be ignored + assertEquals(0, pluginsPaths.size()); + assertPathDoesNotExists(pluginsPaths, pluginsPath.resolve(DevelopmentPluginRepository.MAVEN_BUILD_DIR)); + assertPathDoesNotExists(pluginsPaths, pluginsPath.resolve(DevelopmentPluginRepository.GRADLE_BUILD_DIR)); + } + + private void assertPathDoesNotExists(List paths, Path path) { + assertFalse(paths.contains(path), "The directory must not contain the file " + path); + } + +} From b6b4e3ddc42fcbabcaa784c53f383e098b7c87c7 Mon Sep 17 00:00:00 2001 From: decebals Date: Fri, 3 May 2019 01:18:55 +0300 Subject: [PATCH 41/54] Remove unneeded method --- pf4j/src/main/java/org/pf4j/AbstractPluginManager.java | 8 ++++---- pf4j/src/main/java/org/pf4j/PluginWrapper.java | 5 +---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index fc0a22e..5a7546e 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -15,6 +15,10 @@ */ package org.pf4j; +import org.pf4j.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.Closeable; import java.io.IOException; import java.nio.file.Files; @@ -27,9 +31,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import org.pf4j.util.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * This class implements the boilerplate plugin code that any {@link PluginManager} @@ -820,7 +821,6 @@ public abstract class AbstractPluginManager implements PluginManager { log.debug("Creating wrapper for plugin '{}'", pluginPath); PluginWrapper pluginWrapper = new PluginWrapper(this, pluginDescriptor, pluginPath, pluginClassLoader); pluginWrapper.setPluginFactory(getPluginFactory()); - pluginWrapper.setRuntimeMode(getRuntimeMode()); // test for disabled plugin if (isPluginDisabled(pluginDescriptor.getPluginId())) { diff --git a/pf4j/src/main/java/org/pf4j/PluginWrapper.java b/pf4j/src/main/java/org/pf4j/PluginWrapper.java index 209afb9..a9aa147 100644 --- a/pf4j/src/main/java/org/pf4j/PluginWrapper.java +++ b/pf4j/src/main/java/org/pf4j/PluginWrapper.java @@ -41,6 +41,7 @@ public class PluginWrapper { this.pluginClassLoader = pluginClassLoader; pluginState = PluginState.CREATED; + runtimeMode = pluginManager.getRuntimeMode(); } /** @@ -134,10 +135,6 @@ public class PluginWrapper { this.pluginState = pluginState; } - void setRuntimeMode(RuntimeMode runtimeMode) { - this.runtimeMode = runtimeMode; - } - void setPluginFactory(PluginFactory pluginFactory) { this.pluginFactory = pluginFactory; } From 5a8e5eaa3edcf50e29b24ddeb027ba02ff86bf8b Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 3 May 2019 12:01:46 +0300 Subject: [PATCH 42/54] Remove empty line --- pf4j/src/main/java/org/pf4j/AbstractPluginManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 5a7546e..b6b4741 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -532,7 +532,6 @@ public abstract class AbstractPluginManager implements PluginManager { return extensionClasses; } - @Override public List> getExtensionClasses(Class type) { return getExtensionClasses(extensionFinder.find(type)); From 3cd26fc19d3511477870ad797a9de52bf99fef0a Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Mon, 13 May 2019 20:37:56 +0300 Subject: [PATCH 43/54] Revert commit 40846fa (Rename PluginRepository.getPluginPaths to getPluginsPaths) --- .../java/org/pf4j/AbstractPluginManager.java | 10 +++++----- .../java/org/pf4j/BasePluginRepository.java | 4 ++-- .../org/pf4j/CompoundPluginRepository.java | 4 ++-- .../java/org/pf4j/DefaultPluginRepository.java | 4 ++-- .../main/java/org/pf4j/PluginRepository.java | 4 ++-- .../org/pf4j/DefaultPluginRepositoryTest.java | 18 +++++++++--------- .../pf4j/DevelopmentPluginRepositoryTest.java | 8 ++++---- .../java/org/pf4j/JarPluginRepositoryTest.java | 8 ++++---- 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index b6b4741..6039b51 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -207,19 +207,19 @@ public abstract class AbstractPluginManager implements PluginManager { return; } - // get all plugins paths from repository - List pluginsPaths = pluginRepository.getPluginsPaths(); + // get all plugin paths from repository + List pluginPaths = pluginRepository.getPluginPaths(); // check for no plugins - if (pluginsPaths.isEmpty()) { + if (pluginPaths.isEmpty()) { log.info("No plugins"); return; } - log.debug("Found {} possible plugins: {}", pluginsPaths.size(), pluginsPaths); + log.debug("Found {} possible plugins: {}", pluginPaths.size(), pluginPaths); // load plugins from plugin paths - for (Path pluginPath : pluginsPaths) { + for (Path pluginPath : pluginPaths) { try { loadPluginFromPath(pluginPath); } catch (PluginException e) { diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java index b083994..64c996b 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java @@ -57,7 +57,7 @@ public class BasePluginRepository implements PluginRepository { /** * Set a {@link File} {@link Comparator} used to sort the listed files from {@code pluginsRoot}. - * This comparator is used in {@link #getPluginsPaths()} method. + * This comparator is used in {@link #getPluginPaths()} method. * By default is used a file comparator that returns the last modified files first. * If you don't want a file comparator, then call this method with {@code null}. */ @@ -66,7 +66,7 @@ public class BasePluginRepository implements PluginRepository { } @Override - public List getPluginsPaths() { + public List getPluginPaths() { File[] files = pluginsRoot.toFile().listFiles(filter); if ((files == null) || files.length == 0) { diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java index aef714c..600f00c 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java @@ -56,10 +56,10 @@ public class CompoundPluginRepository implements PluginRepository { } @Override - public List getPluginsPaths() { + public List getPluginPaths() { Set paths = new LinkedHashSet<>(); for (PluginRepository repository : repositories) { - paths.addAll(repository.getPluginsPaths()); + paths.addAll(repository.getPluginPaths()); } return new ArrayList<>(paths); diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java index f50a231..70a4bb9 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java @@ -48,9 +48,9 @@ public class DefaultPluginRepository extends BasePluginRepository { } @Override - public List getPluginsPaths() { + public List getPluginPaths() { extractZipFiles(); - return super.getPluginsPaths(); + return super.getPluginPaths(); } @Override diff --git a/pf4j/src/main/java/org/pf4j/PluginRepository.java b/pf4j/src/main/java/org/pf4j/PluginRepository.java index 941d68f..9b4298a 100644 --- a/pf4j/src/main/java/org/pf4j/PluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/PluginRepository.java @@ -27,11 +27,11 @@ import java.util.List; public interface PluginRepository { /** - * List all plugins paths. + * List all plugin paths. * * @return a list with paths */ - List getPluginsPaths(); + List getPluginPaths(); /** * Removes a plugin from the repository. diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java index 2237dfe..3474aa6 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -49,18 +49,18 @@ public class DefaultPluginRepositoryTest { } /** - * Test of {@link DefaultPluginRepository#getPluginsPaths()} method. + * Test of {@link DefaultPluginRepository#getPluginPaths()} method. */ @Test public void testGetPluginArchives() { PluginRepository repository = new DefaultPluginRepository(pluginsPath); - List pluginsPaths = repository.getPluginsPaths(); + List pluginPaths = repository.getPluginPaths(); - assertEquals(3, pluginsPaths.size()); - assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-1")); - assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-2")); - assertPathExists(pluginsPaths, pluginsPath.resolve("plugin-3")); + assertEquals(3, pluginPaths.size()); + assertPathExists(pluginPaths, pluginsPath.resolve("plugin-1")); + assertPathExists(pluginPaths, pluginsPath.resolve("plugin-2")); + assertPathExists(pluginPaths, pluginsPath.resolve("plugin-3")); } /** @@ -76,10 +76,10 @@ public class DefaultPluginRepositoryTest { assertTrue(repository.deletePluginPath(pluginsPath.resolve("plugin-3"))); assertFalse(repository.deletePluginPath(pluginsPath.resolve("plugin-4"))); - List pluginsPaths = repository.getPluginsPaths(); + List pluginPaths = repository.getPluginPaths(); - assertEquals(1, pluginsPaths.size()); - assertEquals(pluginsPath.relativize(pluginsPaths.get(0)).toString(), "plugin-2"); + assertEquals(1, pluginPaths.size()); + assertEquals(pluginsPath.relativize(pluginPaths.get(0)).toString(), "plugin-2"); } private void assertPathExists(List paths, Path path) { diff --git a/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java index 9e4c8da..20d9129 100644 --- a/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java @@ -46,12 +46,12 @@ public class DevelopmentPluginRepositoryTest { public void testGetPluginArchivesInDevelopmentMode() { PluginRepository repository = new DevelopmentPluginRepository(pluginsPath); - List pluginsPaths = repository.getPluginsPaths(); + List pluginPaths = repository.getPluginPaths(); // target and build should be ignored - assertEquals(0, pluginsPaths.size()); - assertPathDoesNotExists(pluginsPaths, pluginsPath.resolve(DevelopmentPluginRepository.MAVEN_BUILD_DIR)); - assertPathDoesNotExists(pluginsPaths, pluginsPath.resolve(DevelopmentPluginRepository.GRADLE_BUILD_DIR)); + assertEquals(0, pluginPaths.size()); + assertPathDoesNotExists(pluginPaths, pluginsPath.resolve(DevelopmentPluginRepository.MAVEN_BUILD_DIR)); + assertPathDoesNotExists(pluginPaths, pluginsPath.resolve(DevelopmentPluginRepository.GRADLE_BUILD_DIR)); } private void assertPathDoesNotExists(List paths, Path path) { diff --git a/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java index 02d2bcc..4501223 100644 --- a/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java @@ -46,13 +46,13 @@ public class JarPluginRepositoryTest { assertFalse(repository.deletePluginPath(plugin1Path)); - List pluginsPaths = repository.getPluginsPaths(); - assertEquals(1, pluginsPaths.size()); + List pluginPaths = repository.getPluginPaths(); + assertEquals(1, pluginPaths.size()); assertTrue(repository.deletePluginPath(plugin1JarPath)); - pluginsPaths = repository.getPluginsPaths(); - assertEquals(0, pluginsPaths.size()); + pluginPaths = repository.getPluginPaths(); + assertEquals(0, pluginPaths.size()); } } From 2ad15a19742e19a4d49449e3c7ae725b48aec68d Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Thu, 16 May 2019 21:30:27 +0300 Subject: [PATCH 44/54] Resolve #306 --- maven-archetypes/quickstart/pom.xml | 68 ++++++++++++ .../META-INF/maven/archetype-metadata.xml | 86 +++++++++++++++ .../resources/archetype-resources/app/pom.xml | 86 +++++++++++++++ .../app/src/main/assembly/assembly.xml | 30 ++++++ .../app/src/main/java/Boot.java | 102 ++++++++++++++++++ .../app/src/main/java/Greeting.java | 9 ++ .../app/src/main/java/WhazzupGreeting.java | 13 +++ .../app/src/main/resources/log4j.properties | 20 ++++ .../archetype-resources/plugins/disabled.txt | 6 ++ .../archetype-resources/plugins/enabled.txt | 6 ++ .../plugins/hello/plugin.properties | 5 + .../archetype-resources/plugins/hello/pom.xml | 24 +++++ .../src/main/java/hello/HelloPlugin.java | 37 +++++++ .../archetype-resources/plugins/pom.xml | 86 +++++++++++++++ .../plugins/welcome/plugin.properties | 5 + .../plugins/welcome/pom.xml | 32 ++++++ .../src/main/java/welcome/WelcomePlugin.java | 41 +++++++ .../resources/archetype-resources/pom.xml | 48 +++++++++ .../main/resources/archetype-resources/run.sh | 23 ++++ pom.xml | 1 + 20 files changed, 728 insertions(+) create mode 100755 maven-archetypes/quickstart/pom.xml create mode 100644 maven-archetypes/quickstart/src/main/resources/META-INF/maven/archetype-metadata.xml create mode 100644 maven-archetypes/quickstart/src/main/resources/archetype-resources/app/pom.xml create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/assembly/assembly.xml create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Boot.java create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Greeting.java create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/WhazzupGreeting.java create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/resources/log4j.properties create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/disabled.txt create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/enabled.txt create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/plugin.properties create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/pom.xml create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/src/main/java/hello/HelloPlugin.java create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/pom.xml create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/plugin.properties create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/pom.xml create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/src/main/java/welcome/WelcomePlugin.java create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml create mode 100755 maven-archetypes/quickstart/src/main/resources/archetype-resources/run.sh diff --git a/maven-archetypes/quickstart/pom.xml b/maven-archetypes/quickstart/pom.xml new file mode 100755 index 0000000..783bed1 --- /dev/null +++ b/maven-archetypes/quickstart/pom.xml @@ -0,0 +1,68 @@ + + + + + org.pf4j + pf4j-parent + 3.0.0-SNAPSHOT + ../../pom.xml + + + 4.0.0 + pf4j-quickstart + maven-archetype + Quickstart Archetype + + + + + + true + src/main/resources + + archetype-resources/**/pom.xml + + + + + false + src/main/resources + + archetype-resources/**/pom.xml + + + + + + + org.apache.maven.archetype + archetype-packaging + 2.3 + + + + + + + org.apache.maven.plugins + maven-archetype-plugin + 2.3 + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + + {{*}} + + false + + + + + + + diff --git a/maven-archetypes/quickstart/src/main/resources/META-INF/maven/archetype-metadata.xml b/maven-archetypes/quickstart/src/main/resources/META-INF/maven/archetype-metadata.xml new file mode 100644 index 0000000..a6f40bd --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/META-INF/maven/archetype-metadata.xml @@ -0,0 +1,86 @@ + + + + + + + + run.sh + + + + + + + + + src/main/java + + **/*.java + + + + src/main/resources + + **/*.properties + + + + src/main/assembly + + **/*.xml + + + + + + + + + + + enabled.txt + disabled.txt + + + + + + + + + src/main/java + + **/*.java + + + + + + plugin.properties + + + + + + + + + src/main/java + + **/*.java + + + + + + plugin.properties + + + + + + + + + diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/pom.xml new file mode 100644 index 0000000..986c0a3 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/pom.xml @@ -0,0 +1,86 @@ + + + + + ${groupId} + ${rootArtifactId} + ${version} + + + 4.0.0 + ${artifactId} + ${version} + jar + App + + + ${package}.Boot + + + + + + maven-assembly-plugin + 2.3 + + + src/main/assembly/assembly.xml + + false + + + + make-assembly + package + + attached + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.1 + + + + true + lib/ + ${main.class} + + + + + + + + + + org.pf4j + pf4j + ${pf4j.version} + + + + + log4j + log4j + 1.2.16 + + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + + + + commons-lang + commons-lang + 2.4 + + + + diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/assembly/assembly.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/assembly/assembly.xml new file mode 100755 index 0000000..b88a245 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/assembly/assembly.xml @@ -0,0 +1,30 @@ + + app + + dir + zip + + false + + + false + lib + + *:jar:* + + + + + + ${project.build.directory} + + + *.jar + + + *-javadoc.jar + *-sources.jar + + + + diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Boot.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Boot.java new file mode 100755 index 0000000..2853b08 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Boot.java @@ -0,0 +1,102 @@ +package ${package}; + +import org.apache.commons.lang.StringUtils; +import org.pf4j.DefaultPluginManager; +import org.pf4j.ExtensionFinder; +import org.pf4j.PluginManager; +import org.pf4j.PluginWrapper; + +import java.util.List; +import java.util.Set; + +/** + * A boot class that start the application. + */ +public class Boot { + + public static void main(String[] args) { + // create the plugin manager + PluginManager pluginManager = new DefaultPluginManager(); + + // load the plugins + pluginManager.loadPlugins(); + + // enable a disabled plugin +// pluginManager.enablePlugin("welcome-plugin"); + + // start (active/resolved) the plugins + pluginManager.startPlugins(); + + // retrieves the extensions for Greeting extension point + List greetings = pluginManager.getExtensions(Greeting.class); + System.out.println(String.format("Found %d extensions for extension point '%s'", greetings.size(), Greeting.class.getName())); + for (Greeting greeting : greetings) { + System.out.println(">>> " + greeting.getGreeting()); + } + + // print extensions from classpath (non plugin) + System.out.println("Extensions added by classpath:"); + Set extensionClassNames = pluginManager.getExtensionClassNames(null); + for (String extension : extensionClassNames) { + System.out.println(" " + extension); + } + + System.out.println("Extension classes by classpath:"); + List> greetingsClasses = pluginManager.getExtensionClasses(Greeting.class); + for (Class greeting : greetingsClasses) { + System.out.println(" Class: " + greeting.getCanonicalName()); + } + + // print extensions ids for each started plugin + List startedPlugins = pluginManager.getStartedPlugins(); + for (PluginWrapper plugin : startedPlugins) { + String pluginId = plugin.getDescriptor().getPluginId(); + System.out.println(String.format("Extensions added by plugin '%s':", pluginId)); + extensionClassNames = pluginManager.getExtensionClassNames(pluginId); + for (String extension : extensionClassNames) { + System.out.println(" " + extension); + } + } + + // print extensions instances for Greeting extension point for each started plugin + for (PluginWrapper plugin : startedPlugins) { + String pluginId = plugin.getDescriptor().getPluginId(); + System.out.println(String.format("Extensions instances added by plugin '%s' for extension point '%s':", pluginId, Greeting.class.getName())); + List extensions = pluginManager.getExtensions(Greeting.class, pluginId); + for (Object extension : extensions) { + System.out.println(" " + extension); + } + } + + // print extensions instances from classpath (non plugin) + System.out.println("Extensions instances added by classpath:"); + List extensions = pluginManager.getExtensions((String) null); + for (Object extension : extensions) { + System.out.println(" " + extension); + } + + // print extensions instances for each started plugin + for (PluginWrapper plugin : startedPlugins) { + String pluginId = plugin.getDescriptor().getPluginId(); + System.out.println(String.format("Extensions instances added by plugin '%s':", pluginId)); + extensions = pluginManager.getExtensions(pluginId); + for (Object extension : extensions) { + System.out.println(" " + extension); + } + } + + // stop the plugins + pluginManager.stopPlugins(); + /* + Runtime.getRuntime().addShutdownHook(new Thread() { + + @Override + public void run() { + pluginManager.stopPlugins(); + } + + }); + */ + } + +} diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Greeting.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Greeting.java new file mode 100755 index 0000000..d64d5fe --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Greeting.java @@ -0,0 +1,9 @@ +package ${package}; + +import org.pf4j.ExtensionPoint; + +public interface Greeting extends ExtensionPoint { + + String getGreeting(); + +} diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/WhazzupGreeting.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/WhazzupGreeting.java new file mode 100755 index 0000000..bb747f5 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/WhazzupGreeting.java @@ -0,0 +1,13 @@ +package ${package}; + +import org.pf4j.Extension; + +@Extension +public class WhazzupGreeting implements Greeting { + + @Override + public String getGreeting() { + return "Whazzup"; + } + +} diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/resources/log4j.properties b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/resources/log4j.properties new file mode 100755 index 0000000..a05d9eb --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/resources/log4j.properties @@ -0,0 +1,20 @@ +log4j.rootLogger=DEBUG, Console + +# +# PF4J log +# +log4j.logger.org.pf4j=DEBUG, Console +# !!! Put the bellow classes on level TRACE when you are in trouble +log4j.logger.org.pf4j.PluginClassLoader=DEBUG, Console +log4j.logger.org.pf4j.AbstractExtensionFinder=DEBUG, Console +log4j.additivity.org.pf4j=false +log4j.additivity.org.pf4j.PluginClassLoader=false +log4j.additivity.org.pf4j.AbstractExtensionFinder=false + +# +# Appenders +# +log4j.appender.Console=org.apache.log4j.ConsoleAppender +log4j.appender.Console.layout=org.apache.log4j.PatternLayout +#log4j.appender.Console.layout.conversionPattern=%-5p - %-32.32c{1} - %m\n +log4j.appender.Console.layout.ConversionPattern=%d %p %c - %m%n diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/disabled.txt b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/disabled.txt new file mode 100755 index 0000000..45f1801 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/disabled.txt @@ -0,0 +1,6 @@ +######################################## +# - load all plugins except these +# - add one plugin id on each line +# - put this file in plugins folder +######################################## +#welcome-plugin diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/enabled.txt b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/enabled.txt new file mode 100755 index 0000000..3d76b2f --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/enabled.txt @@ -0,0 +1,6 @@ +######################################## +# - load only these plugins +# - add one plugin id on each line +# - put this file in plugins folder +######################################## +#welcome-plugin diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/plugin.properties b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/plugin.properties new file mode 100755 index 0000000..9ed49b1 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/plugin.properties @@ -0,0 +1,5 @@ +plugin.id=hello-plugin +plugin.class=${package}.hello.HelloPlugin +plugin.version=${version} +plugin.provider= +plugin.dependencies= diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/pom.xml new file mode 100755 index 0000000..10e8262 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/pom.xml @@ -0,0 +1,24 @@ + + + + + ${groupId} + ${rootArtifactId}-plugins + ${version} + + + 4.0.0 + hello-plugin + ${version} + jar + Hello Plugin + + + hello-plugin + ${package}.hello.HelloPlugin + ${version} + + + + + diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/src/main/java/hello/HelloPlugin.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/src/main/java/hello/HelloPlugin.java new file mode 100755 index 0000000..48604d6 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/src/main/java/hello/HelloPlugin.java @@ -0,0 +1,37 @@ +package ${package}.hello; + +import org.pf4j.Extension; +import org.pf4j.Plugin; +import org.pf4j.PluginWrapper; +import ${package}.Greeting; + +/** + * A very simple plugin. + */ +public class HelloPlugin extends Plugin { + + public HelloPlugin(PluginWrapper wrapper) { + super(wrapper); + } + + @Override + public void start() { + System.out.println("HelloPlugin.start()"); + } + + @Override + public void stop() { + System.out.println("HelloPlugin.stop()"); + } + + @Extension(ordinal=1) + public static class HelloGreeting implements Greeting { + + @Override + public String getGreeting() { + return "Hello"; + } + + } + +} diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/pom.xml new file mode 100755 index 0000000..b144ca0 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/pom.xml @@ -0,0 +1,86 @@ + + + + + ${groupId} + ${rootArtifactId} + ${version} + + + 4.0.0 + ${artifactId} + ${version} + pom + Plugins Parent + + + UTF-8 + UTF-8 + + + + + + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.0 + + + jar-with-dependencies + + ${project.artifactId}-${project.version}-all + false + false + + + true + true + + + ${plugin.id} + ${plugin.version} + ${plugin.provider} + ${plugin.class} + ${plugin.dependencies} + + + + + + make-assembly + package + + single + + + + + + + + + + org.pf4j + pf4j + ${pf4j.version} + + provided + + + + ${groupId} + ${rootArtifactId}-app + ${version} + + provided + + + + diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/plugin.properties b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/plugin.properties new file mode 100755 index 0000000..80edaab --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/plugin.properties @@ -0,0 +1,5 @@ +plugin.id=welcome-plugin +plugin.class=${package}.welcome.WelcomePlugin +plugin.version=${version} +plugin.provider= +plugin.dependencies= diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/pom.xml new file mode 100755 index 0000000..9101abb --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/pom.xml @@ -0,0 +1,32 @@ + + + + + ${groupId} + ${rootArtifactId}-plugins + ${version} + + + 4.0.0 + welcome-plugin + ${version} + jar + Welcom Plugin + + + welcome-plugin + ${package}.welcome.WelcomePlugin + ${version} + + + + + + + commons-lang + commons-lang + 2.6 + + + + diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/src/main/java/welcome/WelcomePlugin.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/src/main/java/welcome/WelcomePlugin.java new file mode 100755 index 0000000..a82d13c --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/src/main/java/welcome/WelcomePlugin.java @@ -0,0 +1,41 @@ +package ${package}.welcome; + +import org.apache.commons.lang.StringUtils; + +import org.pf4j.PluginWrapper; +import org.pf4j.RuntimeMode; +import org.pf4j.Extension; +import org.pf4j.Plugin; +import ${package}.Greeting; + +public class WelcomePlugin extends Plugin { + + public WelcomePlugin(PluginWrapper wrapper) { + super(wrapper); + } + + @Override + public void start() { + System.out.println("WelcomePlugin.start()"); + // for testing the development mode + if (RuntimeMode.DEVELOPMENT.equals(wrapper.getRuntimeMode())) { + System.out.println(StringUtils.upperCase("WelcomePlugin")); + } + } + + @Override + public void stop() { + System.out.println("WelcomePlugin.stop()"); + } + + @Extension + public static class WelcomeGreeting implements Greeting { + + @Override + public String getGreeting() { + return "Welcome"; + } + + } + +} diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml new file mode 100755 index 0000000..13ed127 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml @@ -0,0 +1,48 @@ + + + + 4.0.0 + ${groupId} + ${artifactId} + ${version} + pom + PF4J Quickstart + + + + sonatype-nexus-snapshots + https://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + UTF-8 + 8 + + {{project.version}} + 1.7.7 + + + + + + false + src/main/java + + **/*.java + + + + + src/main/resources + + + + + diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/run.sh b/maven-archetypes/quickstart/src/main/resources/archetype-resources/run.sh new file mode 100755 index 0000000..6214823 --- /dev/null +++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/run.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +# create artifacts using Maven +mvn clean package -DskipTests + +# create "dist" directory +rm -fr dist +mkdir -p dist/plugins + +# copy plugins to "dist" directory +cp plugins/*/target/*-all.jar dist/plugins/ +cp plugins/enabled.txt dist/plugins/ +cp plugins/disabled.txt dist/plugins/ + +cd dist + +# unzip app to "dist" directory +jar xf ../app/target/*.zip + +# run app +java -jar *.jar + +cd - diff --git a/pom.xml b/pom.xml index 46a432d..add6723 100644 --- a/pom.xml +++ b/pom.xml @@ -160,6 +160,7 @@ pf4j demo + maven-archetypes/quickstart From 1bfeed1312f038ec0c4ecc454fbb2f9583f22202 Mon Sep 17 00:00:00 2001 From: decebals Date: Thu, 30 May 2019 22:00:52 +0300 Subject: [PATCH 45/54] Add constructors in JarPluginManager --- pf4j/src/main/java/org/pf4j/JarPluginManager.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pf4j/src/main/java/org/pf4j/JarPluginManager.java b/pf4j/src/main/java/org/pf4j/JarPluginManager.java index 5921aa5..f280466 100644 --- a/pf4j/src/main/java/org/pf4j/JarPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/JarPluginManager.java @@ -15,6 +15,8 @@ */ package org.pf4j; +import java.nio.file.Path; + /** * It's a {@link PluginManager} that loads each plugin from a {@code jar} file. * Actually, a plugin is a fat jar, a jar which contains classes from all the libraries, @@ -24,6 +26,14 @@ package org.pf4j; */ public class JarPluginManager extends DefaultPluginManager { + public JarPluginManager() { + super(); + } + + public JarPluginManager(Path pluginsRoot) { + super(pluginsRoot); + } + @Override protected PluginDescriptorFinder createPluginDescriptorFinder() { return new ManifestPluginDescriptorFinder(); From a8f00177d9306b949c60f5549c6b374557b750ef Mon Sep 17 00:00:00 2001 From: decebals Date: Thu, 30 May 2019 22:01:58 +0300 Subject: [PATCH 46/54] Improve PluginJar --- .../test/java/org/pf4j/plugin/PluginJar.java | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java index d486ef8..366c22a 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java @@ -17,6 +17,7 @@ package org.pf4j.plugin; import org.pf4j.ManifestPluginDescriptorFinder; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; @@ -51,6 +52,10 @@ public class PluginJar { return path; } + public File file() { + return path.toFile(); + } + public String pluginClass() { return pluginClass; } @@ -81,7 +86,7 @@ public class PluginJar { private String pluginClass; private String pluginVersion; - private Map attributes; + private Map manifestAttributes = new LinkedHashMap<>(); public Builder(Path path, String pluginId) { this.path = path; @@ -102,9 +107,20 @@ public class PluginJar { /** * 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 attributes(Map attributes) { - this.attributes = attributes; + public Builder manifestAttribute(String name, String value) { + manifestAttributes.put(name, value); return this; } @@ -122,11 +138,12 @@ public class PluginJar { if (pluginClass != null) { map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); } - if (attributes != null) { - map.putAll(attributes); + if (manifestAttributes != null) { + map.putAll(manifestAttributes); } - JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(path.toFile()), createManifest(map)); + Manifest manifest = createManifest(map); + JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(path.toFile()), manifest); outputStream.close(); } From 0ad926448eae71ff720174dd940468eac942161d Mon Sep 17 00:00:00 2001 From: decebals Date: Thu, 30 May 2019 22:02:38 +0300 Subject: [PATCH 47/54] Improve PluginZip --- .../test/java/org/pf4j/plugin/PluginZip.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java index 5f705e1..f34d84a 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java @@ -17,6 +17,7 @@ package org.pf4j.plugin; import org.pf4j.PropertiesPluginDescriptorFinder; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; @@ -50,6 +51,10 @@ public class PluginZip { return path; } + public File file() { + return path.toFile(); + } + public String pluginId() { return pluginId; } @@ -83,7 +88,7 @@ public class PluginZip { private String pluginClass; private String pluginVersion; - private Map properties; + private Map properties = new LinkedHashMap<>(); public Builder(Path path, String pluginId) { this.path = path; @@ -104,9 +109,20 @@ public class PluginZip { /** * Add extra properties to the {@code properties} file. + * As possible attribute name please see {@link PropertiesPluginDescriptorFinder}. */ public Builder properties(Map properties) { - this.properties = 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; } From 733fb970b4523f61832f0f92f8b4c90daf949487 Mon Sep 17 00:00:00 2001 From: decebals Date: Thu, 30 May 2019 22:03:51 +0300 Subject: [PATCH 48/54] Add JarPluginManagerTest --- .../java/org/pf4j/JarPluginManagerTest.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java diff --git a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java new file mode 100644 index 0000000..45c3999 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.pf4j.plugin.PluginJar; +import org.pf4j.plugin.TestPlugin; + +import java.io.IOException; +import java.nio.file.Path; + +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 { + + private PluginJar pluginJar; + private JarPluginManager pluginManager; + + @TempDir + Path pluginsPath; + + @BeforeEach + public void setUp() throws IOException { + pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), "test-plugin") + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("1.2.3") + .build(); + + pluginManager = new JarPluginManager(pluginsPath); + } + + @AfterEach + public void tearDown() { + pluginJar = null; + pluginManager = null; + } + + @Test + public void unloadPlugin() throws Exception { + pluginManager.loadPlugins(); + + assertEquals(1, pluginManager.getPlugins().size()); + + boolean unloaded = pluginManager.unloadPlugin(pluginJar.pluginId()); + assertTrue(unloaded); + + assertTrue(pluginJar.file().exists()); + } + + @Test + public void deletePlugin() throws Exception { + pluginManager.loadPlugins(); + + assertEquals(1, pluginManager.getPlugins().size()); + + boolean deleted = pluginManager.deletePlugin(pluginJar.pluginId()); + assertTrue(deleted); + + assertFalse(pluginJar.file().exists()); + } + +} From 6fd8ae23848fafaadb37d0e9e9169e0c1dc4ccb2 Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Fri, 31 May 2019 20:02:09 +0300 Subject: [PATCH 49/54] Improve PluginJar, add ClassDataProvider concept --- .../java/org/pf4j/JarPluginManagerTest.java | 16 +++++ .../org/pf4j/plugin/ClassDataProvider.java | 33 ++++++++++ .../pf4j/plugin/DefaultClassDataProvider.java | 55 +++++++++++++++++ .../org/pf4j/plugin/FailTestExtension.java | 5 ++ .../test/java/org/pf4j/plugin/PluginJar.java | 60 +++++++++++++++++-- .../java/org/pf4j/plugin/TestExtension.java | 5 ++ .../org/pf4j/plugin/TestExtensionPoint.java | 2 + 7 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java create mode 100644 pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java diff --git a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java index 45c3999..d9ca90a 100644 --- a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java @@ -20,10 +20,13 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.plugin.PluginJar; +import org.pf4j.plugin.TestExtension; +import org.pf4j.plugin.TestExtensionPoint; import org.pf4j.plugin.TestPlugin; import java.io.IOException; import java.nio.file.Path; +import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -42,6 +45,7 @@ public class JarPluginManagerTest { pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), "test-plugin") .pluginClass(TestPlugin.class.getName()) .pluginVersion("1.2.3") + .extension(TestExtension.class.getName()) .build(); pluginManager = new JarPluginManager(pluginsPath); @@ -53,6 +57,18 @@ public class JarPluginManagerTest { pluginManager = null; } + @Test + public void getExtensions() { + pluginManager.loadPlugins(); + pluginManager.startPlugins(); + + List extensions = pluginManager.getExtensions(TestExtensionPoint.class); + assertEquals(1, extensions.size()); + + String something = extensions.get(0).saySomething(); + assertEquals(new TestExtension().saySomething(), something); + } + @Test public void unloadPlugin() throws Exception { pluginManager.loadPlugins(); diff --git a/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java b/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java new file mode 100644 index 0000000..ff55967 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j.plugin; + +/** + * Defines the interface for classes that know to supply class data for a class name. + * The idea is to have the possibility to retrieve the data for a class from different sources: + *
    + *
  • Class path - the class is already loaded by the class loader
  • + *
  • String - the string (the source code) is compiled dynamically via {@link javax.tools.JavaCompiler} + *
  • Generate the source code programmatically using something like {@code https://github.com/square/javapoet}
  • + *
+ * + * @author Decebal Suiu + */ +public interface ClassDataProvider { + + byte[] getClassData(String className); + +} diff --git a/pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java b/pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java new file mode 100644 index 0000000..ef0eaf9 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.pf4j.plugin; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Get class data from the class path. + * + * @author Decebal Suiu + */ +public class DefaultClassDataProvider implements ClassDataProvider { + + @Override + public byte[] getClassData(String className) { + String path = className.replace('.', '/') + ".class"; + InputStream classDataStream = getClass().getClassLoader().getResourceAsStream(path); + if (classDataStream == null) { + throw new RuntimeException("Cannot find class data"); + } + + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + copyStream(classDataStream, outputStream); + return outputStream.toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + private void copyStream(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[1024]; + + int bytesRead; + while ((bytesRead = in.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + } + +} diff --git a/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java b/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java index 9cc37e0..13b51ee 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java +++ b/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java @@ -26,4 +26,9 @@ public class FailTestExtension implements TestExtensionPoint { public FailTestExtension(String name) { } + @Override + public String saySomething() { + return "I am a fail test extension"; + } + } diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java index 366c22a..a75b68f 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java +++ b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java @@ -17,18 +17,23 @@ package org.pf4j.plugin; import org.pf4j.ManifestPluginDescriptorFinder; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; 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. * The {@code MANIFEST.MF} file is created on the fly from the information supplied in {@link Builder}. * @@ -87,6 +92,8 @@ public class PluginJar { 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) { this.path = path; @@ -125,13 +132,44 @@ public class PluginJar { return this; } + public Builder extension(String extensionClassName) { + extensions.add(extensionClassName); + + return this; + } + + public Builder classDataProvider(ClassDataProvider classDataProvider) { + this.classDataProvider = classDataProvider; + + return this; + } + public PluginJar build() throws IOException { - createManifestFile(); + Manifest manifest = createManifest(); + try (OutputStream outputStream = new FileOutputStream(path.toFile())) { + JarOutputStream jarOutputStream = new JarOutputStream(outputStream, manifest); + if (!extensions.isEmpty()) { + // add extensions.idx + JarEntry jarEntry = new JarEntry("META-INF/extensions.idx"); + jarOutputStream.putNextEntry(jarEntry); + jarOutputStream.write(extensionsAsByteArray()); + jarOutputStream.closeEntry(); + // add extensions classes + for (String extension : extensions) { + String extensionPath = extension.replace('.', '/') + ".class"; + JarEntry classEntry = new JarEntry(extensionPath); + jarOutputStream.putNextEntry(classEntry); + jarOutputStream.write(classDataProvider.getClassData(extension)); + jarOutputStream.closeEntry(); + } + } + jarOutputStream.close(); + } return new PluginJar(this); } - protected void createManifestFile() throws IOException { + private Manifest createManifest() { Map map = new LinkedHashMap<>(); map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, pluginId); map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); @@ -142,9 +180,19 @@ public class PluginJar { map.putAll(manifestAttributes); } - Manifest manifest = createManifest(map); - JarOutputStream outputStream = new JarOutputStream(new FileOutputStream(path.toFile()), manifest); - outputStream.close(); + return PluginJar.createManifest(map); + } + + private byte[] extensionsAsByteArray() throws IOException { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + PrintWriter writer = new PrintWriter(outputStream); + for (String extension : extensions) { + writer.println(extension); + } + writer.flush(); + + return outputStream.toByteArray(); + } } } diff --git a/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java b/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java index 5f48c9a..83bc0b5 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java +++ b/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java @@ -23,4 +23,9 @@ import org.pf4j.Extension; @Extension public class TestExtension implements TestExtensionPoint { + @Override + public String saySomething() { + return "I am a test extension"; + } + } diff --git a/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java b/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java index a33ac40..d29a7ab 100644 --- a/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java +++ b/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java @@ -22,4 +22,6 @@ import org.pf4j.ExtensionPoint; */ public interface TestExtensionPoint extends ExtensionPoint { + String saySomething(); + } From 1bd6b801d45193b660d59656fafe6ea6cde77975 Mon Sep 17 00:00:00 2001 From: hazemkmammu Date: Tue, 4 Jun 2019 15:02:55 +0530 Subject: [PATCH 50/54] Recreate FileSystemException in windows on plugin delete (#321) --- .../org/pf4j/LegacyExtensionFinderTest.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java diff --git a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java new file mode 100644 index 0000000..fe2cac2 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java @@ -0,0 +1,69 @@ +package org.pf4j; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.pf4j.plugin.PluginJar; + +public class LegacyExtensionFinderTest { + + @TempDir + public Path pluginsPath; + + public static class TestPlugin extends Plugin { + + public TestPlugin(PluginWrapper wrapper) { + super(wrapper); + } + } + + @Extension + public static class TestExtension implements ExtensionPoint { + + } + + private static boolean systemIsWindows() { + String os = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); + return os.startsWith("win"); + } + + @Test + public void shouldUnlockFileAfterReadingExtensionsFromPlugin() throws IOException, PluginException { + + assumeTrue(systemIsWindows()); + final Path pluginJarPath = pluginsPath.resolve("test-plugin.jar"); + PluginJar pluginJar = new PluginJar.Builder(pluginJarPath, "test-plugin") + .pluginClass(TestPlugin.class.getName()) + .pluginVersion("1.2.3") + .extension(TestExtension.class.getName()) + .build(); + + JarPluginManager pluginManager = new JarPluginManager(pluginsPath); + + pluginManager.loadPlugins(); + LegacyExtensionFinder extensionFinder = new LegacyExtensionFinder(pluginManager); + Map> pluginStorages = extensionFinder.readPluginsStorages(); + pluginManager.unloadPlugin(pluginJar.pluginId()); + boolean fileDeleted = pluginJarPath.toFile().delete(); + + assertThat(pluginStorages, is(notNullValue())); + assertThat(pluginStorages.get(pluginJar.pluginId()), is(notNullValue())); + assertThat(pluginStorages.get(pluginJar.pluginId()).size(), is(equalTo(1))); + assertThat(pluginStorages.get(pluginJar.pluginId()), + contains("org.pf4j.LegacyExtensionFinderTest$TestExtension")); + assertThat(fileDeleted, is(equalTo(true))); + } + +} From a0a645ffdd924d17f431a5db49ce4b24e9c88e58 Mon Sep 17 00:00:00 2001 From: decebals Date: Tue, 4 Jun 2019 13:17:43 +0300 Subject: [PATCH 51/54] Polishing #321 --- .../org/pf4j/LegacyExtensionFinderTest.java | 92 ++++++++++--------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java index fe2cac2..8f5a727 100644 --- a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java @@ -1,69 +1,73 @@ +/* + * Copyright (C) 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.pf4j; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.jupiter.api.Assumptions.assumeTrue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.io.TempDir; +import org.pf4j.plugin.PluginJar; +import org.pf4j.plugin.TestExtension; +import org.pf4j.plugin.TestPlugin; -import java.io.IOException; import java.nio.file.Path; -import java.util.Locale; import java.util.Map; import java.util.Set; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import org.pf4j.plugin.PluginJar; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.condition.OS.WINDOWS; public class LegacyExtensionFinderTest { @TempDir - public Path pluginsPath; - - public static class TestPlugin extends Plugin { - - public TestPlugin(PluginWrapper wrapper) { - super(wrapper); - } - } - - @Extension - public static class TestExtension implements ExtensionPoint { - - } - - private static boolean systemIsWindows() { - String os = System.getProperty("os.name").toLowerCase(Locale.ENGLISH); - return os.startsWith("win"); - } + Path pluginsPath; @Test - public void shouldUnlockFileAfterReadingExtensionsFromPlugin() throws IOException, PluginException { - - assumeTrue(systemIsWindows()); - final Path pluginJarPath = pluginsPath.resolve("test-plugin.jar"); - PluginJar pluginJar = new PluginJar.Builder(pluginJarPath, "test-plugin") + @EnabledOnOs(WINDOWS) + public void shouldUnlockFileAfterReadingExtensionsFromPlugin() throws Exception { + PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), "test-plugin") .pluginClass(TestPlugin.class.getName()) .pluginVersion("1.2.3") .extension(TestExtension.class.getName()) .build(); - JarPluginManager pluginManager = new JarPluginManager(pluginsPath); + assertTrue(pluginJar.file().exists()); + PluginManager pluginManager = new JarPluginManager(pluginsPath); pluginManager.loadPlugins(); + + assertEquals(1, pluginManager.getPlugins().size()); + LegacyExtensionFinder extensionFinder = new LegacyExtensionFinder(pluginManager); - Map> pluginStorages = extensionFinder.readPluginsStorages(); - pluginManager.unloadPlugin(pluginJar.pluginId()); - boolean fileDeleted = pluginJarPath.toFile().delete(); + Map> pluginsStorages = extensionFinder.readPluginsStorages(); + assertNotNull(pluginsStorages); - assertThat(pluginStorages, is(notNullValue())); - assertThat(pluginStorages.get(pluginJar.pluginId()), is(notNullValue())); - assertThat(pluginStorages.get(pluginJar.pluginId()).size(), is(equalTo(1))); - assertThat(pluginStorages.get(pluginJar.pluginId()), - contains("org.pf4j.LegacyExtensionFinderTest$TestExtension")); - assertThat(fileDeleted, is(equalTo(true))); + pluginManager.unloadPlugin(pluginJar.pluginId()); + boolean fileDeleted = pluginJar.file().delete(); + + Set pluginStorages = pluginsStorages.get(pluginJar.pluginId()); + assertNotNull(pluginStorages); + assertEquals(1, pluginStorages.size()); + assertThat(pluginStorages, contains(TestExtension.class.getName())); + assertTrue(fileDeleted); + assertFalse(pluginJar.file().exists()); } } From 553a0753f59870b29515b05013ad4f1a0ef547d7 Mon Sep 17 00:00:00 2001 From: hazemkmammu Date: Wed, 5 Jun 2019 03:03:11 +0530 Subject: [PATCH 52/54] Fix FileSystemException in windows on plugin delete (#322) --- .../java/org/pf4j/LegacyExtensionFinder.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java b/pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java index 99e1313..33adc27 100644 --- a/pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java +++ b/pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java @@ -20,6 +20,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; @@ -81,11 +82,14 @@ public class LegacyExtensionFinder extends AbstractExtensionFinder { Set bucket = new HashSet<>(); try { - Enumeration urls = ((PluginClassLoader) plugin.getPluginClassLoader()).findResources(getExtensionsResource()); - if (urls.hasMoreElements()) { - collectExtensions(urls, bucket); - } else { - log.debug("Cannot find '{}'", getExtensionsResource()); + log.debug("Read '{}'", getExtensionsResource()); + ClassLoader pluginClassLoader = plugin.getPluginClassLoader(); + try (InputStream resourceStream = pluginClassLoader.getResourceAsStream(getExtensionsResource())) { + if (resourceStream == null) { + log.debug("Cannot find '{}'", getExtensionsResource()); + } else { + collectExtensions(resourceStream, bucket); + } } debugExtensions(bucket); @@ -103,9 +107,13 @@ public class LegacyExtensionFinder extends AbstractExtensionFinder { while (urls.hasMoreElements()) { URL url = urls.nextElement(); log.debug("Read '{}'", url.getFile()); - try (Reader reader = new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)) { - LegacyExtensionStorage.read(reader, bucket); - } + collectExtensions(url.openStream(), bucket); + } + } + + private void collectExtensions(InputStream inputStream, Set bucket) throws IOException { + try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + LegacyExtensionStorage.read(reader, bucket); } } From e81d9054f721dbd2900fb6190b4326e47dd0f1fd Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Sat, 8 Jun 2019 22:49:38 +0300 Subject: [PATCH 53/54] Convert PluginException in PluginRuntimeException and use unchecked exceptions --- .../java/org/pf4j/AbstractPluginManager.java | 44 +++++++++---------- .../java/org/pf4j/BasePluginRepository.java | 4 +- .../pf4j/CompoundPluginDescriptorFinder.java | 4 +- .../org/pf4j/CompoundPluginRepository.java | 2 +- .../org/pf4j/DefaultExtensionFactory.java | 4 +- .../java/org/pf4j/DefaultPluginManager.java | 7 +-- .../org/pf4j/DefaultPluginRepository.java | 3 +- .../org/pf4j/DefaultPluginStatusProvider.java | 8 ++-- .../java/org/pf4j/DependencyResolver.java | 6 +-- .../main/java/org/pf4j/ExtensionFactory.java | 2 +- .../main/java/org/pf4j/ExtensionWrapper.java | 2 +- .../pf4j/ManifestPluginDescriptorFinder.java | 12 ++--- pf4j/src/main/java/org/pf4j/Plugin.java | 6 +-- .../pf4j/PluginAlreadyLoadedException.java | 2 +- .../java/org/pf4j/PluginDescriptorFinder.java | 5 +-- .../src/main/java/org/pf4j/PluginManager.java | 28 +++++++----- .../main/java/org/pf4j/PluginRepository.java | 3 +- ...ption.java => PluginRuntimeException.java} | 16 +++---- .../java/org/pf4j/PluginStatusProvider.java | 6 ++- .../PropertiesPluginDescriptorFinder.java | 14 +++--- .../org/pf4j/SingletonExtensionFactory.java | 2 +- .../CompoundPluginDescriptorFinderTest.java | 2 +- .../org/pf4j/DefaultExtensionFactoryTest.java | 4 +- .../org/pf4j/DefaultPluginManagerTest.java | 8 ++-- .../org/pf4j/DefaultPluginRepositoryTest.java | 2 +- .../test/java/org/pf4j/LoadPluginsTest.java | 4 +- .../ManifestPluginDescriptorFinderTest.java | 2 +- .../PropertiesPluginDescriptorFinderTest.java | 2 +- .../pf4j/SingletonExtensionFactoryTest.java | 4 +- 29 files changed, 105 insertions(+), 103 deletions(-) rename pf4j/src/main/java/org/pf4j/{PluginException.java => PluginRuntimeException.java} (72%) diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java index 6039b51..6bd6170 100644 --- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java @@ -180,7 +180,7 @@ public abstract class AbstractPluginManager implements PluginManager { } @Override - public String loadPlugin(Path pluginPath) throws PluginException { + public String loadPlugin(Path pluginPath) { if ((pluginPath == null) || Files.notExists(pluginPath)) { throw new IllegalArgumentException(String.format("Specified plugin %s does not exist!", pluginPath)); } @@ -222,7 +222,7 @@ public abstract class AbstractPluginManager implements PluginManager { for (Path pluginPath : pluginPaths) { try { loadPluginFromPath(pluginPath); - } catch (PluginException e) { + } catch (PluginRuntimeException e) { log.error(e.getMessage(), e); } } @@ -230,7 +230,7 @@ public abstract class AbstractPluginManager implements PluginManager { // resolve plugins try { resolvePlugins(); - } catch (PluginException e) { + } catch (PluginRuntimeException e) { log.error(e.getMessage(), e); } } @@ -239,11 +239,11 @@ public abstract class AbstractPluginManager implements PluginManager { * Unload the specified plugin and it's dependents. */ @Override - public boolean unloadPlugin(String pluginId) throws PluginException { + public boolean unloadPlugin(String pluginId) { return unloadPlugin(pluginId, true); } - private boolean unloadPlugin(String pluginId, boolean unloadDependents) throws PluginException { + private boolean unloadPlugin(String pluginId, boolean unloadDependents) { try { if (unloadDependents) { List dependents = dependencyResolver.getDependents(pluginId); @@ -276,7 +276,7 @@ public abstract class AbstractPluginManager implements PluginManager { try { ((Closeable) classLoader).close(); } catch (IOException e) { - throw new PluginException("Cannot close classloader", e); + throw new PluginRuntimeException(e, "Cannot close classloader"); } } } @@ -290,7 +290,7 @@ public abstract class AbstractPluginManager implements PluginManager { } @Override - public boolean deletePlugin(String pluginId) throws PluginException { + public boolean deletePlugin(String pluginId) { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -344,7 +344,7 @@ public abstract class AbstractPluginManager implements PluginManager { * Start the specified plugin and its dependencies. */ @Override - public PluginState startPlugin(String pluginId) throws PluginException { + public PluginState startPlugin(String pluginId) { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -400,7 +400,7 @@ public abstract class AbstractPluginManager implements PluginManager { itr.remove(); firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState)); - } catch (PluginException e) { + } catch (PluginRuntimeException e) { log.error(e.getMessage(), e); } } @@ -411,11 +411,11 @@ public abstract class AbstractPluginManager implements PluginManager { * Stop the specified plugin and it's dependents. */ @Override - public PluginState stopPlugin(String pluginId) throws PluginException { + public PluginState stopPlugin(String pluginId) { return stopPlugin(pluginId, true); } - private PluginState stopPlugin(String pluginId, boolean stopDependents) throws PluginException { + private PluginState stopPlugin(String pluginId, boolean stopDependents) { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -458,7 +458,7 @@ public abstract class AbstractPluginManager implements PluginManager { } @Override - public boolean disablePlugin(String pluginId) throws PluginException { + public boolean disablePlugin(String pluginId) { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -484,7 +484,7 @@ public abstract class AbstractPluginManager implements PluginManager { } @Override - public boolean enablePlugin(String pluginId) throws PluginException { + public boolean enablePlugin(String pluginId) { checkPluginId(pluginId); PluginWrapper pluginWrapper = getPlugin(pluginId); @@ -560,7 +560,7 @@ public abstract class AbstractPluginManager implements PluginManager { for (ExtensionWrapper extensionWrapper : extensionsWrapper) { try { extensions.add(extensionWrapper.getExtension()); - } catch (PluginException e) { + } catch (PluginRuntimeException e) { log.error("Cannot retrieve extension", e); } } @@ -732,7 +732,7 @@ public abstract class AbstractPluginManager implements PluginManager { return pluginStatusProvider.isPluginDisabled(pluginId); } - protected void resolvePlugins() throws PluginException { + protected void resolvePlugins() { // retrieves the plugins descriptors List descriptors = new ArrayList<>(); for (PluginWrapper plugin : plugins.values()) { @@ -781,7 +781,7 @@ public abstract class AbstractPluginManager implements PluginManager { } } - protected PluginWrapper loadPluginFromPath(Path pluginPath) throws PluginException { + protected PluginWrapper loadPluginFromPath(Path pluginPath) { // Test for plugin path duplication String pluginId = idForPath(pluginPath); if (pluginId != null) { @@ -799,7 +799,7 @@ public abstract class AbstractPluginManager implements PluginManager { pluginId = pluginDescriptor.getPluginId(); if (plugins.containsKey(pluginId)) { PluginWrapper loadedPlugin = getPlugin(pluginId); - throw new PluginException("There is an already loaded plugin ({}) " + throw new PluginRuntimeException("There is an already loaded plugin ({}) " + "with the same id ({}) as the plugin at path '{}'. Simultaneous loading " + "of plugins with the same PluginId is not currently supported.\n" + "As a workaround you may include PluginVersion and PluginProvider " @@ -867,15 +867,15 @@ public abstract class AbstractPluginManager implements PluginManager { * Override this to change the validation criteria. * * @param descriptor the plugin descriptor to validate - * @throws PluginException if validation fails + * @throws PluginRuntimeException if validation fails */ - protected void validatePluginDescriptor(PluginDescriptor descriptor) throws PluginException { + protected void validatePluginDescriptor(PluginDescriptor descriptor) { if (StringUtils.isNullOrEmpty(descriptor.getPluginId())) { - throw new PluginException("Field 'id' cannot be empty"); + throw new PluginRuntimeException("Field 'id' cannot be empty"); } if (descriptor.getVersion() == null) { - throw new PluginException("Field 'version' cannot be empty"); + throw new PluginRuntimeException("Field 'version' cannot be empty"); } } @@ -925,7 +925,7 @@ public abstract class AbstractPluginManager implements PluginManager { for (ExtensionWrapper extensionWrapper : extensionsWrapper) { try { extensions.add(extensionWrapper.getExtension()); - } catch (PluginException e) { + } catch (PluginRuntimeException e) { log.error("Cannot retrieve extension", e); } } diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java index 64c996b..8c856f8 100644 --- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java @@ -86,7 +86,7 @@ public class BasePluginRepository implements PluginRepository { } @Override - public boolean deletePluginPath(Path pluginPath) throws PluginException { + public boolean deletePluginPath(Path pluginPath) { if (!filter.accept(pluginPath.toFile())) { return false; } @@ -97,7 +97,7 @@ public class BasePluginRepository implements PluginRepository { } catch (NoSuchFileException e) { return false; // Return false on not found to be compatible with previous API (#135) } catch (IOException e) { - throw new PluginException(e); + throw new PluginRuntimeException(e); } } diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java index 751ad5e..6fe1ff2 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java @@ -57,7 +57,7 @@ public class CompoundPluginDescriptorFinder implements PluginDescriptorFinder { } @Override - public PluginDescriptor find(Path pluginPath) throws PluginException { + public PluginDescriptor find(Path pluginPath) { for (PluginDescriptorFinder finder : finders) { if (finder.isApplicable(pluginPath)) { log.debug("'{}' is applicable for plugin '{}'", finder, pluginPath); @@ -81,7 +81,7 @@ public class CompoundPluginDescriptorFinder implements PluginDescriptorFinder { } } - throw new PluginException("No PluginDescriptorFinder for plugin '{}'", pluginPath); + throw new PluginRuntimeException("No PluginDescriptorFinder for plugin '{}'", pluginPath); } } diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java index 600f00c..a36b00a 100644 --- a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java @@ -66,7 +66,7 @@ public class CompoundPluginRepository implements PluginRepository { } @Override - public boolean deletePluginPath(Path pluginPath) throws PluginException { + public boolean deletePluginPath(Path pluginPath) { for (PluginRepository repository : repositories) { if (repository.deletePluginPath(pluginPath)) { return true; diff --git a/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java b/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java index fbcba27..66e5054 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java +++ b/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java @@ -32,12 +32,12 @@ public class DefaultExtensionFactory implements ExtensionFactory { * Creates an extension instance. */ @Override - public T create(Class extensionClass) throws PluginException { + public T create(Class extensionClass) { log.debug("Create instance for extension '{}'", extensionClass.getName()); try { return extensionClass.newInstance(); } catch (Exception e) { - throw new PluginException(e); + throw new PluginRuntimeException(e); } } diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java index cafdb4e..9cad187 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java @@ -111,13 +111,14 @@ public class DefaultPluginManager extends AbstractPluginManager { } /** - * Load a plugin from disk. If the path is a zip file, first unpack + * Load a plugin from disk. If the path is a zip file, first unpack. + * * @param pluginPath plugin location on disk * @return PluginWrapper for the loaded plugin or null if not loaded - * @throws PluginException if problems during load + * @throws PluginRuntimeException if problems during load */ @Override - protected PluginWrapper loadPluginFromPath(Path pluginPath) throws PluginException { + protected PluginWrapper loadPluginFromPath(Path pluginPath) { // First unzip any ZIP files try { pluginPath = FileUtils.expandIfZip(pluginPath); diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java index 70a4bb9..2fafbc7 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java @@ -24,7 +24,6 @@ import org.pf4j.util.OrFileFilter; import org.pf4j.util.ZipFileFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.pf4j.util.NameFileFilter; import java.io.File; import java.io.FileFilter; @@ -54,7 +53,7 @@ public class DefaultPluginRepository extends BasePluginRepository { } @Override - public boolean deletePluginPath(Path pluginPath) throws PluginException { + public boolean deletePluginPath(Path pluginPath) { FileUtils.optimisticDelete(FileUtils.findWithEnding(pluginPath, ".zip", ".ZIP", ".Zip")); return super.deletePluginPath(pluginPath); } diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java b/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java index 823a29c..0b88fe8 100644 --- a/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java +++ b/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java @@ -66,22 +66,22 @@ public class DefaultPluginStatusProvider implements PluginStatusProvider { } @Override - public void disablePlugin(String pluginId) throws PluginException { + public void disablePlugin(String pluginId) { disabledPlugins.add(pluginId); try { FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile()); } catch (IOException e) { - throw new PluginException(e); + throw new PluginRuntimeException(e); } } @Override - public void enablePlugin(String pluginId) throws PluginException { + public void enablePlugin(String pluginId) { disabledPlugins.remove(pluginId); try { FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile()); } catch (IOException e) { - throw new PluginException(e); + throw new PluginRuntimeException(e); } } diff --git a/pf4j/src/main/java/org/pf4j/DependencyResolver.java b/pf4j/src/main/java/org/pf4j/DependencyResolver.java index a3aa9f6..45005e2 100644 --- a/pf4j/src/main/java/org/pf4j/DependencyResolver.java +++ b/pf4j/src/main/java/org/pf4j/DependencyResolver.java @@ -272,7 +272,7 @@ public class DependencyResolver { /** * It will be thrown if a cyclic dependency is detected. */ - public static class CyclicDependencyException extends PluginException { + public static class CyclicDependencyException extends PluginRuntimeException { public CyclicDependencyException() { super("Cyclic dependencies"); @@ -283,7 +283,7 @@ public class DependencyResolver { /** * Indicates that the dependencies required were not found. */ - public static class DependenciesNotFoundException extends PluginException { + public static class DependenciesNotFoundException extends PluginRuntimeException { private List dependencies; @@ -302,7 +302,7 @@ public class DependencyResolver { /** * Indicates that some dependencies have wrong version. */ - public static class DependenciesWrongVersionException extends PluginException { + public static class DependenciesWrongVersionException extends PluginRuntimeException { private List dependencies; diff --git a/pf4j/src/main/java/org/pf4j/ExtensionFactory.java b/pf4j/src/main/java/org/pf4j/ExtensionFactory.java index 42b0de8..176c6ff 100644 --- a/pf4j/src/main/java/org/pf4j/ExtensionFactory.java +++ b/pf4j/src/main/java/org/pf4j/ExtensionFactory.java @@ -20,6 +20,6 @@ package org.pf4j; */ public interface ExtensionFactory { - T create(Class extensionClass) throws PluginException; + T create(Class extensionClass); } diff --git a/pf4j/src/main/java/org/pf4j/ExtensionWrapper.java b/pf4j/src/main/java/org/pf4j/ExtensionWrapper.java index 85c5b91..3899d5f 100644 --- a/pf4j/src/main/java/org/pf4j/ExtensionWrapper.java +++ b/pf4j/src/main/java/org/pf4j/ExtensionWrapper.java @@ -32,7 +32,7 @@ public class ExtensionWrapper implements Comparable> { } @SuppressWarnings("unchecked") - public T getExtension() throws PluginException { + public T getExtension() { if (extension == null) { extension = (T) extensionFactory.create(descriptor.extensionClass); } diff --git a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java index 20810ba..650b2d7 100644 --- a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java @@ -52,13 +52,13 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { } @Override - public PluginDescriptor find(Path pluginPath) throws PluginException { + public PluginDescriptor find(Path pluginPath) { Manifest manifest = readManifest(pluginPath); return createPluginDescriptor(manifest); } - protected Manifest readManifest(Path pluginPath) throws PluginException { + protected Manifest readManifest(Path pluginPath) { if (FileUtils.isJarFile(pluginPath)) { try (JarFile jar = new JarFile(pluginPath.toFile())) { Manifest manifest = jar.getManifest(); @@ -66,24 +66,24 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder { return manifest; } } catch (IOException e) { - throw new PluginException(e); + throw new PluginRuntimeException(e); } } Path manifestPath = getManifestPath(pluginPath); if (manifestPath == null) { - throw new PluginException("Cannot find the manifest path"); + throw new PluginRuntimeException("Cannot find the manifest path"); } log.debug("Lookup plugin descriptor in '{}'", manifestPath); if (Files.notExists(manifestPath)) { - throw new PluginException("Cannot find '{}' path", manifestPath); + throw new PluginRuntimeException("Cannot find '{}' path", manifestPath); } try (InputStream input = Files.newInputStream(manifestPath)) { return new Manifest(input); } catch (IOException e) { - throw new PluginException(e); + throw new PluginRuntimeException(e); } } diff --git a/pf4j/src/main/java/org/pf4j/Plugin.java b/pf4j/src/main/java/org/pf4j/Plugin.java index b648b64..e3dd449 100644 --- a/pf4j/src/main/java/org/pf4j/Plugin.java +++ b/pf4j/src/main/java/org/pf4j/Plugin.java @@ -60,21 +60,21 @@ public class Plugin { * This method is called by the application when the plugin is started. * See {@link PluginManager#startPlugin(String)}. */ - public void start() throws PluginException { + public void start() { } /** * This method is called by the application when the plugin is stopped. * See {@link PluginManager#stopPlugin(String)}. */ - public void stop() throws PluginException { + public void stop() { } /** * This method is called by the application when the plugin is deleted. * See {@link PluginManager#deletePlugin(String)}. */ - public void delete() throws PluginException { + public void delete() { } } diff --git a/pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java b/pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java index adfd90b..411756c 100644 --- a/pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java +++ b/pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java @@ -20,7 +20,7 @@ import java.nio.file.Path; /** * @author Decebal Suiu */ -public class PluginAlreadyLoadedException extends PluginException { +public class PluginAlreadyLoadedException extends PluginRuntimeException { private final String pluginId; private final Path pluginPath; diff --git a/pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java index 3b9f600..35185af 100644 --- a/pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java @@ -29,12 +29,9 @@ public interface PluginDescriptorFinder { /** * Returns true if this finder is applicable to the given {@link Path}. - * - * @param pluginPath - * @return */ boolean isApplicable(Path pluginPath); - PluginDescriptor find(Path pluginPath) throws PluginException; + PluginDescriptor find(Path pluginPath); } diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java index 0fb9b1f..a937f22 100644 --- a/pf4j/src/main/java/org/pf4j/PluginManager.java +++ b/pf4j/src/main/java/org/pf4j/PluginManager.java @@ -69,11 +69,10 @@ public interface PluginManager { * Load a plugin. * * @param pluginPath the plugin location - * @return the pluginId of the installed plugin as specified in - * its {@linkplain PluginDescriptor metadata} - * @throws PluginException if load of plugin fails + * @return the pluginId of the installed plugin as specified in its {@linkplain PluginDescriptor metadata} + * @throws PluginRuntimeException if something goes wrong */ - String loadPlugin(Path pluginPath) throws PluginException; + String loadPlugin(Path pluginPath); /** * Start all active plugins. @@ -84,8 +83,9 @@ public interface PluginManager { * Start the specified plugin and its dependencies. * * @return the plugin state + * @throws PluginRuntimeException if something goes wrong */ - PluginState startPlugin(String pluginId) throws PluginException; + PluginState startPlugin(String pluginId); /** * Stop all active plugins. @@ -96,40 +96,45 @@ public interface PluginManager { * Stop the specified plugin and its dependencies. * * @return the plugin state + * @throws PluginRuntimeException if something goes wrong */ - PluginState stopPlugin(String pluginId) throws PluginException; + PluginState stopPlugin(String pluginId); /** * Unload a plugin. * * @param pluginId the unique plugin identifier, specified in its metadata * @return true if the plugin was unloaded + * @throws PluginRuntimeException if something goes wrong */ - boolean unloadPlugin(String pluginId) throws PluginException; + boolean unloadPlugin(String pluginId); /** * Disables a plugin from being loaded. * * @param pluginId the unique plugin identifier, specified in its metadata * @return true if plugin is disabled + * @throws PluginRuntimeException if something goes wrong */ - boolean disablePlugin(String pluginId) throws PluginException; + boolean disablePlugin(String pluginId); /** * Enables a plugin that has previously been disabled. * * @param pluginId the unique plugin identifier, specified in its metadata * @return true if plugin is enabled + * @throws PluginRuntimeException if something goes wrong */ - boolean enablePlugin(String pluginId) throws PluginException; + boolean enablePlugin(String pluginId); /** * Deletes a plugin. * * @param pluginId the unique plugin identifier, specified in its metadata * @return true if the plugin was deleted + * @throws PluginRuntimeException if something goes wrong */ - boolean deletePlugin(String pluginId) throws PluginException; + boolean deletePlugin(String pluginId); ClassLoader getPluginClassLoader(String pluginId); @@ -195,7 +200,8 @@ public interface PluginManager { String getSystemVersion(); /** - * Gets the path of the folder where plugins are installed + * Gets the path of the folder where plugins are installed. + * * @return Path of plugins root */ Path getPluginsRoot(); diff --git a/pf4j/src/main/java/org/pf4j/PluginRepository.java b/pf4j/src/main/java/org/pf4j/PluginRepository.java index 9b4298a..6bc2356 100644 --- a/pf4j/src/main/java/org/pf4j/PluginRepository.java +++ b/pf4j/src/main/java/org/pf4j/PluginRepository.java @@ -38,7 +38,8 @@ public interface PluginRepository { * * @param pluginPath the plugin path * @return true if deleted + * @throws PluginRuntimeException if something goes wrong */ - boolean deletePluginPath(Path pluginPath) throws PluginException; + boolean deletePluginPath(Path pluginPath); } diff --git a/pf4j/src/main/java/org/pf4j/PluginException.java b/pf4j/src/main/java/org/pf4j/PluginRuntimeException.java similarity index 72% rename from pf4j/src/main/java/org/pf4j/PluginException.java rename to pf4j/src/main/java/org/pf4j/PluginRuntimeException.java index d1ba6f2..5d5ede9 100644 --- a/pf4j/src/main/java/org/pf4j/PluginException.java +++ b/pf4j/src/main/java/org/pf4j/PluginRuntimeException.java @@ -23,29 +23,25 @@ import org.pf4j.util.StringUtils; * * @author Decebal Suiu */ -public class PluginException extends Exception { +public class PluginRuntimeException extends RuntimeException { - public PluginException() { + public PluginRuntimeException() { super(); } - public PluginException(String message) { + public PluginRuntimeException(String message) { super(message); } - public PluginException(Throwable cause) { + public PluginRuntimeException(Throwable cause) { super(cause); } - public PluginException(String message, Throwable cause) { - super(message, cause); - } - - public PluginException(Throwable cause, String message, Object... args) { + public PluginRuntimeException(Throwable cause, String message, Object... args) { super(StringUtils.format(message, args), cause); } - public PluginException(String message, Object... args) { + public PluginRuntimeException(String message, Object... args) { super(StringUtils.format(message, args)); } diff --git a/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java b/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java index 228575f..46967b2 100644 --- a/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java +++ b/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java @@ -33,14 +33,16 @@ public interface PluginStatusProvider { * Disables a plugin from being loaded. * * @param pluginId the unique plugin identifier, specified in its metadata + * @throws PluginRuntimeException if something goes wrong */ - void disablePlugin(String pluginId) throws PluginException; + void disablePlugin(String pluginId); /** * Enables a plugin that has previously been disabled. * * @param pluginId the unique plugin identifier, specified in its metadata + * @throws PluginRuntimeException if something goes wrong */ - void enablePlugin(String pluginId) throws PluginException; + void enablePlugin(String pluginId); } diff --git a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java index 31afee9..6789a5f 100644 --- a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java +++ b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java @@ -63,34 +63,34 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder } @Override - public PluginDescriptor find(Path pluginPath) throws PluginException { + public PluginDescriptor find(Path pluginPath) { Properties properties = readProperties(pluginPath); return createPluginDescriptor(properties); } - protected Properties readProperties(Path pluginPath) throws PluginException { + protected Properties readProperties(Path pluginPath) { Path propertiesPath = getPropertiesPath(pluginPath, propertiesFileName); if (propertiesPath == null) { - throw new PluginException("Cannot find the properties path"); + throw new PluginRuntimeException("Cannot find the properties path"); } log.debug("Lookup plugin descriptor in '{}'", propertiesPath); if (Files.notExists(propertiesPath)) { - throw new PluginException("Cannot find '{}' path", propertiesPath); + throw new PluginRuntimeException("Cannot find '{}' path", propertiesPath); } Properties properties = new Properties(); try (InputStream input = Files.newInputStream(propertiesPath)) { properties.load(input); } catch (IOException e) { - throw new PluginException(e); + throw new PluginRuntimeException(e); } return properties; } - protected Path getPropertiesPath(Path pluginPath, String propertiesFileName) throws PluginException { + protected Path getPropertiesPath(Path pluginPath, String propertiesFileName) { if (Files.isDirectory(pluginPath)) { return pluginPath.resolve(Paths.get(propertiesFileName)); } else { @@ -98,7 +98,7 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder try { return FileUtils.getPath(pluginPath, propertiesFileName); } catch (IOException e) { - throw new PluginException(e); + throw new PluginRuntimeException(e); } } } diff --git a/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java b/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java index 3da97d0..725b9a7 100644 --- a/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java +++ b/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java @@ -40,7 +40,7 @@ public class SingletonExtensionFactory extends DefaultExtensionFactory { @Override @SuppressWarnings("unchecked") - public T create(Class extensionClass) throws PluginException { + public T create(Class extensionClass) { String extensionClassName = extensionClass.getName(); if (cache.containsKey(extensionClassName)) { return (T) cache.get(extensionClassName); diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java index d74bea3..c16839e 100644 --- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java @@ -87,7 +87,7 @@ public class CompoundPluginDescriptorFinderTest { @Test public void testNotFound() { PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder(); - assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); + assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } @Test diff --git a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java index 207c178..150828f 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java @@ -45,7 +45,7 @@ public class DefaultExtensionFactoryTest { * Test of create method, of class DefaultExtensionFactory. */ @Test - public void testCreate() throws PluginException { + public void testCreate() { assertNotNull(extensionFactory.create(TestExtension.class)); } @@ -54,7 +54,7 @@ public class DefaultExtensionFactoryTest { */ @Test public void testCreateFailConstructor() { - assertThrows(PluginException.class, () -> extensionFactory.create(FailTestExtension.class)); + assertThrows(PluginRuntimeException.class, () -> extensionFactory.create(FailTestExtension.class)); } } diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java index ced9b4e..8cb9b27 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java @@ -65,24 +65,24 @@ public class DefaultPluginManagerTest { } @Test - public void validateOK() throws PluginException { + public void validateOK() { pluginManager.validatePluginDescriptor(pluginDescriptor); } @Test public void validateFailsOnId() { pluginDescriptor.setPluginId(""); - assertThrows(PluginException.class, () -> pluginManager.validatePluginDescriptor(pluginDescriptor)); + assertThrows(PluginRuntimeException.class, () -> pluginManager.validatePluginDescriptor(pluginDescriptor)); } @Test public void validateFailsOnVersion() { pluginDescriptor.setPluginVersion(null); - assertThrows(PluginException.class, () -> pluginManager.validatePluginDescriptor(pluginDescriptor)); + assertThrows(PluginRuntimeException.class, () -> pluginManager.validatePluginDescriptor(pluginDescriptor)); } @Test - public void validateNoPluginClass() throws PluginException { + public void validateNoPluginClass() { pluginManager.validatePluginDescriptor(pluginDescriptor); assertEquals(Plugin.class.getName(), pluginDescriptor.getPluginClass()); } diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java index 3474aa6..c564543 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -67,7 +67,7 @@ public class DefaultPluginRepositoryTest { * Test of {@link DefaultPluginRepository#deletePluginPath(Path)} method. */ @Test - public void testDeletePluginPath() throws PluginException { + public void testDeletePluginPath() { PluginRepository repository = new DefaultPluginRepository(pluginsPath); assertTrue(Files.exists(pluginsPath.resolve("plugin-1.zip"))); diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java index d2a7e25..e3dac02 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java @@ -102,7 +102,7 @@ public class LoadPluginsTest { // Verify the second plugin is not loaded as it has the same metadata pluginManager.loadPluginFromPath(plugin2.path()); fail("Expected loadPluginFromPath to fail"); - } catch (PluginException e) { + } catch (PluginRuntimeException e) { // Check the path of the loaded plugin remains the same PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId); assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path)); @@ -141,7 +141,7 @@ public class LoadPluginsTest { // Verify the second plugin is not loaded as it has the same pluginId pluginManager.loadPluginFromPath(plugin2.path()); fail("Expected loadPluginFromPath to fail"); - } catch (PluginException e) { + } catch (PluginRuntimeException e) { // Check the path and version of the loaded plugin remain the same PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId); assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path)); diff --git a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java index 2ffe01b..468f2fb 100644 --- a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java @@ -107,7 +107,7 @@ public class ManifestPluginDescriptorFinderTest { @Test public void testFindNotFound() { PluginDescriptorFinder descriptorFinder = new ManifestPluginDescriptorFinder(); - assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); + assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } private Manifest getPlugin1Manifest() { diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index 1f51e95..bc91a7f 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -104,7 +104,7 @@ public class PropertiesPluginDescriptorFinderTest { @Test public void testNotFound() { PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder(); - assertThrows(PluginException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); + assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3"))); } private Properties getPlugin1Properties() { diff --git a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java index 97e98cf..80e7ab0 100644 --- a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java @@ -28,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.assertSame; public class SingletonExtensionFactoryTest { @Test - public void create() throws PluginException { + public void create() { ExtensionFactory extensionFactory = new SingletonExtensionFactory(); Object extensionOne = extensionFactory.create(TestExtension.class); Object extensionTwo = extensionFactory.create(TestExtension.class); @@ -36,7 +36,7 @@ public class SingletonExtensionFactoryTest { } @Test - public void createNewEachTime() throws PluginException { + public void createNewEachTime() { ExtensionFactory extensionFactory = new SingletonExtensionFactory(FailTestExtension.class.getName()); Object extensionOne = extensionFactory.create(TestExtension.class); Object extensionTwo = extensionFactory.create(TestExtension.class); From 06148f7fda2ec9d8e048856b9ca2e70d804a433e Mon Sep 17 00:00:00 2001 From: Decebal Suiu Date: Tue, 11 Jun 2019 20:11:49 +0300 Subject: [PATCH 54/54] Merge branch master --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc1f9e6..d6997a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -155,7 +155,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [#133]: Support for adding license information to the plugins - [#136]: Delete plugin zip on uninstall - [#139]: Ability to get `pluginsRoot` from PluginManager -- Add constructors with varargs in PippoException +- Add constructors with varargs in PluginException #### Removed