</manifestEntries>
</archive>
</configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ <configuration>
+ <includes>
+ <inculde>org/pf4j/test/*</inculde>
+ </includes>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
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;
Map<String, Set<String>> entries = new LinkedHashMap<>();
Set<String> 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;
Map<String, Set<String>> entries = new LinkedHashMap<>();
Set<String> 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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
private PluginClassLoader parentLastPluginClassLoader;
private PluginClassLoader parentFirstPluginClassLoader;
-
+
private PluginClassLoader parentLastPluginDependencyClassLoader;
private PluginClassLoader parentFirstPluginDependencyClassLoader;
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())
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);
parentFirstPluginDependencyClassLoader.addFile(jar);
}
}
-
+
pluginDescriptor = new DefaultPluginDescriptor();
pluginDescriptor.setPluginId("myPlugin");
pluginDescriptor.setPluginVersion("1.2.3");
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);
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");
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");
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");
Enumeration<URL> resources = parentFirstPluginClassLoader.getResources("META-INF/dependency-file");
assertNumberOfResourcesAndFirstLineOfFirstElement(1, "dependency", resources);
}
-
+
@Test
void parentLastGetResourcesExistsOnlyInPlugin() throws IOException, URISyntaxException {
Enumeration<URL> resources = parentLastPluginClassLoader.getResources("META-INF/plugin-file");
Enumeration<URL> resources = parentFirstPluginClassLoader.getResources("META-INF/file-in-both-parent-and-plugin");
assertNumberOfResourcesAndFirstLineOfFirstElement(2, "parent", resources);
}
-
+
@Test
void parentLastGetResourcesExistsInParentAndDependencyAndPlugin() throws URISyntaxException, IOException {
Enumeration<URL> resources = parentLastPluginClassLoader.getResources("META-INF/file-in-both-parent-and-dependency-and-plugin");
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);
}
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;
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;
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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:
- * <ul>
- * <li>Class path - the class is already loaded by the class loader</li>
- * <li>String - the string (the source code) is compiled dynamically via {@link javax.tools.JavaCompiler}</>
- * <li>Generate the source code programmatically using something like {@code https://github.com/square/javapoet}</li>
- * </ul>
- *
- * @author Decebal Suiu
- */
-public interface ClassDataProvider {
-
- byte[] getClassData(String className);
-
-}
+++ /dev/null
-/*
- * 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);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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";
- }
-
-}
+++ /dev/null
-/*
- * 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 {
-
-}
+++ /dev/null
-/*
- * 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<String, String> map) {
- Manifest manifest = new Manifest();
- Attributes attributes = manifest.getMainAttributes();
- attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
- for (Map.Entry<String, String> 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<String, String> manifestAttributes = new LinkedHashMap<>();
- private Set<String> 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<String, String> 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<String, String> 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();
- }
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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<String, String> 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<String, String> properties = new LinkedHashMap<>();
- private Map<Path, byte[]> 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<String, String> 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<String, String> 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<Path, byte[]> fileEntry : files.entrySet()) {
- ZipEntry file = new ZipEntry(fileEntry.getKey().toString());
- outputStream.putNextEntry(file);
- outputStream.write(fileEntry.getValue());
- outputStream.closeEntry();
- }
- }
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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";
- }
-
-}
+++ /dev/null
-/*
- * 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();
-
-}
+++ /dev/null
-/*
- * 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);
- }
-
-}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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:
+ * <ul>
+ * <li>Class path - the class is already loaded by the class loader</li>
+ * <li>String - the string (the source code) is compiled dynamically via {@link javax.tools.JavaCompiler}</>
+ * <li>Generate the source code programmatically using something like {@code https://github.com/square/javapoet}</li>
+ * </ul>
+ *
+ * @author Decebal Suiu
+ */
+public interface ClassDataProvider {
+
+ byte[] getClassData(String className);
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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";
+ }
+
+}
--- /dev/null
+/*
+ * 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 {
+
+}
--- /dev/null
+/*
+ * 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<String, String> map) {
+ Manifest manifest = new Manifest();
+ Attributes attributes = manifest.getMainAttributes();
+ attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
+ for (Map.Entry<String, String> 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<String, String> manifestAttributes = new LinkedHashMap<>();
+ private Set<String> 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<String, String> 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<String, String> 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();
+ }
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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<String, String> 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<String, String> properties = new LinkedHashMap<>();
+ private Map<Path, byte[]> 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<String, String> 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<String, String> 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<Path, byte[]> fileEntry : files.entrySet()) {
+ ZipEntry file = new ZipEntry(fileEntry.getKey().toString());
+ outputStream.putNextEntry(file);
+ outputStream.write(fileEntry.getValue());
+ outputStream.closeEntry();
+ }
+ }
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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";
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/**
+ * Classes used to test different aspects of PF4J (plugins, extensions points, extensions).
+ *
+ * @author Decebal Suiu
+ */
+package org.pf4j.test;
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;