From: Decebal Suiu Date: Sat, 9 Jan 2021 16:45:20 +0000 (+0200) Subject: Externalize some useful classes from testing (#415) X-Git-Tag: release-3.6.0~3 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=02c52acbd05e4ccea00b98c84318f44eefc1a66d;p=pf4j.git Externalize some useful classes from testing (#415) --- diff --git a/pf4j/pom.xml b/pf4j/pom.xml index 2266775..06f016f 100644 --- a/pf4j/pom.xml +++ b/pf4j/pom.xml @@ -66,6 +66,18 @@ + + + + test-jar + + + + org/pf4j/test/* + + + + diff --git a/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java index e841189..83796ab 100644 --- a/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java @@ -22,8 +22,8 @@ import java.util.Comparator; 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; +import org.pf4j.test.FailTestPlugin; +import org.pf4j.test.TestExtensionPoint; import javax.tools.JavaFileObject; import java.io.IOException; @@ -113,8 +113,8 @@ public class AbstractExtensionFinderTest { Map> entries = new LinkedHashMap<>(); Set bucket = new HashSet<>(); - bucket.add("org.pf4j.plugin.TestExtension"); - bucket.add("org.pf4j.plugin.FailTestExtension"); + bucket.add("org.pf4j.test.TestExtension"); + bucket.add("org.pf4j.test.FailTestExtension"); entries.put(null, bucket); return entries; @@ -138,11 +138,11 @@ public class AbstractExtensionFinderTest { Map> entries = new LinkedHashMap<>(); Set bucket = new HashSet<>(); - bucket.add("org.pf4j.plugin.TestExtension"); - bucket.add("org.pf4j.plugin.FailTestExtension"); + bucket.add("org.pf4j.test.TestExtension"); + bucket.add("org.pf4j.test.FailTestExtension"); entries.put("plugin1", bucket); bucket = new HashSet<>(); - bucket.add("org.pf4j.plugin.TestExtension"); + bucket.add("org.pf4j.test.TestExtension"); entries.put("plugin2", bucket); return entries; diff --git a/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java index 784d1f9..f1824f7 100644 --- a/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java @@ -16,8 +16,8 @@ package org.pf4j; import org.junit.jupiter.api.Test; -import org.pf4j.plugin.TestExtension; -import org.pf4j.plugin.TestExtensionPoint; +import org.pf4j.test.TestExtension; +import org.pf4j.test.TestExtensionPoint; import java.util.ArrayList; import java.util.List; diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java index c16839e..f80c19e 100644 --- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java @@ -17,9 +17,9 @@ 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 org.pf4j.plugin.TestPlugin; +import org.pf4j.test.PluginJar; +import org.pf4j.test.PluginZip; +import org.pf4j.test.TestPlugin; import java.io.FileOutputStream; import java.io.IOException; diff --git a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java index 150828f..9d73b5e 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java @@ -18,8 +18,8 @@ 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 org.pf4j.test.FailTestExtension; +import org.pf4j.test.TestExtension; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java index eccfca2..3107083 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java @@ -16,9 +16,9 @@ package org.pf4j; import org.junit.jupiter.api.Test; -import org.pf4j.plugin.AnotherFailTestPlugin; -import org.pf4j.plugin.FailTestPlugin; -import org.pf4j.plugin.TestPlugin; +import org.pf4j.test.AnotherFailTestPlugin; +import org.pf4j.test.FailTestPlugin; +import org.pf4j.test.TestPlugin; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java index ae51282..fab1a02 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java @@ -19,8 +19,8 @@ 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.PluginZip; +import org.pf4j.test.PluginJar; +import org.pf4j.test.PluginZip; import java.io.IOException; import java.nio.file.Files; diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java index b8ffd7c..c11938d 100644 --- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java +++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java @@ -18,7 +18,7 @@ package org.pf4j; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.pf4j.plugin.PluginZip; +import org.pf4j.test.PluginZip; import org.pf4j.util.FileUtils; import java.io.IOException; diff --git a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java index 4eb2872..0e16f75 100644 --- a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java +++ b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java @@ -19,10 +19,10 @@ 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.TestExtension; -import org.pf4j.plugin.TestExtensionPoint; -import org.pf4j.plugin.TestPlugin; +import org.pf4j.test.PluginJar; +import org.pf4j.test.TestExtension; +import org.pf4j.test.TestExtensionPoint; +import org.pf4j.test.TestPlugin; import java.io.IOException; import java.nio.file.Path; diff --git a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java index 8f5a727..bde5417 100644 --- a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java @@ -18,9 +18,9 @@ package org.pf4j; 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 org.pf4j.test.PluginJar; +import org.pf4j.test.TestExtension; +import org.pf4j.test.TestPlugin; import java.nio.file.Path; import java.util.Map; diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsFromMultipleRootsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsFromMultipleRootsTest.java index 2117a62..9396f15 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsFromMultipleRootsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsFromMultipleRootsTest.java @@ -18,7 +18,7 @@ package org.pf4j; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.pf4j.plugin.PluginZip; +import org.pf4j.test.PluginZip; import org.pf4j.util.FileUtils; import java.io.IOException; diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java index ef2376b..189bd0a 100644 --- a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java +++ b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java @@ -18,7 +18,7 @@ package org.pf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.pf4j.plugin.PluginZip; +import org.pf4j.test.PluginZip; import java.nio.file.Files; import java.nio.file.Path; diff --git a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java index 468f2fb..079d8e2 100644 --- a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java @@ -18,7 +18,7 @@ package org.pf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.pf4j.plugin.PluginJar; +import org.pf4j.test.PluginJar; import java.io.FileOutputStream; import java.io.IOException; diff --git a/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java b/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java index b0316c7..fb75f27 100644 --- a/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java +++ b/pf4j/src/test/java/org/pf4j/PluginClassLoaderTest.java @@ -20,7 +20,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.pf4j.plugin.PluginZip; +import org.pf4j.test.PluginZip; import org.pf4j.util.FileUtils; import java.io.File; @@ -49,7 +49,7 @@ public class PluginClassLoaderTest { private PluginClassLoader parentLastPluginClassLoader; private PluginClassLoader parentFirstPluginClassLoader; - + private PluginClassLoader parentLastPluginDependencyClassLoader; private PluginClassLoader parentFirstPluginDependencyClassLoader; @@ -95,7 +95,7 @@ public class PluginClassLoaderTest { pluginDependencyDescriptor.setProvider("Me"); pluginDependencyDescriptor.setRequires("5.0.0"); - + Path pluginDependencyPath = pluginsPath.resolve(pluginDependencyDescriptor.getPluginId() + "-" + pluginDependencyDescriptor.getVersion() + ".zip"); PluginZip pluginDependencyZip = new PluginZip.Builder(pluginDependencyPath, pluginDependencyDescriptor.getPluginId()) .pluginVersion(pluginDependencyDescriptor.getVersion()) @@ -110,11 +110,11 @@ public class PluginClassLoaderTest { parentLastPluginDependencyClassLoader = new PluginClassLoader(pluginManager, pluginDependencyDescriptor, PluginClassLoaderTest.class.getClassLoader()); parentFirstPluginDependencyClassLoader = new PluginClassLoader(pluginManagerParentFirst, pluginDependencyDescriptor, PluginClassLoaderTest.class.getClassLoader(), true); - + pluginManager.addClassLoader(pluginDependencyDescriptor.getPluginId(), parentLastPluginDependencyClassLoader); pluginManagerParentFirst.addClassLoader(pluginDependencyDescriptor.getPluginId(), parentFirstPluginDependencyClassLoader); - - + + for (String classesDirectory : pluginDependencyClasspath.getClassesDirectories()) { File classesDirectoryFile = pluginDependencyZip.unzippedPath().resolve(classesDirectory).toFile(); parentLastPluginDependencyClassLoader.addFile(classesDirectoryFile); @@ -129,7 +129,7 @@ public class PluginClassLoaderTest { parentFirstPluginDependencyClassLoader.addFile(jar); } } - + pluginDescriptor = new DefaultPluginDescriptor(); pluginDescriptor.setPluginId("myPlugin"); pluginDescriptor.setPluginVersion("1.2.3"); @@ -155,7 +155,7 @@ public class PluginClassLoaderTest { pluginManager.addClassLoader(pluginDescriptor.getPluginId(), parentLastPluginClassLoader); pluginManagerParentFirst.addClassLoader(pluginDescriptor.getPluginId(), parentFirstPluginClassLoader); - + for (String classesDirectory : pluginClasspath.getClassesDirectories()) { File classesDirectoryFile = pluginZip.unzippedPath().resolve(classesDirectory).toFile(); parentLastPluginClassLoader.addFile(classesDirectoryFile); @@ -196,7 +196,7 @@ public class PluginClassLoaderTest { URL resource = parentLastPluginClassLoader.getResource("META-INF/file-only-in-parent"); assertFirstLine("parent", resource); } - + @Test void parentFirstGetResourceExistsInParent() throws IOException, URISyntaxException { URL resource = parentFirstPluginClassLoader.getResource("META-INF/file-only-in-parent"); @@ -214,7 +214,7 @@ public class PluginClassLoaderTest { URL resource = parentFirstPluginClassLoader.getResource("META-INF/plugin-file"); assertFirstLine("plugin", resource); } - + @Test void parentLastGetResourceExistsOnlyInDependnecy() throws IOException, URISyntaxException { URL resource = parentLastPluginClassLoader.getResource("META-INF/dependency-file"); @@ -238,13 +238,13 @@ public class PluginClassLoaderTest { URL resource = parentFirstPluginClassLoader.getResource("META-INF/file-in-both-parent-and-plugin"); assertFirstLine("parent", resource); } - + @Test void parentLastGetResourceExistsInParentAndDependencyAndPlugin() throws URISyntaxException, IOException { URL resource = parentLastPluginClassLoader.getResource("META-INF/file-in-both-parent-and-dependency-and-plugin"); assertFirstLine("plugin", resource); } - + @Test void parentFirstGetResourceExistsInParentAndDependencyAndPlugin() throws URISyntaxException, IOException { URL resource = parentFirstPluginClassLoader.getResource("META-INF/file-in-both-parent-and-dependency-and-plugin"); @@ -284,7 +284,7 @@ public class PluginClassLoaderTest { Enumeration resources = parentFirstPluginClassLoader.getResources("META-INF/dependency-file"); assertNumberOfResourcesAndFirstLineOfFirstElement(1, "dependency", resources); } - + @Test void parentLastGetResourcesExistsOnlyInPlugin() throws IOException, URISyntaxException { Enumeration resources = parentLastPluginClassLoader.getResources("META-INF/plugin-file"); @@ -308,7 +308,7 @@ public class PluginClassLoaderTest { Enumeration resources = parentFirstPluginClassLoader.getResources("META-INF/file-in-both-parent-and-plugin"); assertNumberOfResourcesAndFirstLineOfFirstElement(2, "parent", resources); } - + @Test void parentLastGetResourcesExistsInParentAndDependencyAndPlugin() throws URISyntaxException, IOException { Enumeration resources = parentLastPluginClassLoader.getResources("META-INF/file-in-both-parent-and-dependency-and-plugin"); @@ -333,9 +333,9 @@ public class PluginClassLoaderTest { URL firstResource = list.get(0); assertEquals(expectedFirstLine, Files.readAllLines(Paths.get(firstResource.toURI())).get(0)); } - + class TestPluginManager extends DefaultPluginManager { - + public TestPluginManager(Path pluginsPath) { super(pluginsPath); } diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java index bc91a7f..4d73a4f 100644 --- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java +++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java @@ -18,8 +18,8 @@ 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 org.pf4j.plugin.TestPlugin; +import org.pf4j.test.PluginZip; +import org.pf4j.test.TestPlugin; import java.io.FileOutputStream; import java.io.IOException; diff --git a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java index ac8a3c5..1044034 100644 --- a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java +++ b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java @@ -16,8 +16,8 @@ package org.pf4j; import org.junit.jupiter.api.Test; -import org.pf4j.plugin.FailTestExtension; -import org.pf4j.plugin.TestExtension; +import org.pf4j.test.FailTestExtension; +import org.pf4j.test.TestExtension; import java.io.File; import java.net.MalformedURLException; diff --git a/pf4j/src/test/java/org/pf4j/plugin/AnotherFailTestPlugin.java b/pf4j/src/test/java/org/pf4j/plugin/AnotherFailTestPlugin.java deleted file mode 100644 index b45f343..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/AnotherFailTestPlugin.java +++ /dev/null @@ -1,29 +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. - */ -package org.pf4j.plugin; - -import org.pf4j.Plugin; - -/** - * @author Mario Franco - */ -public class AnotherFailTestPlugin extends Plugin { - - public AnotherFailTestPlugin() { - super(null); - } - -} diff --git a/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java b/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java deleted file mode 100644 index ff55967..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java +++ /dev/null @@ -1,33 +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. - */ -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 deleted file mode 100644 index ef0eaf9..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java +++ /dev/null @@ -1,55 +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. - */ -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 deleted file mode 100644 index 13b51ee..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java +++ /dev/null @@ -1,34 +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. - */ -package org.pf4j.plugin; - -import org.pf4j.Extension; - -/** - * @author Mario Franco - */ -@Extension -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/FailTestPlugin.java b/pf4j/src/test/java/org/pf4j/plugin/FailTestPlugin.java deleted file mode 100644 index fab11c9..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/FailTestPlugin.java +++ /dev/null @@ -1,23 +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. - */ -package org.pf4j.plugin; - -/** - * @author Mario Franco - */ -public class FailTestPlugin { - -} diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java deleted file mode 100644 index 4a08e20..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java +++ /dev/null @@ -1,199 +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. - */ -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}. - * - * @author Decebal Suiu - */ -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; - } - - public Path path() { - return path; - } - - public File file() { - return path.toFile(); - } - - public String pluginClass() { - return pluginClass; - } - - public String pluginId() { - return pluginId; - } - - public String pluginVersion() { - return pluginVersion; - } - - public static Manifest createManifest(Map map) { - Manifest manifest = new Manifest(); - Attributes attributes = manifest.getMainAttributes(); - attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0"); - for (Map.Entry entry : map.entrySet()) { - attributes.put(new Attributes.Name(entry.getKey()), entry.getValue()); - } - - return manifest; - } - - public static class Builder { - - private final Path path; - private final String pluginId; - - 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; - this.pluginId = pluginId; - } - - public Builder pluginClass(String pluginClass) { - this.pluginClass = pluginClass; - - return this; - } - - public Builder pluginVersion(String pluginVersion) { - this.pluginVersion = pluginVersion; - - return this; - } - - /** - * Add extra attributes to the {@code manifest} file. - * As possible attribute name please see {@link ManifestPluginDescriptorFinder}. - */ - public Builder manifestAttributes(Map manifestAttributes) { - this.manifestAttributes.putAll(manifestAttributes); - - return this; - } - - /** - * Add extra attribute to the {@code manifest} file. - * As possible attribute name please see {@link ManifestPluginDescriptorFinder}. - */ - public Builder manifestAttribute(String name, String value) { - manifestAttributes.put(name, value); - - return this; - } - - 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 { - 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(); - } - } - } - - return new PluginJar(this); - } - - private Manifest createManifest() { - Map map = new LinkedHashMap<>(); - map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, pluginId); - map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); - if (pluginClass != null) { - map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); - } - if (manifestAttributes != null) { - map.putAll(manifestAttributes); - } - - return PluginJar.createManifest(map); - } - - private byte[] extensionsAsByteArray() throws IOException { - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - PrintWriter writer = new PrintWriter(outputStream); - for (String extension : extensions) { - writer.println(extension); - } - writer.flush(); - - return outputStream.toByteArray(); - } - } - - } - -} diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java deleted file mode 100644 index c2da257..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java +++ /dev/null @@ -1,189 +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. - */ -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; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Properties; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * 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 - */ -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; - } - - public Path path() { - return path; - } - - public File file() { - return path.toFile(); - } - - public String pluginId() { - return pluginId; - } - - public String pluginClass() { - return pluginClass; - } - - public String pluginVersion() { - return pluginVersion; - } - - public Path unzippedPath() { - Path path = path(); - String fileName = path.getFileName().toString(); - - return path.getParent().resolve(fileName.substring(0, fileName.length() - 4)); // without ".zip" suffix - } - - public static Properties createProperties(Map map) { - Properties properties = new Properties(); - properties.putAll(map); - - return properties; - } - - public static class Builder { - - private final Path path; - private final String pluginId; - - private String pluginClass; - private String pluginVersion; - private Map properties = new LinkedHashMap<>(); - private Map files = new LinkedHashMap<>(); - - public Builder(Path path, String pluginId) { - this.path = path; - this.pluginId = pluginId; - } - - public Builder pluginClass(String pluginClass) { - this.pluginClass = pluginClass; - - return this; - } - - public Builder pluginVersion(String pluginVersion) { - this.pluginVersion = pluginVersion; - - return this; - } - - /** - * Add extra properties to the {@code properties} file. - * As possible attribute name please see {@link PropertiesPluginDescriptorFinder}. - */ - public Builder properties(Map properties) { - this.properties.putAll(properties); - - return this; - } - - /** - * Add extra property to the {@code properties} file. - * As possible property name please see {@link PropertiesPluginDescriptorFinder}. - */ - public Builder property(String name, String value) { - properties.put(name, value); - - return this; - } - - /** - * Adds a file to the archive. - * - * @param path the relative path of the file - * @param content the content of the file - */ - public Builder addFile(Path path, byte[] content) { - files.put(path, content.clone()); - - return this; - } - - /** - * Adds a file to the archive. - * - * @param path the relative path of the file - * @param content the content of the file - */ - public Builder addFile(Path path, String content) { - files.put(path, content.getBytes()); - - return this; - } - - public PluginZip build() throws IOException { - createPropertiesFile(); - - return new PluginZip(this); - } - - protected void createPropertiesFile() throws IOException { - Map map = new LinkedHashMap<>(); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, pluginId); - map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); - if (pluginClass != null) { - map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); - } - if (properties != null) { - map.putAll(properties); - } - - try (ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(path.toFile()))) { - ZipEntry propertiesFile = new ZipEntry(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); - outputStream.putNextEntry(propertiesFile); - createProperties(map).store(outputStream, ""); - outputStream.closeEntry(); - - for (Map.Entry fileEntry : files.entrySet()) { - ZipEntry file = new ZipEntry(fileEntry.getKey().toString()); - outputStream.putNextEntry(file); - outputStream.write(fileEntry.getValue()); - outputStream.closeEntry(); - } - } - } - - } - -} diff --git a/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java b/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java deleted file mode 100644 index 83bc0b5..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java +++ /dev/null @@ -1,31 +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. - */ -package org.pf4j.plugin; - -import org.pf4j.Extension; - -/** - * @author Mario Franco - */ -@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 deleted file mode 100644 index d29a7ab..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java +++ /dev/null @@ -1,27 +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. - */ -package org.pf4j.plugin; - -import org.pf4j.ExtensionPoint; - -/** - * @author Mario Franco - */ -public interface TestExtensionPoint extends ExtensionPoint { - - String saySomething(); - -} diff --git a/pf4j/src/test/java/org/pf4j/plugin/TestPlugin.java b/pf4j/src/test/java/org/pf4j/plugin/TestPlugin.java deleted file mode 100644 index f094808..0000000 --- a/pf4j/src/test/java/org/pf4j/plugin/TestPlugin.java +++ /dev/null @@ -1,30 +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. - */ -package org.pf4j.plugin; - -import org.pf4j.Plugin; -import org.pf4j.PluginWrapper; - -/** - * @author Mario Franco - */ -public class TestPlugin extends Plugin { - - public TestPlugin(PluginWrapper wrapper) { - super(wrapper); - } - -} diff --git a/pf4j/src/test/java/org/pf4j/test/AnotherFailTestPlugin.java b/pf4j/src/test/java/org/pf4j/test/AnotherFailTestPlugin.java new file mode 100644 index 0000000..d97b32c --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/AnotherFailTestPlugin.java @@ -0,0 +1,32 @@ +/* + * 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.test; + +import org.pf4j.Plugin; + +/** + * A wrong {@link org.pf4j.Plugin}. + * It's wrong because it doesn't contain a constructor with one parameter ({@link org.pf4j.PluginWrapper} as parameter type). + * + * @author Mario Franco + */ +public class AnotherFailTestPlugin extends Plugin { + + public AnotherFailTestPlugin() { + super(null); + } + +} diff --git a/pf4j/src/test/java/org/pf4j/test/ClassDataProvider.java b/pf4j/src/test/java/org/pf4j/test/ClassDataProvider.java new file mode 100644 index 0000000..cc5a984 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/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.test; + +/** + * 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/test/DefaultClassDataProvider.java b/pf4j/src/test/java/org/pf4j/test/DefaultClassDataProvider.java new file mode 100644 index 0000000..6a203aa --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/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.test; + +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/test/FailTestExtension.java b/pf4j/src/test/java/org/pf4j/test/FailTestExtension.java new file mode 100644 index 0000000..1ce2aa8 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/FailTestExtension.java @@ -0,0 +1,37 @@ +/* + * 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.test; + +import org.pf4j.Extension; + +/** + * A wrong {@link org.pf4j.Extension}. + * It's wrong because it doesn't contain a constructor with empty parameters (or only the default constructor). + * + * @author Mario Franco + */ +@Extension +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/test/FailTestPlugin.java b/pf4j/src/test/java/org/pf4j/test/FailTestPlugin.java new file mode 100644 index 0000000..3a1824f --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/FailTestPlugin.java @@ -0,0 +1,26 @@ +/* + * 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.test; + +/** + * A wrong {@link org.pf4j.Plugin}. + * It's wrong because it doesn't extends {@link org.pf4j.Plugin}. + * + * @author Mario Franco + */ +public class FailTestPlugin { + +} diff --git a/pf4j/src/test/java/org/pf4j/test/PluginJar.java b/pf4j/src/test/java/org/pf4j/test/PluginJar.java new file mode 100644 index 0000000..034b10f --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/PluginJar.java @@ -0,0 +1,199 @@ +/* + * 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.test; + +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}. + * + * @author Decebal Suiu + */ +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; + } + + public Path path() { + return path; + } + + public File file() { + return path.toFile(); + } + + public String pluginClass() { + return pluginClass; + } + + public String pluginId() { + return pluginId; + } + + public String pluginVersion() { + return pluginVersion; + } + + public static Manifest createManifest(Map map) { + Manifest manifest = new Manifest(); + Attributes attributes = manifest.getMainAttributes(); + attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0"); + for (Map.Entry entry : map.entrySet()) { + attributes.put(new Attributes.Name(entry.getKey()), entry.getValue()); + } + + return manifest; + } + + public static class Builder { + + private final Path path; + private final String pluginId; + + 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; + this.pluginId = pluginId; + } + + public Builder pluginClass(String pluginClass) { + this.pluginClass = pluginClass; + + return this; + } + + public Builder pluginVersion(String pluginVersion) { + this.pluginVersion = pluginVersion; + + return this; + } + + /** + * Add extra attributes to the {@code manifest} file. + * As possible attribute name please see {@link ManifestPluginDescriptorFinder}. + */ + public Builder manifestAttributes(Map manifestAttributes) { + this.manifestAttributes.putAll(manifestAttributes); + + return this; + } + + /** + * Add extra attribute to the {@code manifest} file. + * As possible attribute name please see {@link ManifestPluginDescriptorFinder}. + */ + public Builder manifestAttribute(String name, String value) { + manifestAttributes.put(name, value); + + return this; + } + + 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 { + 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(); + } + } + } + + return new PluginJar(this); + } + + private Manifest createManifest() { + Map map = new LinkedHashMap<>(); + map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, pluginId); + map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); + if (pluginClass != null) { + map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); + } + if (manifestAttributes != null) { + map.putAll(manifestAttributes); + } + + return PluginJar.createManifest(map); + } + + private byte[] extensionsAsByteArray() throws IOException { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + PrintWriter writer = new PrintWriter(outputStream); + for (String extension : extensions) { + writer.println(extension); + } + writer.flush(); + + return outputStream.toByteArray(); + } + } + + } + +} diff --git a/pf4j/src/test/java/org/pf4j/test/PluginZip.java b/pf4j/src/test/java/org/pf4j/test/PluginZip.java new file mode 100644 index 0000000..5dd2291 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/PluginZip.java @@ -0,0 +1,189 @@ +/* + * 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.test; + +import org.pf4j.PropertiesPluginDescriptorFinder; + +import java.io.File; +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; +import java.util.zip.ZipOutputStream; + +/** + * 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 + */ +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; + } + + public Path path() { + return path; + } + + public File file() { + return path.toFile(); + } + + public String pluginId() { + return pluginId; + } + + public String pluginClass() { + return pluginClass; + } + + public String pluginVersion() { + return pluginVersion; + } + + public Path unzippedPath() { + Path path = path(); + String fileName = path.getFileName().toString(); + + return path.getParent().resolve(fileName.substring(0, fileName.length() - 4)); // without ".zip" suffix + } + + public static Properties createProperties(Map map) { + Properties properties = new Properties(); + properties.putAll(map); + + return properties; + } + + public static class Builder { + + private final Path path; + private final String pluginId; + + private String pluginClass; + private String pluginVersion; + private Map properties = new LinkedHashMap<>(); + private Map files = new LinkedHashMap<>(); + + public Builder(Path path, String pluginId) { + this.path = path; + this.pluginId = pluginId; + } + + public Builder pluginClass(String pluginClass) { + this.pluginClass = pluginClass; + + return this; + } + + public Builder pluginVersion(String pluginVersion) { + this.pluginVersion = pluginVersion; + + return this; + } + + /** + * Add extra properties to the {@code properties} file. + * As possible attribute name please see {@link PropertiesPluginDescriptorFinder}. + */ + public Builder properties(Map properties) { + this.properties.putAll(properties); + + return this; + } + + /** + * Add extra property to the {@code properties} file. + * As possible property name please see {@link PropertiesPluginDescriptorFinder}. + */ + public Builder property(String name, String value) { + properties.put(name, value); + + return this; + } + + /** + * Adds a file to the archive. + * + * @param path the relative path of the file + * @param content the content of the file + */ + public Builder addFile(Path path, byte[] content) { + files.put(path, content.clone()); + + return this; + } + + /** + * Adds a file to the archive. + * + * @param path the relative path of the file + * @param content the content of the file + */ + public Builder addFile(Path path, String content) { + files.put(path, content.getBytes()); + + return this; + } + + public PluginZip build() throws IOException { + createPropertiesFile(); + + return new PluginZip(this); + } + + protected void createPropertiesFile() throws IOException { + Map map = new LinkedHashMap<>(); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, pluginId); + map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, pluginVersion); + if (pluginClass != null) { + map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, pluginClass); + } + if (properties != null) { + map.putAll(properties); + } + + try (ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(path.toFile()))) { + ZipEntry propertiesFile = new ZipEntry(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME); + outputStream.putNextEntry(propertiesFile); + createProperties(map).store(outputStream, ""); + outputStream.closeEntry(); + + for (Map.Entry fileEntry : files.entrySet()) { + ZipEntry file = new ZipEntry(fileEntry.getKey().toString()); + outputStream.putNextEntry(file); + outputStream.write(fileEntry.getValue()); + outputStream.closeEntry(); + } + } + } + + } + +} diff --git a/pf4j/src/test/java/org/pf4j/test/TestExtension.java b/pf4j/src/test/java/org/pf4j/test/TestExtension.java new file mode 100644 index 0000000..ec67b14 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/TestExtension.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.test; + +import org.pf4j.Extension; + +/** + * A simple {@link Extension}. It implements {@link TestExtensionPoint}. + * + * @author Mario Franco + */ +@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/test/TestExtensionPoint.java b/pf4j/src/test/java/org/pf4j/test/TestExtensionPoint.java new file mode 100644 index 0000000..3849c92 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/TestExtensionPoint.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.test; + +import org.pf4j.ExtensionPoint; + +/** + * A simple {@link ExtensionPoint} that contains one method ({@link #saySomething()}). + * + * @author Mario Franco + */ +public interface TestExtensionPoint extends ExtensionPoint { + + String saySomething(); + +} diff --git a/pf4j/src/test/java/org/pf4j/test/TestPlugin.java b/pf4j/src/test/java/org/pf4j/test/TestPlugin.java new file mode 100644 index 0000000..bab85b3 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/TestPlugin.java @@ -0,0 +1,35 @@ +/* + * 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.test; + +import org.pf4j.Plugin; +import org.pf4j.PluginWrapper; + +/** + * A simple {@link Plugin}. + * + * In real applications you don't need to create a plugin like this if you are not interested in lifecycle events. + * {@codes PF4J} will automatically create a plugin similar to this (empty / dummy) if no class plugin is specified. + * + * @author Mario Franco + */ +public class TestPlugin extends Plugin { + + public TestPlugin(PluginWrapper wrapper) { + super(wrapper); + } + +} diff --git a/pf4j/src/test/java/org/pf4j/test/package-info.java b/pf4j/src/test/java/org/pf4j/test/package-info.java new file mode 100644 index 0000000..bdd5723 --- /dev/null +++ b/pf4j/src/test/java/org/pf4j/test/package-info.java @@ -0,0 +1,6 @@ +/** + * Classes used to test different aspects of PF4J (plugins, extensions points, extensions). + * + * @author Decebal Suiu + */ +package org.pf4j.test; diff --git a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java index 7bf06c6..050b3f1 100644 --- a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java +++ b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java @@ -17,7 +17,7 @@ package org.pf4j.util; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.pf4j.plugin.PluginZip; +import org.pf4j.test.PluginZip; import java.nio.file.Files; import java.nio.file.Path;