summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml4
-rw-r--r--demo/api/pom.xml4
-rw-r--r--demo/app/pom.xml4
-rw-r--r--demo/app/src/main/java/org/pf4j/demo/Boot.java4
-rw-r--r--demo/plugins/plugin1/pom.xml4
-rw-r--r--demo/plugins/plugin2/pom.xml4
-rw-r--r--demo/plugins/pom.xml13
-rw-r--r--demo/pom.xml4
-rwxr-xr-xmaven-archetypes/quickstart/pom.xml68
-rw-r--r--maven-archetypes/quickstart/src/main/resources/META-INF/maven/archetype-metadata.xml86
-rw-r--r--maven-archetypes/quickstart/src/main/resources/archetype-resources/app/pom.xml86
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/assembly/assembly.xml30
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Boot.java102
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Greeting.java9
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/WhazzupGreeting.java13
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/resources/log4j.properties20
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/disabled.txt6
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/enabled.txt6
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/plugin.properties5
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/pom.xml24
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/src/main/java/hello/HelloPlugin.java37
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/pom.xml86
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/plugin.properties5
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/pom.xml32
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/src/main/java/welcome/WelcomePlugin.java41
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml48
-rwxr-xr-xmaven-archetypes/quickstart/src/main/resources/archetype-resources/run.sh23
-rw-r--r--pf4j/pom.xml49
-rw-r--r--pf4j/src/main/java/module-info.java47
-rw-r--r--pf4j/src/main/java/org/pf4j/AbstractPluginManager.java193
-rw-r--r--pf4j/src/main/java/org/pf4j/BasePluginLoader.java88
-rw-r--r--pf4j/src/main/java/org/pf4j/BasePluginRepository.java19
-rw-r--r--pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java4
-rw-r--r--pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java16
-rw-r--r--pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java22
-rw-r--r--pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java10
-rw-r--r--pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java9
-rw-r--r--pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java59
-rw-r--r--pf4j/src/main/java/org/pf4j/DefaultPluginManager.java46
-rw-r--r--pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java44
-rw-r--r--pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java32
-rw-r--r--pf4j/src/main/java/org/pf4j/DependencyResolver.java6
-rw-r--r--pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java8
-rw-r--r--pf4j/src/main/java/org/pf4j/DevelopmentPluginLoader.java29
-rw-r--r--pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java55
-rw-r--r--pf4j/src/main/java/org/pf4j/ExtensionFactory.java2
-rw-r--r--pf4j/src/main/java/org/pf4j/JarPluginManager.java56
-rw-r--r--pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java24
-rw-r--r--pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java39
-rw-r--r--pf4j/src/main/java/org/pf4j/Plugin.java6
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java2
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginClasspath.java17
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java5
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginManager.java31
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginRepository.java5
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginRuntimeException.java (renamed from pf4j/src/main/java/org/pf4j/PluginException.java)16
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginStatusProvider.java8
-rw-r--r--pf4j/src/main/java/org/pf4j/PluginWrapper.java11
-rw-r--r--pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java41
-rw-r--r--pf4j/src/main/java/org/pf4j/RuntimeMode.java2
-rw-r--r--pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java7
-rw-r--r--pf4j/src/main/java/org/pf4j/ZipPluginManager.java49
-rw-r--r--pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java6
-rw-r--r--pf4j/src/main/java/org/pf4j/util/AndFileFilter.java12
-rw-r--r--pf4j/src/main/java/org/pf4j/util/DirectedGraph.java10
-rw-r--r--pf4j/src/main/java/org/pf4j/util/FileUtils.java11
-rw-r--r--pf4j/src/main/java/org/pf4j/util/OrFileFilter.java12
-rw-r--r--pf4j/src/main/java/org/pf4j/util/Unzip.java6
-rw-r--r--pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java12
-rw-r--r--pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java49
-rw-r--r--pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java82
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java30
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java8
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java46
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java66
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java51
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java18
-rw-r--r--pf4j/src/test/java/org/pf4j/DependencyResolverTest.java10
-rw-r--r--pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java61
-rw-r--r--pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java6
-rw-r--r--pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java96
-rw-r--r--pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java58
-rw-r--r--pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java73
-rw-r--r--pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java4
-rw-r--r--pf4j/src/test/java/org/pf4j/LoadPluginsTest.java83
-rw-r--r--pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java218
-rw-r--r--pf4j/src/test/java/org/pf4j/PluginDependencyTest.java19
-rw-r--r--pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java193
-rw-r--r--pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java5
-rw-r--r--pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java33
-rw-r--r--pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java55
-rw-r--r--pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java5
-rw-r--r--pf4j/src/test/java/org/pf4j/plugin/PluginJar.java200
-rw-r--r--pf4j/src/test/java/org/pf4j/plugin/PluginZip.java88
-rw-r--r--pf4j/src/test/java/org/pf4j/plugin/TestExtension.java5
-rw-r--r--pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java2
-rw-r--r--pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java15
-rw-r--r--pf4j/src/test/java/org/pf4j/util/DirectedGraphTest.java98
-rw-r--r--pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java18
-rw-r--r--pom.xml10
100 files changed, 2659 insertions, 940 deletions
diff --git a/.travis.yml b/.travis.yml
index 90b2770..b2e4fb7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,5 @@
language: java
jdk:
- - openjdk7
-# JDK7 is not supported anymore; https://github.com/travis-ci/travis-ci/issues/7884#issuecomment-308451879
-# - oraclejdk7
- - oraclejdk8
- openjdk11
after_success:
- mvn clean cobertura:cobertura coveralls:report
diff --git a/demo/api/pom.xml b/demo/api/pom.xml
index 723e602..9a5f33f 100644
--- a/demo/api/pom.xml
+++ b/demo/api/pom.xml
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-parent</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-api</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Demo Api</name>
diff --git a/demo/app/pom.xml b/demo/app/pom.xml
index 3335fbe..4cb624c 100644
--- a/demo/app/pom.xml
+++ b/demo/app/pom.xml
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-parent</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-app</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Demo App</name>
diff --git a/demo/app/src/main/java/org/pf4j/demo/Boot.java b/demo/app/src/main/java/org/pf4j/demo/Boot.java
index 562f8f8..066a207 100644
--- a/demo/app/src/main/java/org/pf4j/demo/Boot.java
+++ b/demo/app/src/main/java/org/pf4j/demo/Boot.java
@@ -73,8 +73,8 @@ public class Boot {
}
System.out.println("Extension classes by classpath:");
- List<Class<Greeting>> greetingsClasses = pluginManager.getExtensionClasses(Greeting.class);
- for (Class<Greeting> greeting : greetingsClasses) {
+ List<Class<? extends Greeting>> greetingsClasses = pluginManager.getExtensionClasses(Greeting.class);
+ for (Class<? extends Greeting> greeting : greetingsClasses) {
System.out.println(" Class: " + greeting.getCanonicalName());
}
diff --git a/demo/plugins/plugin1/pom.xml b/demo/plugins/plugin1/pom.xml
index 4695489..51e4ff9 100644
--- a/demo/plugins/plugin1/pom.xml
+++ b/demo/plugins/plugin1/pom.xml
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-plugins</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-plugin1</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Demo Plugin #1</name>
diff --git a/demo/plugins/plugin2/pom.xml b/demo/plugins/plugin2/pom.xml
index 40e19b1..db67c4b 100644
--- a/demo/plugins/plugin2/pom.xml
+++ b/demo/plugins/plugin2/pom.xml
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-plugins</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-plugin2</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Demo Plugin #2</name>
diff --git a/demo/plugins/pom.xml b/demo/plugins/pom.xml
index 4460964..589951a 100644
--- a/demo/plugins/pom.xml
+++ b/demo/plugins/pom.xml
@@ -4,19 +4,18 @@
<parent>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-parent</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j-demo-plugins</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Demo Plugins Parent</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <java.version>1.7</java.version>
<!-- Override below properties in each plugin's pom.xml -->
<plugin.id />
@@ -30,14 +29,6 @@
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>${java.version}</source>
- <target>${java.version}</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
diff --git a/demo/pom.xml b/demo/pom.xml
index 2d046b5..fc182e5 100644
--- a/demo/pom.xml
+++ b/demo/pom.xml
@@ -4,13 +4,13 @@
<parent>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-parent</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.pf4j.demo</groupId>
<artifactId>pf4j-demo-parent</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Demo Parent</name>
diff --git a/maven-archetypes/quickstart/pom.xml b/maven-archetypes/quickstart/pom.xml
new file mode 100755
index 0000000..783bed1
--- /dev/null
+++ b/maven-archetypes/quickstart/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.pf4j</groupId>
+ <artifactId>pf4j-parent</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>pf4j-quickstart</artifactId>
+ <packaging>maven-archetype</packaging>
+ <name>Quickstart Archetype</name>
+
+ <build>
+ <!-- http://stackoverflow.com/questions/7223031/how-to-embed-archetype-project-version-in-maven-archetype -->
+ <resources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>archetype-resources/**/pom.xml</include>
+ </includes>
+ </resource>
+
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/resources</directory>
+ <excludes>
+ <exclude>archetype-resources/**/pom.xml</exclude>
+ </excludes>
+ </resource>
+ </resources>
+
+ <extensions>
+ <extension>
+ <groupId>org.apache.maven.archetype</groupId>
+ <artifactId>archetype-packaging</artifactId>
+ <version>2.3</version>
+ </extension>
+ </extensions>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-archetype-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+
+ <!-- http://stackoverflow.com/questions/7223031/how-to-embed-archetype-project-version-in-maven-archetype -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <delimiters>
+ <delimiter>{{*}}</delimiter>
+ </delimiters>
+ <useDefaultDelimiters>false</useDefaultDelimiters>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+</project>
diff --git a/maven-archetypes/quickstart/src/main/resources/META-INF/maven/archetype-metadata.xml b/maven-archetypes/quickstart/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..a6f40bd
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archetype-descriptor name="quickstart">
+
+ <fileSets>
+ <fileSet encoding="UTF-8">
+ <directory></directory>
+ <includes>
+ <include>run.sh</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+
+ <modules>
+ <module id="${rootArtifactId}-app" dir="app" name="${rootArtifactId}-app">
+ <fileSets>
+ <fileSet filtered="true" packaged="true" encoding="UTF-8">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.properties</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory>src/main/assembly</directory>
+ <includes>
+ <include>**/*.xml</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ </module>
+
+ <module id="${rootArtifactId}-plugins" dir="plugins" name="${rootArtifactId}-plugins">
+ <fileSets>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory></directory>
+ <includes>
+ <include>enabled.txt</include>
+ <include>disabled.txt</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+
+ <modules>
+ <module id="hello-plugin" dir="hello" name="hello-plugin">
+ <fileSets>
+ <fileSet filtered="true" packaged="true" encoding="UTF-8">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory></directory>
+ <includes>
+ <include>plugin.properties</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ </module>
+
+ <module id="welcome-plugin" dir="welcome" name="welcome-plugin">
+ <fileSets>
+ <fileSet filtered="true" packaged="true" encoding="UTF-8">
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*.java</include>
+ </includes>
+ </fileSet>
+ <fileSet filtered="true" encoding="UTF-8">
+ <directory></directory>
+ <includes>
+ <include>plugin.properties</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ </module>
+ </modules>
+ </module>
+ </modules>
+
+</archetype-descriptor>
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/pom.xml
new file mode 100644
index 0000000..986c0a3
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+ <packaging>jar</packaging>
+ <name>App</name>
+
+ <properties>
+ <main.class>${package}.Boot</main.class>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.3</version>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/assembly.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.3.1</version>
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ <classpathPrefix>lib/</classpathPrefix>
+ <mainClass>${main.class}</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.pf4j</groupId>
+ <artifactId>pf4j</artifactId>
+ <version>${pf4j.version}</version>
+ </dependency>
+
+ <!-- Logs -->
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.16</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.4</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/assembly/assembly.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/assembly/assembly.xml
new file mode 100755
index 0000000..b88a245
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/assembly/assembly.xml
@@ -0,0 +1,30 @@
+<assembly>
+ <id>app</id>
+ <formats>
+ <format>dir</format>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <useProjectArtifact>false</useProjectArtifact>
+ <outputDirectory>lib</outputDirectory>
+ <includes>
+ <include>*:jar:*</include>
+ </includes>
+ </dependencySet>
+ </dependencySets>
+ <fileSets>
+ <fileSet>
+ <directory>${project.build.directory}</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ <excludes>
+ <exclude>*-javadoc.jar</exclude>
+ <exclude>*-sources.jar</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Boot.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Boot.java
new file mode 100755
index 0000000..2853b08
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Boot.java
@@ -0,0 +1,102 @@
+package ${package};
+
+import org.apache.commons.lang.StringUtils;
+import org.pf4j.DefaultPluginManager;
+import org.pf4j.ExtensionFinder;
+import org.pf4j.PluginManager;
+import org.pf4j.PluginWrapper;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A boot class that start the application.
+ */
+public class Boot {
+
+ public static void main(String[] args) {
+ // create the plugin manager
+ PluginManager pluginManager = new DefaultPluginManager();
+
+ // load the plugins
+ pluginManager.loadPlugins();
+
+ // enable a disabled plugin
+// pluginManager.enablePlugin("welcome-plugin");
+
+ // start (active/resolved) the plugins
+ pluginManager.startPlugins();
+
+ // retrieves the extensions for Greeting extension point
+ List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);
+ System.out.println(String.format("Found %d extensions for extension point '%s'", greetings.size(), Greeting.class.getName()));
+ for (Greeting greeting : greetings) {
+ System.out.println(">>> " + greeting.getGreeting());
+ }
+
+ // print extensions from classpath (non plugin)
+ System.out.println("Extensions added by classpath:");
+ Set<String> extensionClassNames = pluginManager.getExtensionClassNames(null);
+ for (String extension : extensionClassNames) {
+ System.out.println(" " + extension);
+ }
+
+ System.out.println("Extension classes by classpath:");
+ List<Class<? extends Greeting>> greetingsClasses = pluginManager.getExtensionClasses(Greeting.class);
+ for (Class<? extends Greeting> greeting : greetingsClasses) {
+ System.out.println(" Class: " + greeting.getCanonicalName());
+ }
+
+ // print extensions ids for each started plugin
+ List<PluginWrapper> startedPlugins = pluginManager.getStartedPlugins();
+ for (PluginWrapper plugin : startedPlugins) {
+ String pluginId = plugin.getDescriptor().getPluginId();
+ System.out.println(String.format("Extensions added by plugin '%s':", pluginId));
+ extensionClassNames = pluginManager.getExtensionClassNames(pluginId);
+ for (String extension : extensionClassNames) {
+ System.out.println(" " + extension);
+ }
+ }
+
+ // print extensions instances for Greeting extension point for each started plugin
+ for (PluginWrapper plugin : startedPlugins) {
+ String pluginId = plugin.getDescriptor().getPluginId();
+ System.out.println(String.format("Extensions instances added by plugin '%s' for extension point '%s':", pluginId, Greeting.class.getName()));
+ List<Greeting> extensions = pluginManager.getExtensions(Greeting.class, pluginId);
+ for (Object extension : extensions) {
+ System.out.println(" " + extension);
+ }
+ }
+
+ // print extensions instances from classpath (non plugin)
+ System.out.println("Extensions instances added by classpath:");
+ List extensions = pluginManager.getExtensions((String) null);
+ for (Object extension : extensions) {
+ System.out.println(" " + extension);
+ }
+
+ // print extensions instances for each started plugin
+ for (PluginWrapper plugin : startedPlugins) {
+ String pluginId = plugin.getDescriptor().getPluginId();
+ System.out.println(String.format("Extensions instances added by plugin '%s':", pluginId));
+ extensions = pluginManager.getExtensions(pluginId);
+ for (Object extension : extensions) {
+ System.out.println(" " + extension);
+ }
+ }
+
+ // stop the plugins
+ pluginManager.stopPlugins();
+ /*
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+
+ @Override
+ public void run() {
+ pluginManager.stopPlugins();
+ }
+
+ });
+ */
+ }
+
+}
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Greeting.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Greeting.java
new file mode 100755
index 0000000..d64d5fe
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/Greeting.java
@@ -0,0 +1,9 @@
+package ${package};
+
+import org.pf4j.ExtensionPoint;
+
+public interface Greeting extends ExtensionPoint {
+
+ String getGreeting();
+
+}
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/WhazzupGreeting.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/WhazzupGreeting.java
new file mode 100755
index 0000000..bb747f5
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/java/WhazzupGreeting.java
@@ -0,0 +1,13 @@
+package ${package};
+
+import org.pf4j.Extension;
+
+@Extension
+public class WhazzupGreeting implements Greeting {
+
+ @Override
+ public String getGreeting() {
+ return "Whazzup";
+ }
+
+}
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/resources/log4j.properties b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/resources/log4j.properties
new file mode 100755
index 0000000..a05d9eb
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/app/src/main/resources/log4j.properties
@@ -0,0 +1,20 @@
+log4j.rootLogger=DEBUG, Console
+
+#
+# PF4J log
+#
+log4j.logger.org.pf4j=DEBUG, Console
+# !!! Put the bellow classes on level TRACE when you are in trouble
+log4j.logger.org.pf4j.PluginClassLoader=DEBUG, Console
+log4j.logger.org.pf4j.AbstractExtensionFinder=DEBUG, Console
+log4j.additivity.org.pf4j=false
+log4j.additivity.org.pf4j.PluginClassLoader=false
+log4j.additivity.org.pf4j.AbstractExtensionFinder=false
+
+#
+# Appenders
+#
+log4j.appender.Console=org.apache.log4j.ConsoleAppender
+log4j.appender.Console.layout=org.apache.log4j.PatternLayout
+#log4j.appender.Console.layout.conversionPattern=%-5p - %-32.32c{1} - %m\n
+log4j.appender.Console.layout.ConversionPattern=%d %p %c - %m%n
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/disabled.txt b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/disabled.txt
new file mode 100755
index 0000000..45f1801
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/disabled.txt
@@ -0,0 +1,6 @@
+########################################
+# - load all plugins except these
+# - add one plugin id on each line
+# - put this file in plugins folder
+########################################
+#welcome-plugin
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/enabled.txt b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/enabled.txt
new file mode 100755
index 0000000..3d76b2f
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/enabled.txt
@@ -0,0 +1,6 @@
+########################################
+# - load only these plugins
+# - add one plugin id on each line
+# - put this file in plugins folder
+########################################
+#welcome-plugin
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/plugin.properties b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/plugin.properties
new file mode 100755
index 0000000..9ed49b1
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/plugin.properties
@@ -0,0 +1,5 @@
+plugin.id=hello-plugin
+plugin.class=${package}.hello.HelloPlugin
+plugin.version=${version}
+plugin.provider=
+plugin.dependencies=
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/pom.xml
new file mode 100755
index 0000000..10e8262
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-plugins</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>hello-plugin</artifactId>
+ <version>${version}</version>
+ <packaging>jar</packaging>
+ <name>Hello Plugin</name>
+
+ <properties>
+ <plugin.id>hello-plugin</plugin.id>
+ <plugin.class>${package}.hello.HelloPlugin</plugin.class>
+ <plugin.version>${version}</plugin.version>
+ <plugin.provider/>
+ <plugin.dependencies/>
+ </properties>
+
+</project>
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/src/main/java/hello/HelloPlugin.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/src/main/java/hello/HelloPlugin.java
new file mode 100755
index 0000000..48604d6
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/hello/src/main/java/hello/HelloPlugin.java
@@ -0,0 +1,37 @@
+package ${package}.hello;
+
+import org.pf4j.Extension;
+import org.pf4j.Plugin;
+import org.pf4j.PluginWrapper;
+import ${package}.Greeting;
+
+/**
+ * A very simple plugin.
+ */
+public class HelloPlugin extends Plugin {
+
+ public HelloPlugin(PluginWrapper wrapper) {
+ super(wrapper);
+ }
+
+ @Override
+ public void start() {
+ System.out.println("HelloPlugin.start()");
+ }
+
+ @Override
+ public void stop() {
+ System.out.println("HelloPlugin.stop()");
+ }
+
+ @Extension(ordinal=1)
+ public static class HelloGreeting implements Greeting {
+
+ @Override
+ public String getGreeting() {
+ return "Hello";
+ }
+
+ }
+
+}
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/pom.xml
new file mode 100755
index 0000000..b144ca0
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+ <packaging>pom</packaging>
+ <name>Plugins Parent</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+ <!-- Override below properties in each plugin's pom.xml -->
+ <plugin.id></plugin.id>
+ <plugin.class></plugin.class>
+ <plugin.version></plugin.version>
+ <plugin.provider></plugin.provider>
+ <plugin.dependencies></plugin.dependencies>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>3.1.0</version>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <finalName>${project.artifactId}-${project.version}-all</finalName>
+ <appendAssemblyId>false</appendAssemblyId>
+ <attach>false</attach>
+ <archive>
+ <manifest>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+ </manifest>
+ <manifestEntries>
+ <Plugin-Id>${plugin.id}</Plugin-Id>
+ <Plugin-Version>${plugin.version}</Plugin-Version>
+ <Plugin-Provider>${plugin.provider}</Plugin-Provider>
+ <Plugin-Class>${plugin.class}</Plugin-Class>
+ <Plugin-Dependencies>${plugin.dependencies}</Plugin-Dependencies>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.pf4j</groupId>
+ <artifactId>pf4j</artifactId>
+ <version>${pf4j.version}</version>
+ <!-- !!! VERY IMPORTANT -->
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-app</artifactId>
+ <version>${version}</version>
+ <!-- !!! VERY IMPORTANT -->
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/plugin.properties b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/plugin.properties
new file mode 100755
index 0000000..80edaab
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/plugin.properties
@@ -0,0 +1,5 @@
+plugin.id=welcome-plugin
+plugin.class=${package}.welcome.WelcomePlugin
+plugin.version=${version}
+plugin.provider=
+plugin.dependencies=
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/pom.xml
new file mode 100755
index 0000000..9101abb
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>${groupId}</groupId>
+ <artifactId>${rootArtifactId}-plugins</artifactId>
+ <version>${version}</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>welcome-plugin</artifactId>
+ <version>${version}</version>
+ <packaging>jar</packaging>
+ <name>Welcom Plugin</name>
+
+ <properties>
+ <plugin.id>welcome-plugin</plugin.id>
+ <plugin.class>${package}.welcome.WelcomePlugin</plugin.class>
+ <plugin.version>${version}</plugin.version>
+ <plugin.provider/>
+ <plugin.dependencies/>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/src/main/java/welcome/WelcomePlugin.java b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/src/main/java/welcome/WelcomePlugin.java
new file mode 100755
index 0000000..a82d13c
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/plugins/welcome/src/main/java/welcome/WelcomePlugin.java
@@ -0,0 +1,41 @@
+package ${package}.welcome;
+
+import org.apache.commons.lang.StringUtils;
+
+import org.pf4j.PluginWrapper;
+import org.pf4j.RuntimeMode;
+import org.pf4j.Extension;
+import org.pf4j.Plugin;
+import ${package}.Greeting;
+
+public class WelcomePlugin extends Plugin {
+
+ public WelcomePlugin(PluginWrapper wrapper) {
+ super(wrapper);
+ }
+
+ @Override
+ public void start() {
+ System.out.println("WelcomePlugin.start()");
+ // for testing the development mode
+ if (RuntimeMode.DEVELOPMENT.equals(wrapper.getRuntimeMode())) {
+ System.out.println(StringUtils.upperCase("WelcomePlugin"));
+ }
+ }
+
+ @Override
+ public void stop() {
+ System.out.println("WelcomePlugin.stop()");
+ }
+
+ @Extension
+ public static class WelcomeGreeting implements Greeting {
+
+ @Override
+ public String getGreeting() {
+ return "Welcome";
+ }
+
+ }
+
+}
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml b/maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml
new file mode 100755
index 0000000..13ed127
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>${groupId}</groupId>
+ <artifactId>${artifactId}</artifactId>
+ <version>${version}</version>
+ <packaging>pom</packaging>
+ <name>PF4J Quickstart</name>
+
+ <repositories>
+ <repository>
+ <id>sonatype-nexus-snapshots</id>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <maven.compiler.release>8</maven.compiler.release>
+
+ <pf4j.version>{{project.version}}</pf4j.version>
+ <slf4j.version>1.7.7</slf4j.version>
+ </properties>
+
+ <build>
+ <resources>
+ <resource>
+ <filtering>false</filtering>
+ <directory>src/main/java</directory>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </resource>
+
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ </build>
+
+</project>
diff --git a/maven-archetypes/quickstart/src/main/resources/archetype-resources/run.sh b/maven-archetypes/quickstart/src/main/resources/archetype-resources/run.sh
new file mode 100755
index 0000000..6214823
--- /dev/null
+++ b/maven-archetypes/quickstart/src/main/resources/archetype-resources/run.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# create artifacts using Maven
+mvn clean package -DskipTests
+
+# create "dist" directory
+rm -fr dist
+mkdir -p dist/plugins
+
+# copy plugins to "dist" directory
+cp plugins/*/target/*-all.jar dist/plugins/
+cp plugins/enabled.txt dist/plugins/
+cp plugins/disabled.txt dist/plugins/
+
+cd dist
+
+# unzip app to "dist" directory
+jar xf ../app/target/*.zip
+
+# run app
+java -jar *.jar
+
+cd -
diff --git a/pf4j/pom.xml b/pf4j/pom.xml
index 061412d..c38eae8 100644
--- a/pf4j/pom.xml
+++ b/pf4j/pom.xml
@@ -4,12 +4,12 @@
<parent>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-parent</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pf4j</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>PF4J</name>
<description>Plugin Framework for Java</description>
@@ -22,6 +22,35 @@
<configuration>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
+ <executions>
+ <!-- compile everything for Java 8 except the module-info.java -->
+ <execution>
+ <id>default-compile</id>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <excludes>
+ <exclude>module-info.java</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+
+ <!-- compile module-info.java for Java 9+ -->
+ <execution>
+ <id>java9-compile</id>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <release>9</release>
+ <multiReleaseOutput>true</multiReleaseOutput>
+ <includes>
+ <include>module-info.java</include>
+ </includes>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -29,7 +58,7 @@
<configuration>
<archive>
<manifestEntries>
- <Automatic-Module-Name>org.pf4j</Automatic-Module-Name>
+ <Multi-Release>true</Multi-Release>
</manifestEntries>
</archive>
</configuration>
@@ -69,11 +98,12 @@
</dependency>
<dependency>
- <!-- An empty artifact, required while JUnit 4 is on the classpath to override its
- dependency on hamcrest.
+ <!--
+ An empty artifact, required while JUnit 4 is on the classpath to override its
+ dependency on hamcrest.
- See http://hamcrest.org/JavaHamcrest/distributables#upgrading-from-hamcrest-1x
- -->
+ See http://hamcrest.org/JavaHamcrest/distributables#upgrading-from-hamcrest-1x
+ -->
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>${hamcrest.version}</version>
@@ -81,11 +111,12 @@
</dependency>
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
+
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
diff --git a/pf4j/src/main/java/module-info.java b/pf4j/src/main/java/module-info.java
new file mode 100644
index 0000000..754b9b8
--- /dev/null
+++ b/pf4j/src/main/java/module-info.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Module descriptor for PF4J.
+ *
+ * @author Decebal Suiu
+ * @author Andreas Rudolph
+ */
+module org.pf4j {
+ requires java.base;
+
+ // provides javax.annotation
+ requires java.compiler;
+
+ // provided by the ASM library
+ requires org.objectweb.asm;
+
+ // The SLF4J library currently does not provide a module.
+ // Version 1.8 provides a module called "org.slf4j". But this version is
+ // currently in beta stage. Therefore I'm not sure, if we already like to
+ // use it.
+ requires slf4j.api;
+
+ // The java-semver library currently does not provide a module.
+ // Maybe we should send them a pull request, that at least they provide an
+ // automatic module name in their MANIFEST file.
+ requires java.semver;
+
+ // Maybe we should reconsider the package hierarchy, that only classes are
+ // exported, which are required by 3rd party developers.
+ exports org.pf4j;
+ exports org.pf4j.processor;
+}
diff --git a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
index c17fdab..6bd6170 100644
--- a/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
+++ b/pf4j/src/main/java/org/pf4j/AbstractPluginManager.java
@@ -15,6 +15,10 @@
*/
package org.pf4j;
+import org.pf4j.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.Closeable;
import java.io.IOException;
import java.nio.file.Files;
@@ -27,9 +31,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.pf4j.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* This class implements the boilerplate plugin code that any {@link PluginManager}
@@ -44,6 +45,12 @@ public abstract class AbstractPluginManager implements PluginManager {
private static final Logger log = LoggerFactory.getLogger(AbstractPluginManager.class);
+ public static final String PLUGINS_DIR_PROPERTY_NAME = "pf4j.pluginsDir";
+ public static final String MODE_PROPERTY_NAME = "pf4j.mode";
+
+ public static final String DEFAULT_PLUGINS_DIR = "plugins";
+ public static final String DEVELOPMENT_PLUGINS_DIR = "../plugins";
+
private Path pluginsRoot;
protected ExtensionFinder extensionFinder;
@@ -180,18 +187,12 @@ public abstract class AbstractPluginManager implements PluginManager {
log.debug("Loading plugin from '{}'", pluginPath);
- try {
- PluginWrapper pluginWrapper = loadPluginFromPath(pluginPath);
+ PluginWrapper pluginWrapper = loadPluginFromPath(pluginPath);
- // try to resolve the loaded plugin together with other possible plugins that depend on this plugin
- resolvePlugins();
+ // try to resolve the loaded plugin together with other possible plugins that depend on this plugin
+ resolvePlugins();
- return pluginWrapper.getDescriptor().getPluginId();
- } catch (PluginException e) {
- log.error(e.getMessage(), e);
- }
-
- return null;
+ return pluginWrapper.getDescriptor().getPluginId();
}
/**
@@ -221,7 +222,7 @@ public abstract class AbstractPluginManager implements PluginManager {
for (Path pluginPath : pluginPaths) {
try {
loadPluginFromPath(pluginPath);
- } catch (PluginException e) {
+ } catch (PluginRuntimeException e) {
log.error(e.getMessage(), e);
}
}
@@ -229,7 +230,7 @@ public abstract class AbstractPluginManager implements PluginManager {
// resolve plugins
try {
resolvePlugins();
- } catch (PluginException e) {
+ } catch (PluginRuntimeException e) {
log.error(e.getMessage(), e);
}
}
@@ -275,7 +276,7 @@ public abstract class AbstractPluginManager implements PluginManager {
try {
((Closeable) classLoader).close();
} catch (IOException e) {
- log.error("Cannot close classloader", e);
+ throw new PluginRuntimeException(e, "Cannot close classloader");
}
}
}
@@ -293,23 +294,24 @@ public abstract class AbstractPluginManager implements PluginManager {
checkPluginId(pluginId);
PluginWrapper pluginWrapper = getPlugin(pluginId);
+ // stop the plugin if it's started
PluginState pluginState = stopPlugin(pluginId);
if (PluginState.STARTED == pluginState) {
log.error("Failed to stop plugin '{}' on delete", pluginId);
return false;
}
+ // get an instance of plugin before the plugin is unloaded
+ // for reason see https://github.com/pf4j/pf4j/issues/309
+ Plugin plugin = pluginWrapper.getPlugin();
+
if (!unloadPlugin(pluginId)) {
log.error("Failed to unload plugin '{}' on delete", pluginId);
return false;
}
- try {
- pluginWrapper.getPlugin().delete();
- } catch (PluginException e) {
- log.error(e.getMessage(), e);
- return false;
- }
+ // notify the plugin as it's deleted
+ plugin.delete();
Path pluginPath = pluginWrapper.getPluginPath();
@@ -369,16 +371,12 @@ public abstract class AbstractPluginManager implements PluginManager {
startPlugin(dependency.getPluginId());
}
- try {
- log.info("Start plugin '{}'", getPluginLabel(pluginDescriptor));
- pluginWrapper.getPlugin().start();
- pluginWrapper.setPluginState(PluginState.STARTED);
- startedPlugins.add(pluginWrapper);
+ log.info("Start plugin '{}'", getPluginLabel(pluginDescriptor));
+ pluginWrapper.getPlugin().start();
+ pluginWrapper.setPluginState(PluginState.STARTED);
+ startedPlugins.add(pluginWrapper);
- firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
- } catch (PluginException e) {
- log.error(e.getMessage(), e);
- }
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
return pluginWrapper.getPluginState();
}
@@ -402,7 +400,7 @@ public abstract class AbstractPluginManager implements PluginManager {
itr.remove();
firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
- } catch (PluginException e) {
+ } catch (PluginRuntimeException e) {
log.error(e.getMessage(), e);
}
}
@@ -443,16 +441,12 @@ public abstract class AbstractPluginManager implements PluginManager {
}
}
- try {
- log.info("Stop plugin '{}'", getPluginLabel(pluginDescriptor));
- pluginWrapper.getPlugin().stop();
- pluginWrapper.setPluginState(PluginState.STOPPED);
- startedPlugins.remove(pluginWrapper);
+ log.info("Stop plugin '{}'", getPluginLabel(pluginDescriptor));
+ pluginWrapper.getPlugin().stop();
+ pluginWrapper.setPluginState(PluginState.STOPPED);
+ startedPlugins.remove(pluginWrapper);
- firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
- } catch (PluginException e) {
- log.error(e.getMessage(), e);
- }
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
return pluginWrapper.getPluginState();
}
@@ -480,10 +474,7 @@ public abstract class AbstractPluginManager implements PluginManager {
firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, PluginState.STOPPED));
- if (!pluginStatusProvider.disablePlugin(pluginId)) {
- return false;
- }
-
+ pluginStatusProvider.disablePlugin(pluginId);
log.info("Disabled plugin '{}'", getPluginLabel(pluginDescriptor));
return true;
@@ -509,9 +500,7 @@ public abstract class AbstractPluginManager implements PluginManager {
return true;
}
- if (!pluginStatusProvider.enablePlugin(pluginId)) {
- return false;
- }
+ pluginStatusProvider.enablePlugin(pluginId);
pluginWrapper.setPluginState(PluginState.CREATED);
@@ -539,55 +528,28 @@ public abstract class AbstractPluginManager implements PluginManager {
Class<?> c = extensionWrapper.getDescriptor().extensionClass;
extensionClasses.add(c);
}
+
return extensionClasses;
}
- @SuppressWarnings("unchecked")
@Override
- public <T> List<Class<T>> getExtensionClasses(Class<T> type) {
- List<ExtensionWrapper<T>> extensionsWrapper = extensionFinder.find(type);
- List<Class<T>> extensionClasses = new ArrayList<>(extensionsWrapper.size());
- for (ExtensionWrapper<T> extensionWrapper : extensionsWrapper) {
- Class<T> c = (Class<T>) extensionWrapper.getDescriptor().extensionClass;
- extensionClasses.add(c);
- }
-
- return extensionClasses;
+ public <T> List<Class<? extends T>> getExtensionClasses(Class<T> type) {
+ return getExtensionClasses(extensionFinder.find(type));
}
- @SuppressWarnings("unchecked")
@Override
- public <T> List<Class<T>> getExtensionClasses(Class<T> type, String pluginId) {
- List<ExtensionWrapper<T>> extensionsWrapper = extensionFinder.find(type, pluginId);
- List<Class<T>> extensionClasses = new ArrayList<>(extensionsWrapper.size());
- for (ExtensionWrapper<T> extensionWrapper : extensionsWrapper) {
- Class<T> c = (Class<T>) extensionWrapper.getDescriptor().extensionClass;
- extensionClasses.add(c);
- }
-
- return extensionClasses;
+ public <T> List<Class<? extends T>> getExtensionClasses(Class<T> type, String pluginId) {
+ return getExtensionClasses(extensionFinder.find(type, pluginId));
}
@Override
public <T> List<T> getExtensions(Class<T> type) {
- List<ExtensionWrapper<T>> extensionsWrapper = extensionFinder.find(type);
- List<T> extensions = new ArrayList<>(extensionsWrapper.size());
- for (ExtensionWrapper<T> extensionWrapper : extensionsWrapper) {
- extensions.add(extensionWrapper.getExtension());
- }
-
- return extensions;
+ return getExtensions(extensionFinder.find(type));
}
@Override
public <T> List<T> getExtensions(Class<T> type, String pluginId) {
- List<ExtensionWrapper<T>> extensionsWrapper = extensionFinder.find(type, pluginId);
- List<T> extensions = new ArrayList<>(extensionsWrapper.size());
- for (ExtensionWrapper<T> extensionWrapper : extensionsWrapper) {
- extensions.add(extensionWrapper.getExtension());
- }
-
- return extensions;
+ return getExtensions(extensionFinder.find(type, pluginId));
}
@Override
@@ -596,7 +558,11 @@ public abstract class AbstractPluginManager implements PluginManager {
List<ExtensionWrapper> extensionsWrapper = extensionFinder.find(pluginId);
List extensions = new ArrayList<>(extensionsWrapper.size());
for (ExtensionWrapper extensionWrapper : extensionsWrapper) {
- extensions.add(extensionWrapper.getExtension());
+ try {
+ extensions.add(extensionWrapper.getExtension());
+ } catch (PluginRuntimeException e) {
+ log.error("Cannot retrieve extension", e);
+ }
}
return extensions;
@@ -612,7 +578,6 @@ public abstract class AbstractPluginManager implements PluginManager {
return extensionFactory;
}
- // TODO remove
public PluginLoader getPluginLoader() {
return pluginLoader;
}
@@ -625,7 +590,7 @@ public abstract class AbstractPluginManager implements PluginManager {
public RuntimeMode getRuntimeMode() {
if (runtimeMode == null) {
// retrieves the runtime mode from system
- String modeAsString = System.getProperty("pf4j.mode", RuntimeMode.DEPLOYMENT.toString());
+ String modeAsString = System.getProperty(MODE_PROPERTY_NAME, RuntimeMode.DEPLOYMENT.toString());
runtimeMode = RuntimeMode.byName(modeAsString);
}
@@ -723,20 +688,16 @@ public abstract class AbstractPluginManager implements PluginManager {
/**
* Add the possibility to override the plugins root.
- * If a {@code pf4j.pluginsDir} system property is defined than this method returns that root.
- * If {@link #getRuntimeMode()} returns {@link RuntimeMode#DEVELOPMENT} than {@code ../plugins}
- * is returned else this method returns {@code plugins}.
+ * If a {@link #PLUGINS_DIR_PROPERTY_NAME} system property is defined than this method returns that root.
+ * If {@link #getRuntimeMode()} returns {@link RuntimeMode#DEVELOPMENT} than {@link #DEVELOPMENT_PLUGINS_DIR}
+ * is returned else this method returns {@link #DEFAULT_PLUGINS_DIR}.
*
* @return the plugins root
*/
protected Path createPluginsRoot() {
- String pluginsDir = System.getProperty("pf4j.pluginsDir");
+ String pluginsDir = System.getProperty(PLUGINS_DIR_PROPERTY_NAME);
if (pluginsDir == null) {
- if (isDevelopment()) {
- pluginsDir = "../plugins";
- } else {
- pluginsDir = "plugins";
- }
+ pluginsDir = isDevelopment() ? DEVELOPMENT_PLUGINS_DIR : DEFAULT_PLUGINS_DIR;
}
return Paths.get(pluginsDir);
@@ -771,7 +732,7 @@ public abstract class AbstractPluginManager implements PluginManager {
return pluginStatusProvider.isPluginDisabled(pluginId);
}
- protected void resolvePlugins() throws PluginException {
+ protected void resolvePlugins() {
// retrieves the plugins descriptors
List<PluginDescriptor> descriptors = new ArrayList<>();
for (PluginWrapper plugin : plugins.values()) {
@@ -820,7 +781,7 @@ public abstract class AbstractPluginManager implements PluginManager {
}
}
- protected PluginWrapper loadPluginFromPath(Path pluginPath) throws PluginException {
+ protected PluginWrapper loadPluginFromPath(Path pluginPath) {
// Test for plugin path duplication
String pluginId = idForPath(pluginPath);
if (pluginId != null) {
@@ -838,7 +799,7 @@ public abstract class AbstractPluginManager implements PluginManager {
pluginId = pluginDescriptor.getPluginId();
if (plugins.containsKey(pluginId)) {
PluginWrapper loadedPlugin = getPlugin(pluginId);
- throw new PluginException("There is an already loaded plugin ({}) "
+ throw new PluginRuntimeException("There is an already loaded plugin ({}) "
+ "with the same id ({}) as the plugin at path '{}'. Simultaneous loading "
+ "of plugins with the same PluginId is not currently supported.\n"
+ "As a workaround you may include PluginVersion and PluginProvider "
@@ -859,7 +820,6 @@ public abstract class AbstractPluginManager implements PluginManager {
log.debug("Creating wrapper for plugin '{}'", pluginPath);
PluginWrapper pluginWrapper = new PluginWrapper(this, pluginDescriptor, pluginPath, pluginClassLoader);
pluginWrapper.setPluginFactory(getPluginFactory());
- pluginWrapper.setRuntimeMode(getRuntimeMode());
// test for disabled plugin
if (isPluginDisabled(pluginDescriptor.getPluginId())) {
@@ -907,23 +867,18 @@ public abstract class AbstractPluginManager implements PluginManager {
* Override this to change the validation criteria.
*
* @param descriptor the plugin descriptor to validate
- * @throws PluginException if validation fails
+ * @throws PluginRuntimeException if validation fails
*/
- protected void validatePluginDescriptor(PluginDescriptor descriptor) throws PluginException {
+ protected void validatePluginDescriptor(PluginDescriptor descriptor) {
if (StringUtils.isNullOrEmpty(descriptor.getPluginId())) {
- throw new PluginException("Field 'id' cannot be empty");
+ throw new PluginRuntimeException("Field 'id' cannot be empty");
}
if (descriptor.getVersion() == null) {
- throw new PluginException("Field 'version' cannot be empty");
+ throw new PluginRuntimeException("Field 'version' cannot be empty");
}
}
- // TODO add this method in PluginManager as default method for Java 8.
- protected boolean isDevelopment() {
- return RuntimeMode.DEVELOPMENT.equals(getRuntimeMode());
- }
-
/**
* @return true if exact versions in requires is allowed
*/
@@ -954,4 +909,28 @@ public abstract class AbstractPluginManager implements PluginManager {
return pluginDescriptor.getPluginId() + "@" + pluginDescriptor.getVersion();
}
+ @SuppressWarnings("unchecked")
+ private <T> List<Class<? extends T>> getExtensionClasses(List<ExtensionWrapper<T>> extensionsWrapper) {
+ List<Class<? extends T>> extensionClasses = new ArrayList<>(extensionsWrapper.size());
+ for (ExtensionWrapper<T> extensionWrapper : extensionsWrapper) {
+ Class<T> c = (Class<T>) extensionWrapper.getDescriptor().extensionClass;
+ extensionClasses.add(c);
+ }
+
+ return extensionClasses;
+ }
+
+ private <T> List<T> getExtensions(List<ExtensionWrapper<T>> extensionsWrapper) {
+ List<T> extensions = new ArrayList<>(extensionsWrapper.size());
+ for (ExtensionWrapper<T> extensionWrapper : extensionsWrapper) {
+ try {
+ extensions.add(extensionWrapper.getExtension());
+ } catch (PluginRuntimeException e) {
+ log.error("Cannot retrieve extension", e);
+ }
+ }
+
+ return extensions;
+ }
+
}
diff --git a/pf4j/src/main/java/org/pf4j/BasePluginLoader.java b/pf4j/src/main/java/org/pf4j/BasePluginLoader.java
new file mode 100644
index 0000000..e4f22f3
--- /dev/null
+++ b/pf4j/src/main/java/org/pf4j/BasePluginLoader.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+import org.pf4j.util.FileUtils;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+/**
+ * Load all information needed by a plugin.
+ * This means add to the plugin's {@link ClassLoader} all the jar files and
+ * all the class files specified in the {@link PluginClasspath}.
+ *
+ * @author Decebal Suiu
+ */
+public class BasePluginLoader implements PluginLoader {
+
+ protected PluginManager pluginManager;
+ protected PluginClasspath pluginClasspath;
+
+ public BasePluginLoader(PluginManager pluginManager, PluginClasspath pluginClasspath) {
+ this.pluginManager = pluginManager;
+ this.pluginClasspath = pluginClasspath;
+ }
+
+ @Override
+ public boolean isApplicable(Path pluginPath) {
+ return Files.exists(pluginPath);
+ }
+
+ @Override
+ public ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor) {
+ PluginClassLoader pluginClassLoader = createPluginClassLoader(pluginPath, pluginDescriptor);
+
+ loadClasses(pluginPath, pluginClassLoader);
+ loadJars(pluginPath, pluginClassLoader);
+
+ return pluginClassLoader;
+ }
+
+ protected PluginClassLoader createPluginClassLoader(Path pluginPath, PluginDescriptor pluginDescriptor) {
+ return new PluginClassLoader(pluginManager, pluginDescriptor, getClass().getClassLoader());
+ }
+
+ /**
+ * Add all {@code *.class} files from {@link PluginClasspath#getClassesDirectories()}
+ * to the plugin's {@link ClassLoader}.
+ */
+ protected void loadClasses(Path pluginPath, PluginClassLoader pluginClassLoader) {
+ for (String directory : pluginClasspath.getClassesDirectories()) {
+ File file = pluginPath.resolve(directory).toFile();
+ if (file.exists() && file.isDirectory()) {
+ pluginClassLoader.addFile(file);
+ }
+ }
+ }
+
+ /**
+ * Add all {@code *.jar} files from {@link PluginClasspath#getJarsDirectories()}
+ * to the plugin's {@link ClassLoader}.
+ */
+ protected void loadJars(Path pluginPath, PluginClassLoader pluginClassLoader) {
+ for (String jarsDirectory : pluginClasspath.getJarsDirectories()) {
+ Path file = pluginPath.resolve(jarsDirectory);
+ List<File> jars = FileUtils.getJars(file);
+ for (File jar : jars) {
+ pluginClassLoader.addFile(jar);
+ }
+ }
+ }
+
+}
diff --git a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java
index a353756..8c856f8 100644
--- a/pf4j/src/main/java/org/pf4j/BasePluginRepository.java
+++ b/pf4j/src/main/java/org/pf4j/BasePluginRepository.java
@@ -48,14 +48,7 @@ public class BasePluginRepository implements PluginRepository {
this.filter = filter;
// last modified file is first
- this.comparator = new Comparator<File>() {
-
- @Override
- public int compare(File o1, File o2) {
- return (int) (o2.lastModified() - o1.lastModified());
- }
-
- };
+ this.comparator = (o1, o2) -> (int) (o2.lastModified() - o1.lastModified());
}
public void setFilter(FileFilter filter) {
@@ -94,13 +87,17 @@ public class BasePluginRepository implements PluginRepository {
@Override
public boolean deletePluginPath(Path pluginPath) {
+ if (!filter.accept(pluginPath.toFile())) {
+ return false;
+ }
+
try {
FileUtils.delete(pluginPath);
return true;
- } catch (NoSuchFileException nsf) {
- return false; // Return false on not found to be compatible with previous API
+ } catch (NoSuchFileException e) {
+ return false; // Return false on not found to be compatible with previous API (#135)
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new PluginRuntimeException(e);
}
}
diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java
index 751ad5e..6fe1ff2 100644
--- a/pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java
+++ b/pf4j/src/main/java/org/pf4j/CompoundPluginDescriptorFinder.java
@@ -57,7 +57,7 @@ public class CompoundPluginDescriptorFinder implements PluginDescriptorFinder {
}
@Override
- public PluginDescriptor find(Path pluginPath) throws PluginException {
+ public PluginDescriptor find(Path pluginPath) {
for (PluginDescriptorFinder finder : finders) {
if (finder.isApplicable(pluginPath)) {
log.debug("'{}' is applicable for plugin '{}'", finder, pluginPath);
@@ -81,7 +81,7 @@ public class CompoundPluginDescriptorFinder implements PluginDescriptorFinder {
}
}
- throw new PluginException("No PluginDescriptorFinder for plugin '{}'", pluginPath);
+ throw new PluginRuntimeException("No PluginDescriptorFinder for plugin '{}'", pluginPath);
}
}
diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java b/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java
index fe10d68..c20e4bb 100644
--- a/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java
+++ b/pf4j/src/main/java/org/pf4j/CompoundPluginLoader.java
@@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.BooleanSupplier;
/**
* @author Decebal Suiu
@@ -41,6 +42,21 @@ public class CompoundPluginLoader implements PluginLoader {
return this;
}
+ /**
+ * Add a {@link PluginLoader} only if the {@code condition} is satisfied.
+ *
+ * @param loader
+ * @param condition
+ * @return
+ */
+ public CompoundPluginLoader add(PluginLoader loader, BooleanSupplier condition) {
+ if (condition.getAsBoolean()) {
+ return add(loader);
+ }
+
+ return this;
+ }
+
public int size() {
return loaders.size();
}
diff --git a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java
index 09bc5ce..a36b00a 100644
--- a/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java
+++ b/pf4j/src/main/java/org/pf4j/CompoundPluginRepository.java
@@ -17,7 +17,10 @@ package org.pf4j;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Set;
+import java.util.function.BooleanSupplier;
/**
* @author Decebal Suiu
@@ -37,14 +40,29 @@ public class CompoundPluginRepository implements PluginRepository {
return this;
}
+ /**
+ * Add a {@link PluginRepository} only if the {@code condition} is satisfied.
+ *
+ * @param repository
+ * @param condition
+ * @return
+ */
+ public CompoundPluginRepository add(PluginRepository repository, BooleanSupplier condition) {
+ if (condition.getAsBoolean()) {
+ return add(repository);
+ }
+
+ return this;
+ }
+
@Override
public List<Path> getPluginPaths() {
- List<Path> paths = new ArrayList<>();
+ Set<Path> paths = new LinkedHashSet<>();
for (PluginRepository repository : repositories) {
paths.addAll(repository.getPluginPaths());
}
- return paths;
+ return new ArrayList<>(paths);
}
@Override
diff --git a/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java b/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java
index bd67032..66e5054 100644
--- a/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java
+++ b/pf4j/src/main/java/org/pf4j/DefaultExtensionFactory.java
@@ -29,20 +29,16 @@ public class DefaultExtensionFactory implements ExtensionFactory {
private static final Logger log = LoggerFactory.getLogger(DefaultExtensionFactory.class);
/**
- * Creates an extension instance. If an error occurs than that error is logged and the method returns {@code null}.
- * @param extensionClass
- * @return
+ * Creates an extension instance.
*/
@Override
- public Object create(Class<?> extensionClass) {
+ public <T> T create(Class<T> extensionClass) {
log.debug("Create instance for extension '{}'", extensionClass.getName());
try {
return extensionClass.newInstance();
} catch (Exception e) {
- log.error(e.getMessage(), e);
+ throw new PluginRuntimeException(e);
}
-
- return null;
}
}
diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java b/pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java
index a78bfd3..2d64e1e 100644
--- a/pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java
+++ b/pf4j/src/main/java/org/pf4j/DefaultPluginClasspath.java
@@ -16,17 +16,20 @@
package org.pf4j;
/**
- * The default values are {@code classes} and {@code lib}.
+ * The default values are {@link #CLASSES_DIR} and {@code #LIB_DIR}.
*
* @author Decebal Suiu
*/
public class DefaultPluginClasspath extends PluginClasspath {
+ public static final String CLASSES_DIR = "classes";
+ public static final String LIB_DIR = "lib";
+
public DefaultPluginClasspath() {
super();
- addClassesDirectories("classes");
- addLibDirectories("lib");
+ addClassesDirectories(CLASSES_DIR);
+ addJarsDirectories(LIB_DIR);
}
}
diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java b/pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java
index 60d63be..1ee8349 100644
--- a/pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java
+++ b/pf4j/src/main/java/org/pf4j/DefaultPluginLoader.java
@@ -15,72 +15,23 @@
*/
package org.pf4j;
-import org.pf4j.util.FileUtils;
-
-import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.List;
/**
- * Load all information needed by a plugin.
- * This means add to classpath all jar files from {@code lib} directory
- * and all class files from {@code classes}.
+ * Load all information needed by a plugin from {@link DefaultPluginClasspath}.
*
* @author Decebal Suiu
*/
-public class DefaultPluginLoader implements PluginLoader {
-
- protected PluginManager pluginManager;
- protected PluginClasspath pluginClasspath;
+public class DefaultPluginLoader extends BasePluginLoader {
- public DefaultPluginLoader(PluginManager pluginManager, PluginClasspath pluginClasspath) {
- this.pluginManager = pluginManager;
- this.pluginClasspath = pluginClasspath;
+ public DefaultPluginLoader(PluginManager pluginManager) {
+ super(pluginManager, new DefaultPluginClasspath());
}
@Override
public boolean isApplicable(Path pluginPath) {
- return Files.exists(pluginPath) && Files.isDirectory(pluginPath);
- }
-
- @Override
- public ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor) {
- PluginClassLoader pluginClassLoader = createPluginClassLoader(pluginPath, pluginDescriptor);
-
- loadClasses(pluginPath, pluginClassLoader);
- loadJars(pluginPath, pluginClassLoader);
-
- return pluginClassLoader;
- }
-
- protected PluginClassLoader createPluginClassLoader(Path pluginPath, PluginDescriptor pluginDescriptor) {
- return new PluginClassLoader(pluginManager, pluginDescriptor, getClass().getClassLoader());
- }
-
- /**
- * Add all {@code *.class} files from {@code classes} directories to plugin class loader.
- */
- protected void loadClasses(Path pluginPath, PluginClassLoader pluginClassLoader) {
- for (String directory : pluginClasspath.getClassesDirectories()) {
- File file = pluginPath.resolve(directory).toFile();
- if (file.exists() && file.isDirectory()) {
- pluginClassLoader.addFile(file);
- }
- }
- }
-
- /**
- * Add all {@code *.jar} files from {@code lib} directories to plugin class loader.
- */
- protected void loadJars(Path pluginPath, PluginClassLoader pluginClassLoader) {
- for (String libDirectory : pluginClasspath.getLibDirectories()) {
- Path file = pluginPath.resolve(libDirectory);
- List<File> jars = FileUtils.getJars(file);
- for (File jar : jars) {
- pluginClassLoader.addFile(jar);
- }
- }
+ return super.isApplicable(pluginPath) && Files.isDirectory(pluginPath);
}
}
diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java
index 96a4104..9cad187 100644
--- a/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java
+++ b/pf4j/src/main/java/org/pf4j/DefaultPluginManager.java
@@ -19,12 +19,13 @@ import org.pf4j.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Default implementation of the {@link PluginManager} interface.
+ * In essence it is a {@link ZipPluginManager} plus a {@link JarPluginManager}.
+ * So, it can load plugins from jar and zip, simultaneous.
*
* <p>This class is not thread-safe.
*
@@ -34,22 +35,12 @@ public class DefaultPluginManager extends AbstractPluginManager {
private static final Logger log = LoggerFactory.getLogger(DefaultPluginManager.class);
- protected PluginClasspath pluginClasspath;
+ public static final String PLUGINS_DIR_CONFIG_PROPERTY_NAME = "pf4j.pluginsConfigDir";
public DefaultPluginManager() {
super();
}
- /**
- * Use {@link DefaultPluginManager#DefaultPluginManager(Path)}.
- *
- * @param pluginsDir
- */
- @Deprecated
- public DefaultPluginManager(File pluginsDir) {
- this(pluginsDir.toPath());
- }
-
public DefaultPluginManager(Path pluginsRoot) {
super(pluginsRoot);
}
@@ -81,23 +72,26 @@ public class DefaultPluginManager extends AbstractPluginManager {
@Override
protected PluginStatusProvider createPluginStatusProvider() {
- String configDir = System.getProperty("pf4j.pluginsConfigDir");
+ String configDir = System.getProperty(PLUGINS_DIR_CONFIG_PROPERTY_NAME);
Path configPath = configDir != null ? Paths.get(configDir) : getPluginsRoot();
+
return new DefaultPluginStatusProvider(configPath);
}
@Override
protected PluginRepository createPluginRepository() {
return new CompoundPluginRepository()
- .add(new DefaultPluginRepository(getPluginsRoot(), isDevelopment()))
- .add(new JarPluginRepository(getPluginsRoot()));
+ .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment)
+ .add(new JarPluginRepository(getPluginsRoot()), this::isNotDevelopment)
+ .add(new DefaultPluginRepository(getPluginsRoot()), this::isNotDevelopment);
}
@Override
protected PluginLoader createPluginLoader() {
return new CompoundPluginLoader()
- .add(new DefaultPluginLoader(this, pluginClasspath))
- .add(new JarPluginLoader(this));
+ .add(new DevelopmentPluginLoader(this), this::isDevelopment)
+ .add(new JarPluginLoader(this), this::isNotDevelopment)
+ .add(new DefaultPluginLoader(this), this::isNotDevelopment);
}
@Override
@@ -105,19 +99,8 @@ public class DefaultPluginManager extends AbstractPluginManager {
return new DefaultVersionManager();
}
- /**
- * By default if {@link DefaultPluginManager#isDevelopment()} returns true
- * than a {@link DevelopmentPluginClasspath} is returned
- * else this method returns {@link DefaultPluginClasspath}.
- */
- protected PluginClasspath createPluginClasspath() {
- return isDevelopment() ? new DevelopmentPluginClasspath() : new DefaultPluginClasspath();
- }
-
@Override
protected void initialize() {
- pluginClasspath = createPluginClasspath();
-
super.initialize();
if (isDevelopment()) {
@@ -128,13 +111,14 @@ public class DefaultPluginManager extends AbstractPluginManager {
}
/**
- * Load a plugin from disk. If the path is a zip file, first unpack
+ * Load a plugin from disk. If the path is a zip file, first unpack.
+ *
* @param pluginPath plugin location on disk
* @return PluginWrapper for the loaded plugin or null if not loaded
- * @throws PluginException if problems during load
+ * @throws PluginRuntimeException if problems during load
*/
@Override
- protected PluginWrapper loadPluginFromPath(Path pluginPath) throws PluginException {
+ protected PluginWrapper loadPluginFromPath(Path pluginPath) {
// First unzip any ZIP files
try {
pluginPath = FileUtils.expandIfZip(pluginPath);
diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java
index 78ea43c..2fafbc7 100644
--- a/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java
+++ b/pf4j/src/main/java/org/pf4j/DefaultPluginRepository.java
@@ -24,7 +24,6 @@ import org.pf4j.util.OrFileFilter;
import org.pf4j.util.ZipFileFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.pf4j.util.NameFileFilter;
import java.io.File;
import java.io.FileFilter;
@@ -39,29 +38,17 @@ public class DefaultPluginRepository extends BasePluginRepository {
private static final Logger log = LoggerFactory.getLogger(DefaultPluginRepository.class);
- public DefaultPluginRepository(Path pluginsRoot, boolean development) {
+ public DefaultPluginRepository(Path pluginsRoot) {
super(pluginsRoot);
AndFileFilter pluginsFilter = new AndFileFilter(new DirectoryFileFilter());
- pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter(development)));
+ pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter()));
setFilter(pluginsFilter);
}
@Override
public List<Path> getPluginPaths() {
- // expand plugins zip files
- File[] pluginZips = pluginsRoot.toFile().listFiles(new ZipFileFilter());
- if ((pluginZips != null) && pluginZips.length > 0) {
- for (File pluginZip : pluginZips) {
- try {
- FileUtils.expandIfZip(pluginZip.toPath());
- } catch (IOException e) {
- log.error("Cannot expand plugin zip '{}'", pluginZip);
- log.error(e.getMessage(), e);
- }
- }
- }
-
+ extractZipFiles();
return super.getPluginPaths();
}
@@ -71,16 +58,23 @@ public class DefaultPluginRepository extends BasePluginRepository {
return super.deletePluginPath(pluginPath);
}
- protected FileFilter createHiddenPluginFilter(boolean development) {
- OrFileFilter hiddenPluginFilter = new OrFileFilter(new HiddenFilter());
+ protected FileFilter createHiddenPluginFilter() {
+ return new OrFileFilter(new HiddenFilter());
+ }
- if (development) {
- // skip default build output folders since these will cause errors in the logs
- hiddenPluginFilter
- .addFileFilter(new NameFileFilter("target")) // MAVEN
- .addFileFilter(new NameFileFilter("build")); // GRADLE
+ private void extractZipFiles() {
+ // expand plugins zip files
+ File[] zipFiles = pluginsRoot.toFile().listFiles(new ZipFileFilter());
+ if ((zipFiles != null) && zipFiles.length > 0) {
+ for (File pluginZip : zipFiles) {
+ try {
+ FileUtils.expandIfZip(pluginZip.toPath());
+ } catch (IOException e) {
+ log.error("Cannot expand plugin zip '{}'", pluginZip);
+ log.error(e.getMessage(), e);
+ }
+ }
}
-
- return hiddenPluginFilter;
}
+
}
diff --git a/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java b/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java
index ca85407..0b88fe8 100644
--- a/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java
+++ b/pf4j/src/main/java/org/pf4j/DefaultPluginStatusProvider.java
@@ -66,31 +66,23 @@ public class DefaultPluginStatusProvider implements PluginStatusProvider {
}
@Override
- public boolean disablePlugin(String pluginId) {
- if (disabledPlugins.add(pluginId)) {
- try {
- FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile());
- } catch (IOException e) {
- log.error("Failed to disable plugin {}", pluginId, e);
- return false;
- }
+ public void disablePlugin(String pluginId) {
+ disabledPlugins.add(pluginId);
+ try {
+ FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile());
+ } catch (IOException e) {
+ throw new PluginRuntimeException(e);
}
-
- return true;
}
@Override
- public boolean enablePlugin(String pluginId) {
- if (disabledPlugins.remove(pluginId)) {
- try {
- FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile());
- } catch (IOException e) {
- log.error("Failed to enable plugin {}", pluginId, e);
- return false;
- }
+ public void enablePlugin(String pluginId) {
+ disabledPlugins.remove(pluginId);
+ try {
+ FileUtils.writeLines(disabledPlugins, pluginsRoot.resolve("disabled.txt").toFile());
+ } catch (IOException e) {
+ throw new PluginRuntimeException(e);
}
-
- return true;
}
}
diff --git a/pf4j/src/main/java/org/pf4j/DependencyResolver.java b/pf4j/src/main/java/org/pf4j/DependencyResolver.java
index a3aa9f6..45005e2 100644
--- a/pf4j/src/main/java/org/pf4j/DependencyResolver.java
+++ b/pf4j/src/main/java/org/pf4j/DependencyResolver.java
@@ -272,7 +272,7 @@ public class DependencyResolver {
/**
* It will be thrown if a cyclic dependency is detected.
*/
- public static class CyclicDependencyException extends PluginException {
+ public static class CyclicDependencyException extends PluginRuntimeException {
public CyclicDependencyException() {
super("Cyclic dependencies");
@@ -283,7 +283,7 @@ public class DependencyResolver {
/**
* Indicates that the dependencies required were not found.
*/
- public static class DependenciesNotFoundException extends PluginException {
+ public static class DependenciesNotFoundException extends PluginRuntimeException {
private List<String> dependencies;
@@ -302,7 +302,7 @@ public class DependencyResolver {
/**
* Indicates that some dependencies have wrong version.
*/
- public static class DependenciesWrongVersionException extends PluginException {
+ public static class DependenciesWrongVersionException extends PluginRuntimeException {
private List<WrongDependencyVersion> dependencies;
diff --git a/pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java b/pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java
index 15da659..4d7727d 100644
--- a/pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java
+++ b/pf4j/src/main/java/org/pf4j/DevelopmentPluginClasspath.java
@@ -27,7 +27,7 @@ public class DevelopmentPluginClasspath extends PluginClasspath {
* The development plugin classpath for <a href="https://maven.apache.org">Maven</a>.
* The classes directory is {@code target/classes} and the lib directory is {@code target/lib}.
*/
- public static final PluginClasspath MAVEN = new PluginClasspath().addClassesDirectories("target/classes").addLibDirectories("target/lib");
+ public static final PluginClasspath MAVEN = new PluginClasspath().addClassesDirectories("target/classes").addJarsDirectories("target/lib");
/**
* The development plugin classpath for <a href="https://gradle.org">Gradle</a>.
@@ -46,9 +46,9 @@ public class DevelopmentPluginClasspath extends PluginClasspath {
addClassesDirectories(GRADLE.getClassesDirectories());
addClassesDirectories(KOTLIN.getClassesDirectories());
- addLibDirectories(MAVEN.getLibDirectories());
- addLibDirectories(GRADLE.getLibDirectories());
- addLibDirectories(KOTLIN.getLibDirectories());
+ addJarsDirectories(MAVEN.getJarsDirectories());
+ addJarsDirectories(GRADLE.getJarsDirectories());
+ addJarsDirectories(KOTLIN.getJarsDirectories());
}
}
diff --git a/pf4j/src/main/java/org/pf4j/DevelopmentPluginLoader.java b/pf4j/src/main/java/org/pf4j/DevelopmentPluginLoader.java
new file mode 100644
index 0000000..58c9473
--- /dev/null
+++ b/pf4j/src/main/java/org/pf4j/DevelopmentPluginLoader.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+/**
+ * Load all information needed by a plugin from {@link DevelopmentPluginClasspath}.
+ *
+ * @author Decebal Suiu
+ */
+public class DevelopmentPluginLoader extends BasePluginLoader {
+
+ public DevelopmentPluginLoader(PluginManager pluginManager) {
+ super(pluginManager, new DevelopmentPluginClasspath());
+ }
+
+}
diff --git a/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java b/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java
new file mode 100644
index 0000000..e8f2c69
--- /dev/null
+++ b/pf4j/src/main/java/org/pf4j/DevelopmentPluginRepository.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+import org.pf4j.util.AndFileFilter;
+import org.pf4j.util.DirectoryFileFilter;
+import org.pf4j.util.HiddenFilter;
+import org.pf4j.util.NameFileFilter;
+import org.pf4j.util.NotFileFilter;
+import org.pf4j.util.OrFileFilter;
+
+import java.io.FileFilter;
+import java.nio.file.Path;
+
+/**
+ * @author Decebal Suiu
+ */
+public class DevelopmentPluginRepository extends BasePluginRepository {
+
+ public static final String MAVEN_BUILD_DIR = "target";
+ public static final String GRADLE_BUILD_DIR = "build";
+
+ public DevelopmentPluginRepository(Path pluginsRoot) {
+ super(pluginsRoot);
+
+ AndFileFilter pluginsFilter = new AndFileFilter(new DirectoryFileFilter());
+ pluginsFilter.addFileFilter(new NotFileFilter(createHiddenPluginFilter()));
+ setFilter(pluginsFilter);
+ }
+
+ protected FileFilter createHiddenPluginFilter() {
+ OrFileFilter hiddenPluginFilter = new OrFileFilter(new HiddenFilter());
+
+ // skip default build output folders since these will cause errors in the logs
+ hiddenPluginFilter
+ .addFileFilter(new NameFileFilter(MAVEN_BUILD_DIR))
+ .addFileFilter(new NameFileFilter(GRADLE_BUILD_DIR));
+
+ return hiddenPluginFilter;
+ }
+
+}
diff --git a/pf4j/src/main/java/org/pf4j/ExtensionFactory.java b/pf4j/src/main/java/org/pf4j/ExtensionFactory.java
index 177d489..176c6ff 100644
--- a/pf4j/src/main/java/org/pf4j/ExtensionFactory.java
+++ b/pf4j/src/main/java/org/pf4j/ExtensionFactory.java
@@ -20,6 +20,6 @@ package org.pf4j;
*/
public interface ExtensionFactory {
- Object create(Class<?> extensionClass);
+ <T> T create(Class<T> extensionClass);
}
diff --git a/pf4j/src/main/java/org/pf4j/JarPluginManager.java b/pf4j/src/main/java/org/pf4j/JarPluginManager.java
new file mode 100644
index 0000000..f280466
--- /dev/null
+++ b/pf4j/src/main/java/org/pf4j/JarPluginManager.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+import java.nio.file.Path;
+
+/**
+ * It's a {@link PluginManager} that loads each plugin from a {@code jar} file.
+ * Actually, a plugin is a fat jar, a jar which contains classes from all the libraries,
+ * on which your project depends and, of course, the classes of current project.
+ *
+ * @author Decebal Suiu
+ */
+public class JarPluginManager extends DefaultPluginManager {
+
+ public JarPluginManager() {
+ super();
+ }
+
+ public JarPluginManager(Path pluginsRoot) {
+ super(pluginsRoot);
+ }
+
+ @Override
+ protected PluginDescriptorFinder createPluginDescriptorFinder() {
+ return new ManifestPluginDescriptorFinder();
+ }
+
+ @Override
+ protected PluginLoader createPluginLoader() {
+ return new CompoundPluginLoader()
+ .add(new DevelopmentPluginLoader(this), this::isDevelopment)
+ .add(new JarPluginLoader(this), this::isNotDevelopment);
+ }
+
+ @Override
+ protected PluginRepository createPluginRepository() {
+ return new CompoundPluginRepository()
+ .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment)
+ .add(new JarPluginRepository(getPluginsRoot()), this::isNotDevelopment);
+ }
+
+}
diff --git a/pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java b/pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java
index 99e1313..33adc27 100644
--- a/pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java
+++ b/pf4j/src/main/java/org/pf4j/LegacyExtensionFinder.java
@@ -20,6 +20,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
@@ -81,11 +82,14 @@ public class LegacyExtensionFinder extends AbstractExtensionFinder {
Set<String> bucket = new HashSet<>();
try {
- Enumeration<URL> urls = ((PluginClassLoader) plugin.getPluginClassLoader()).findResources(getExtensionsResource());
- if (urls.hasMoreElements()) {
- collectExtensions(urls, bucket);
- } else {
- log.debug("Cannot find '{}'", getExtensionsResource());
+ log.debug("Read '{}'", getExtensionsResource());
+ ClassLoader pluginClassLoader = plugin.getPluginClassLoader();
+ try (InputStream resourceStream = pluginClassLoader.getResourceAsStream(getExtensionsResource())) {
+ if (resourceStream == null) {
+ log.debug("Cannot find '{}'", getExtensionsResource());
+ } else {
+ collectExtensions(resourceStream, bucket);
+ }
}
debugExtensions(bucket);
@@ -103,9 +107,13 @@ public class LegacyExtensionFinder extends AbstractExtensionFinder {
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
log.debug("Read '{}'", url.getFile());
- try (Reader reader = new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)) {
- LegacyExtensionStorage.read(reader, bucket);
- }
+ collectExtensions(url.openStream(), bucket);
+ }
+ }
+
+ private void collectExtensions(InputStream inputStream, Set<String> bucket) throws IOException {
+ try (Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
+ LegacyExtensionStorage.read(reader, bucket);
}
}
diff --git a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java
index 74cd0f3..650b2d7 100644
--- a/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java
+++ b/pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java
@@ -37,19 +37,28 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder {
private static final Logger log = LoggerFactory.getLogger(ManifestPluginDescriptorFinder.class);
+ public static final String PLUGIN_ID = "Plugin-Id";
+ public static final String PLUGIN_DESCRIPTION = "Plugin-Description";
+ public static final String PLUGIN_CLASS = "Plugin-Class";
+ public static final String PLUGIN_VERSION = "Plugin-Version";
+ public static final String PLUGIN_PROVIDER = "Plugin-Provider";
+ public static final String PLUGIN_DEPENDENCIES = "Plugin-Dependencies";
+ public static final String PLUGIN_REQUIRES = "Plugin-Requires";
+ public static final String PLUGIN_LICENSE = "Plugin-License";
+
@Override
public boolean isApplicable(Path pluginPath) {
return Files.exists(pluginPath) && (Files.isDirectory(pluginPath) || FileUtils.isJarFile(pluginPath));
}
@Override
- public PluginDescriptor find(Path pluginPath) throws PluginException {
+ public PluginDescriptor find(Path pluginPath) {
Manifest manifest = readManifest(pluginPath);
return createPluginDescriptor(manifest);
}
- protected Manifest readManifest(Path pluginPath) throws PluginException {
+ protected Manifest readManifest(Path pluginPath) {
if (FileUtils.isJarFile(pluginPath)) {
try (JarFile jar = new JarFile(pluginPath.toFile())) {
Manifest manifest = jar.getManifest();
@@ -57,28 +66,28 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder {
return manifest;
}
} catch (IOException e) {
- throw new PluginException(e);
+ throw new PluginRuntimeException(e);
}
}
Path manifestPath = getManifestPath(pluginPath);
if (manifestPath == null) {
- throw new PluginException("Cannot find the manifest path");
+ throw new PluginRuntimeException("Cannot find the manifest path");
}
log.debug("Lookup plugin descriptor in '{}'", manifestPath);
if (Files.notExists(manifestPath)) {
- throw new PluginException("Cannot find '{}' path", manifestPath);
+ throw new PluginRuntimeException("Cannot find '{}' path", manifestPath);
}
try (InputStream input = Files.newInputStream(manifestPath)) {
return new Manifest(input);
} catch (IOException e) {
- throw new PluginException(e);
+ throw new PluginRuntimeException(e);
}
}
- protected Path getManifestPath(Path pluginPath) throws PluginException {
+ protected Path getManifestPath(Path pluginPath) {
if (Files.isDirectory(pluginPath)) {
// legacy (the path is something like "classes/META-INF/MANIFEST.MF")
return FileUtils.findFile(pluginPath,"MANIFEST.MF");
@@ -92,37 +101,37 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder {
// TODO validate !!!
Attributes attributes = manifest.getMainAttributes();
- String id = attributes.getValue("Plugin-Id");
+ String id = attributes.getValue(PLUGIN_ID);
pluginDescriptor.setPluginId(id);
- String description = attributes.getValue("Plugin-Description");
+ String description = attributes.getValue(PLUGIN_DESCRIPTION);
if (StringUtils.isNullOrEmpty(description)) {
pluginDescriptor.setPluginDescription("");
} else {
pluginDescriptor.setPluginDescription(description);
}
- String clazz = attributes.getValue("Plugin-Class");
+ String clazz = attributes.getValue(PLUGIN_CLASS);
if (StringUtils.isNotNullOrEmpty(clazz)) {
pluginDescriptor.setPluginClass(clazz);
}
- String version = attributes.getValue("Plugin-Version");
+ String version = attributes.getValue(PLUGIN_VERSION);
if (StringUtils.isNotNullOrEmpty(version)) {
pluginDescriptor.setPluginVersion(version);
}
- String provider = attributes.getValue("Plugin-Provider");
+ String provider = attributes.getValue(PLUGIN_PROVIDER);
pluginDescriptor.setProvider(provider);
- String dependencies = attributes.getValue("Plugin-Dependencies");
+ String dependencies = attributes.getValue(PLUGIN_DEPENDENCIES);
pluginDescriptor.setDependencies(dependencies);
- String requires = attributes.getValue("Plugin-Requires");
+ String requires = attributes.getValue(PLUGIN_REQUIRES);
if (StringUtils.isNotNullOrEmpty(requires)) {
pluginDescriptor.setRequires(requires);
}
- pluginDescriptor.setLicense(attributes.getValue("Plugin-License"));
+ pluginDescriptor.setLicense(attributes.getValue(PLUGIN_LICENSE));
return pluginDescriptor;
}
diff --git a/pf4j/src/main/java/org/pf4j/Plugin.java b/pf4j/src/main/java/org/pf4j/Plugin.java
index b648b64..e3dd449 100644
--- a/pf4j/src/main/java/org/pf4j/Plugin.java
+++ b/pf4j/src/main/java/org/pf4j/Plugin.java
@@ -60,21 +60,21 @@ public class Plugin {
* This method is called by the application when the plugin is started.
* See {@link PluginManager#startPlugin(String)}.
*/
- public void start() throws PluginException {
+ public void start() {
}
/**
* This method is called by the application when the plugin is stopped.
* See {@link PluginManager#stopPlugin(String)}.
*/
- public void stop() throws PluginException {
+ public void stop() {
}
/**
* This method is called by the application when the plugin is deleted.
* See {@link PluginManager#deletePlugin(String)}.
*/
- public void delete() throws PluginException {
+ public void delete() {
}
}
diff --git a/pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java b/pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java
index adfd90b..411756c 100644
--- a/pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java
+++ b/pf4j/src/main/java/org/pf4j/PluginAlreadyLoadedException.java
@@ -20,7 +20,7 @@ import java.nio.file.Path;
/**
* @author Decebal Suiu
*/
-public class PluginAlreadyLoadedException extends PluginException {
+public class PluginAlreadyLoadedException extends PluginRuntimeException {
private final String pluginId;
private final Path pluginPath;
diff --git a/pf4j/src/main/java/org/pf4j/PluginClasspath.java b/pf4j/src/main/java/org/pf4j/PluginClasspath.java
index 57ff9bf..757740c 100644
--- a/pf4j/src/main/java/org/pf4j/PluginClasspath.java
+++ b/pf4j/src/main/java/org/pf4j/PluginClasspath.java
@@ -22,14 +22,15 @@ import java.util.Set;
/**
* The classpath of the plugin.
- * It contains {@code classes} directories and {@code lib} directories (directories that contains jars).
+ * It contains {@code classes} directories (directories that contain classes files)
+ * and {@code jars} directories (directories that contain jars files).
*
* @author Decebal Suiu
*/
public class PluginClasspath {
private Set<String> classesDirectories = new HashSet<>();
- private Set<String> libDirectories = new HashSet<>();
+ private Set<String> jarsDirectories = new HashSet<>();
public Set<String> getClassesDirectories() {
return classesDirectories;
@@ -45,16 +46,16 @@ public class PluginClasspath {
return this;
}
- public Set<String> getLibDirectories() {
- return libDirectories;
+ public Set<String> getJarsDirectories() {
+ return jarsDirectories;
}
- public PluginClasspath addLibDirectories(String... libDirectories) {
- return addLibDirectories(Arrays.asList(libDirectories));
+ public PluginClasspath addJarsDirectories(String... jarsDirectories) {
+ return addJarsDirectories(Arrays.asList(jarsDirectories));
}
- public PluginClasspath addLibDirectories(Collection<String> libDirectories) {
- this.libDirectories.addAll(libDirectories);
+ public PluginClasspath addJarsDirectories(Collection<String> jarsDirectories) {
+ this.jarsDirectories.addAll(jarsDirectories);
return this;
}
diff --git a/pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java
index 3b9f600..35185af 100644
--- a/pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java
+++ b/pf4j/src/main/java/org/pf4j/PluginDescriptorFinder.java
@@ -29,12 +29,9 @@ public interface PluginDescriptorFinder {
/**
* Returns true if this finder is applicable to the given {@link Path}.
- *
- * @param pluginPath
- * @return
*/
boolean isApplicable(Path pluginPath);
- PluginDescriptor find(Path pluginPath) throws PluginException;
+ PluginDescriptor find(Path pluginPath);
}
diff --git a/pf4j/src/main/java/org/pf4j/PluginManager.java b/pf4j/src/main/java/org/pf4j/PluginManager.java
index 6bb6085..a937f22 100644
--- a/pf4j/src/main/java/org/pf4j/PluginManager.java
+++ b/pf4j/src/main/java/org/pf4j/PluginManager.java
@@ -69,8 +69,8 @@ public interface PluginManager {
* Load a plugin.
*
* @param pluginPath the plugin location
- * @return the pluginId of the installed plugin as specified in
- * its {@linkplain PluginDescriptor metadata}; or {@code null}
+ * @return the pluginId of the installed plugin as specified in its {@linkplain PluginDescriptor metadata}
+ * @throws PluginRuntimeException if something goes wrong
*/
String loadPlugin(Path pluginPath);
@@ -83,6 +83,7 @@ public interface PluginManager {
* Start the specified plugin and its dependencies.
*
* @return the plugin state
+ * @throws PluginRuntimeException if something goes wrong
*/
PluginState startPlugin(String pluginId);
@@ -95,6 +96,7 @@ public interface PluginManager {
* Stop the specified plugin and its dependencies.
*
* @return the plugin state
+ * @throws PluginRuntimeException if something goes wrong
*/
PluginState stopPlugin(String pluginId);
@@ -103,6 +105,7 @@ public interface PluginManager {
*
* @param pluginId the unique plugin identifier, specified in its metadata
* @return true if the plugin was unloaded
+ * @throws PluginRuntimeException if something goes wrong
*/
boolean unloadPlugin(String pluginId);
@@ -111,6 +114,7 @@ public interface PluginManager {
*
* @param pluginId the unique plugin identifier, specified in its metadata
* @return true if plugin is disabled
+ * @throws PluginRuntimeException if something goes wrong
*/
boolean disablePlugin(String pluginId);
@@ -119,6 +123,7 @@ public interface PluginManager {
*
* @param pluginId the unique plugin identifier, specified in its metadata
* @return true if plugin is enabled
+ * @throws PluginRuntimeException if something goes wrong
*/
boolean enablePlugin(String pluginId);
@@ -127,6 +132,7 @@ public interface PluginManager {
*
* @param pluginId the unique plugin identifier, specified in its metadata
* @return true if the plugin was deleted
+ * @throws PluginRuntimeException if something goes wrong
*/
boolean deletePlugin(String pluginId);
@@ -134,9 +140,9 @@ public interface PluginManager {
List<Class<?>> getExtensionClasses(String pluginId);
- <T> List<Class<T>> getExtensionClasses(Class<T> type);
+ <T> List<Class<? extends T>> getExtensionClasses(Class<T> type);
- <T> List<Class<T>> getExtensionClasses(Class<T> type, String pluginId);
+ <T> List<Class<? extends T>> getExtensionClasses(Class<T> type, String pluginId);
<T> List<T> getExtensions(Class<T> type);
@@ -154,6 +160,20 @@ public interface PluginManager {
RuntimeMode getRuntimeMode();
/**
+ * Returns {@code true} if the runtime mode is {@code RuntimeMode.DEVELOPMENT}.
+ */
+ default boolean isDevelopment() {
+ return RuntimeMode.DEVELOPMENT.equals(getRuntimeMode());
+ }
+
+ /**
+ * Returns {@code true} if the runtime mode is not {@code RuntimeMode.DEVELOPMENT}.
+ */
+ default boolean isNotDevelopment() {
+ return !isDevelopment();
+ }
+
+ /**
* Retrieves the {@link PluginWrapper} that loaded the given class 'clazz'.
*/
PluginWrapper whichPlugin(Class<?> clazz);
@@ -180,7 +200,8 @@ public interface PluginManager {
String getSystemVersion();
/**
- * Gets the path of the folder where plugins are installed
+ * Gets the path of the folder where plugins are installed.
+ *
* @return Path of plugins root
*/
Path getPluginsRoot();
diff --git a/pf4j/src/main/java/org/pf4j/PluginRepository.java b/pf4j/src/main/java/org/pf4j/PluginRepository.java
index f3617cd..6bc2356 100644
--- a/pf4j/src/main/java/org/pf4j/PluginRepository.java
+++ b/pf4j/src/main/java/org/pf4j/PluginRepository.java
@@ -19,7 +19,7 @@ import java.nio.file.Path;
import java.util.List;
/**
- * Directory that contains plugins. A plugin could be a zip file.
+ * Directory that contains plugins. A plugin could be a {@code directory}, @code zip} or {@code jar} file.
*
* @author Decebal Suiu
* @author Mário Franco
@@ -29,7 +29,7 @@ public interface PluginRepository {
/**
* List all plugin paths.
*
- * @return a list of files
+ * @return a list with paths
*/
List<Path> getPluginPaths();
@@ -38,6 +38,7 @@ public interface PluginRepository {
*
* @param pluginPath the plugin path
* @return true if deleted
+ * @throws PluginRuntimeException if something goes wrong
*/
boolean deletePluginPath(Path pluginPath);
diff --git a/pf4j/src/main/java/org/pf4j/PluginException.java b/pf4j/src/main/java/org/pf4j/PluginRuntimeException.java
index d1ba6f2..5d5ede9 100644
--- a/pf4j/src/main/java/org/pf4j/PluginException.java
+++ b/pf4j/src/main/java/org/pf4j/PluginRuntimeException.java
@@ -23,29 +23,25 @@ import org.pf4j.util.StringUtils;
*
* @author Decebal Suiu
*/
-public class PluginException extends Exception {
+public class PluginRuntimeException extends RuntimeException {
- public PluginException() {
+ public PluginRuntimeException() {
super();
}
- public PluginException(String message) {
+ public PluginRuntimeException(String message) {
super(message);
}
- public PluginException(Throwable cause) {
+ public PluginRuntimeException(Throwable cause) {
super(cause);
}
- public PluginException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public PluginException(Throwable cause, String message, Object... args) {
+ public PluginRuntimeException(Throwable cause, String message, Object... args) {
super(StringUtils.format(message, args), cause);
}
- public PluginException(String message, Object... args) {
+ public PluginRuntimeException(String message, Object... args) {
super(StringUtils.format(message, args));
}
diff --git a/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java b/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java
index dda5f82..46967b2 100644
--- a/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java
+++ b/pf4j/src/main/java/org/pf4j/PluginStatusProvider.java
@@ -33,16 +33,16 @@ public interface PluginStatusProvider {
* Disables a plugin from being loaded.
*
* @param pluginId the unique plugin identifier, specified in its metadata
- * @return true if plugin is disabled
+ * @throws PluginRuntimeException if something goes wrong
*/
- boolean disablePlugin(String pluginId);
+ void disablePlugin(String pluginId);
/**
* Enables a plugin that has previously been disabled.
*
* @param pluginId the unique plugin identifier, specified in its metadata
- * @return true if plugin is enabled
+ * @throws PluginRuntimeException if something goes wrong
*/
- boolean enablePlugin(String pluginId);
+ void enablePlugin(String pluginId);
}
diff --git a/pf4j/src/main/java/org/pf4j/PluginWrapper.java b/pf4j/src/main/java/org/pf4j/PluginWrapper.java
index c7d93ca..a9aa147 100644
--- a/pf4j/src/main/java/org/pf4j/PluginWrapper.java
+++ b/pf4j/src/main/java/org/pf4j/PluginWrapper.java
@@ -41,6 +41,7 @@ public class PluginWrapper {
this.pluginClassLoader = pluginClassLoader;
pluginState = PluginState.CREATED;
+ runtimeMode = pluginManager.getRuntimeMode();
}
/**
@@ -120,11 +121,9 @@ public class PluginWrapper {
}
PluginWrapper other = (PluginWrapper) obj;
- if (!descriptor.getPluginId().equals(other.descriptor.getPluginId())) {
- return false;
- }
- return true;
+ return descriptor.getPluginId().equals(other.descriptor.getPluginId());
+
}
@Override
@@ -136,10 +135,6 @@ public class PluginWrapper {
this.pluginState = pluginState;
}
- void setRuntimeMode(RuntimeMode runtimeMode) {
- this.runtimeMode = runtimeMode;
- }
-
void setPluginFactory(PluginFactory pluginFactory) {
this.pluginFactory = pluginFactory;
}
diff --git a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java
index 3e9e1c1..6789a5f 100644
--- a/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java
+++ b/pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java
@@ -36,7 +36,16 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder
private static final Logger log = LoggerFactory.getLogger(PropertiesPluginDescriptorFinder.class);
- private static final String DEFAULT_PROPERTIES_FILE_NAME = "plugin.properties";
+ public static final String DEFAULT_PROPERTIES_FILE_NAME = "plugin.properties";
+
+ public static final String PLUGIN_ID = "plugin.id";
+ public static final String PLUGIN_DESCRIPTION = "plugin.description";
+ public static final String PLUGIN_CLASS = "plugin.class";
+ public static final String PLUGIN_VERSION = "plugin.version";
+ public static final String PLUGIN_PROVIDER = "plugin.provider";
+ public static final String PLUGIN_DEPENDENCIES = "plugin.dependencies";
+ public static final String PLUGIN_REQUIRES = "plugin.requires";
+ public static final String PLUGIN_LICENSE = "plugin.license";
protected String propertiesFileName;
@@ -54,34 +63,34 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder
}
@Override
- public PluginDescriptor find(Path pluginPath) throws PluginException {
+ public PluginDescriptor find(Path pluginPath) {
Properties properties = readProperties(pluginPath);
return createPluginDescriptor(properties);
}
- protected Properties readProperties(Path pluginPath) throws PluginException {
+ protected Properties readProperties(Path pluginPath) {
Path propertiesPath = getPropertiesPath(pluginPath, propertiesFileName);
if (propertiesPath == null) {
- throw new PluginException("Cannot find the properties path");
+ throw new PluginRuntimeException("Cannot find the properties path");
}
log.debug("Lookup plugin descriptor in '{}'", propertiesPath);
if (Files.notExists(propertiesPath)) {
- throw new PluginException("Cannot find '{}' path", propertiesPath);
+ throw new PluginRuntimeException("Cannot find '{}' path", propertiesPath);
}
Properties properties = new Properties();
try (InputStream input = Files.newInputStream(propertiesPath)) {
properties.load(input);
} catch (IOException e) {
- throw new PluginException(e);
+ throw new PluginRuntimeException(e);
}
return properties;
}
- protected Path getPropertiesPath(Path pluginPath, String propertiesFileName) throws PluginException {
+ protected Path getPropertiesPath(Path pluginPath, String propertiesFileName) {
if (Files.isDirectory(pluginPath)) {
return pluginPath.resolve(Paths.get(propertiesFileName));
} else {
@@ -89,7 +98,7 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder
try {
return FileUtils.getPath(pluginPath, propertiesFileName);
} catch (IOException e) {
- throw new PluginException(e);
+ throw new PluginRuntimeException(e);
}
}
}
@@ -98,38 +107,38 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder
DefaultPluginDescriptor pluginDescriptor = createPluginDescriptorInstance();
// TODO validate !!!
- String id = properties.getProperty("plugin.id");
+ String id = properties.getProperty(PLUGIN_ID);
pluginDescriptor.setPluginId(id);
- String description = properties.getProperty("plugin.description");
+ String description = properties.getProperty(PLUGIN_DESCRIPTION);
if (StringUtils.isNullOrEmpty(description)) {
pluginDescriptor.setPluginDescription("");
} else {
pluginDescriptor.setPluginDescription(description);
}
- String clazz = properties.getProperty("plugin.class");
+ String clazz = properties.getProperty(PLUGIN_CLASS);
if (StringUtils.isNotNullOrEmpty(clazz)) {
pluginDescriptor.setPluginClass(clazz);
}
- String version = properties.getProperty("plugin.version");
+ String version = properties.getProperty(PLUGIN_VERSION);
if (StringUtils.isNotNullOrEmpty(version)) {
pluginDescriptor.setPluginVersion(version);
}
- String provider = properties.getProperty("plugin.provider");
+ String provider = properties.getProperty(PLUGIN_PROVIDER);
pluginDescriptor.setProvider(provider);
- String dependencies = properties.getProperty("plugin.dependencies");
+ String dependencies = properties.getProperty(PLUGIN_DEPENDENCIES);
pluginDescriptor.setDependencies(dependencies);
- String requires = properties.getProperty("plugin.requires");
+ String requires = properties.getProperty(PLUGIN_REQUIRES);
if (StringUtils.isNotNullOrEmpty(requires)) {
pluginDescriptor.setRequires(requires);
}
- pluginDescriptor.setLicense(properties.getProperty("plugin.license"));
+ pluginDescriptor.setLicense(properties.getProperty(PLUGIN_LICENSE));
return pluginDescriptor;
}
diff --git a/pf4j/src/main/java/org/pf4j/RuntimeMode.java b/pf4j/src/main/java/org/pf4j/RuntimeMode.java
index 1fa9cbd..909cc38 100644
--- a/pf4j/src/main/java/org/pf4j/RuntimeMode.java
+++ b/pf4j/src/main/java/org/pf4j/RuntimeMode.java
@@ -41,7 +41,7 @@ public enum RuntimeMode {
}
}
- private RuntimeMode(final String name, final String... aliases) {
+ RuntimeMode(final String name, final String... aliases) {
this.name = name;
this.aliases = aliases;
}
diff --git a/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java b/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java
index d339921..725b9a7 100644
--- a/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java
+++ b/pf4j/src/main/java/org/pf4j/SingletonExtensionFactory.java
@@ -39,13 +39,14 @@ public class SingletonExtensionFactory extends DefaultExtensionFactory {
}
@Override
- public Object create(Class<?> extensionClass) {
+ @SuppressWarnings("unchecked")
+ public <T> T create(Class<T> extensionClass) {
String extensionClassName = extensionClass.getName();
if (cache.containsKey(extensionClassName)) {
- return cache.get(extensionClassName);
+ return (T) cache.get(extensionClassName);
}
- Object extension = super.create(extensionClass);
+ T extension = super.create(extensionClass);
if (extensionClassNames.isEmpty() || extensionClassNames.contains(extensionClassName)) {
cache.put(extensionClassName, extension);
}
diff --git a/pf4j/src/main/java/org/pf4j/ZipPluginManager.java b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java
new file mode 100644
index 0000000..a32d156
--- /dev/null
+++ b/pf4j/src/main/java/org/pf4j/ZipPluginManager.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+/**
+ * It's a {@link PluginManager} that loads each plugin from a {@code zip} file.
+ * The structure of the zip file is:
+ * <ul>
+ * <li>{@code lib} directory that contains all dependencies (as jar files); it's optional (no dependencies)
+ * <li>{@code classes} directory that contains all plugin's classes
+ * </ul>
+ *
+ * @author Decebal Suiu
+ */
+public class ZipPluginManager extends DefaultPluginManager {
+
+ @Override
+ protected PluginDescriptorFinder createPluginDescriptorFinder() {
+ return new PropertiesPluginDescriptorFinder();
+ }
+
+ @Override
+ protected PluginLoader createPluginLoader() {
+ return new CompoundPluginLoader()
+ .add(new DevelopmentPluginLoader(this), this::isDevelopment)
+ .add(new DefaultPluginLoader(this), this::isNotDevelopment);
+ }
+
+ @Override
+ protected PluginRepository createPluginRepository() {
+ return new CompoundPluginRepository()
+ .add(new DevelopmentPluginRepository(getPluginsRoot()), this::isDevelopment)
+ .add(new DefaultPluginRepository(getPluginsRoot()), this::isNotDevelopment);
+ }
+
+}
diff --git a/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java b/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java
index e0f3513..55bbbc2 100644
--- a/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java
+++ b/pf4j/src/main/java/org/pf4j/processor/ExtensionAnnotationProcessor.java
@@ -109,11 +109,7 @@ public class ExtensionAnnotationProcessor extends AbstractProcessor {
String extension = getBinaryName(extensionElement);
for (TypeElement extensionPointElement : extensionPointElements) {
String extensionPoint = getBinaryName(extensionPointElement);
- Set<String> extensionPoints = extensions.get(extensionPoint);
- if (extensionPoints == null) {
- extensionPoints = new TreeSet<>();
- extensions.put(extensionPoint, extensionPoints);
- }
+ Set<String> extensionPoints = extensions.computeIfAbsent(extensionPoint, k -> new TreeSet<>());
extensionPoints.add(extension);
}
}
diff --git a/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java b/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java
index cc74da4..76a17ec 100644
--- a/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java
+++ b/pf4j/src/main/java/org/pf4j/util/AndFileFilter.java
@@ -23,11 +23,9 @@ import java.util.Collections;
import java.util.List;
/**
- * This filter providing conditional AND logic across a list of
- * file filters. This filter returns <code>true</code> if all filters in the
- * list return <code>true</code>. Otherwise, it returns <code>false</code>.
- * Checking of the file filter list stops when the first filter returns
- * <code>false</code>.
+ * This filter providing conditional AND logic across a list of file filters.
+ * This filter returns {@code true} if all filters in the list return {@code true}. Otherwise, it returns {@code false}.
+ * Checking of the file filter list stops when the first filter returns {@code false}.
*
* @author Decebal Suiu
*/
@@ -37,7 +35,7 @@ public class AndFileFilter implements FileFilter {
private List<FileFilter> fileFilters;
public AndFileFilter() {
- this(new ArrayList<FileFilter>());
+ this(new ArrayList<>());
}
public AndFileFilter(FileFilter... fileFilters) {
@@ -68,7 +66,7 @@ public class AndFileFilter implements FileFilter {
@Override
public boolean accept(File file) {
- if (this.fileFilters.size() == 0) {
+ if (this.fileFilters.isEmpty()) {
return false;
}
diff --git a/pf4j/src/main/java/org/pf4j/util/DirectedGraph.java b/pf4j/src/main/java/org/pf4j/util/DirectedGraph.java
index 076d67c..1163f91 100644
--- a/pf4j/src/main/java/org/pf4j/util/DirectedGraph.java
+++ b/pf4j/src/main/java/org/pf4j/util/DirectedGraph.java
@@ -44,7 +44,7 @@ public class DirectedGraph<V> {
return;
}
- neighbors.put(vertex, new ArrayList<V>());
+ neighbors.put(vertex, new ArrayList<>());
}
/**
@@ -85,7 +85,7 @@ public class DirectedGraph<V> {
}
public List<V> getNeighbors(V vertex) {
- return containsVertex(vertex) ? neighbors.get(vertex) : new ArrayList<V>();
+ return containsVertex(vertex) ? neighbors.get(vertex) : new ArrayList<>();
}
/**
@@ -101,7 +101,7 @@ public class DirectedGraph<V> {
}
/**
- * Report (as a Map) the in-degree (the number of head ends adjacent to a vertex) of each vertex.
+ * Report (as a {@link Map}) the in-degree (the number of head ends adjacent to a vertex) of each vertex.
*/
public Map<V, Integer> inDegree() {
Map<V, Integer> result = new HashMap<>();
@@ -181,9 +181,9 @@ public class DirectedGraph<V> {
*/
@Override
public String toString() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
for (V vertex : neighbors.keySet()) {
- sb.append("\n " + vertex + " -> " + neighbors.get(vertex));
+ sb.append("\n ").append(vertex).append(" -> ").append(neighbors.get(vertex));
}
return sb.toString();
diff --git a/pf4j/src/main/java/org/pf4j/util/FileUtils.java b/pf4j/src/main/java/org/pf4j/util/FileUtils.java
index a3e955e..0cb8784 100644
--- a/pf4j/src/main/java/org/pf4j/util/FileUtils.java
+++ b/pf4j/src/main/java/org/pf4j/util/FileUtils.java
@@ -172,17 +172,10 @@ public class FileUtils {
FileTime pluginZipDate = Files.getLastModifiedTime(filePath);
String fileName = filePath.getFileName().toString();
- Path pluginDirectory = filePath.resolveSibling(fileName.substring(0, fileName.lastIndexOf(".")));
+ String directoryName = fileName.substring(0, fileName.lastIndexOf("."));
+ Path pluginDirectory = filePath.resolveSibling(directoryName);
if (!Files.exists(pluginDirectory) || pluginZipDate.compareTo(Files.getLastModifiedTime(pluginDirectory)) > 0) {
- // do not overwrite an old version, remove it
- if (Files.exists(pluginDirectory)) {
- FileUtils.delete(pluginDirectory);
- }
-
- // create root for plugin
- Files.createDirectories(pluginDirectory);
-
// expand '.zip' file
Unzip unzip = new Unzip();
unzip.setSource(filePath.toFile());
diff --git a/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java b/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java
index fccfb7b..5798249 100644
--- a/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java
+++ b/pf4j/src/main/java/org/pf4j/util/OrFileFilter.java
@@ -23,11 +23,9 @@ import java.util.Collections;
import java.util.List;
/**
- * This filter providing conditional OR logic across a list of
- * file filters. This filter returns <code>true</code> if one filter in the
- * list return <code>true</code>. Otherwise, it returns <code>false</code>.
- * Checking of the file filter list stops when the first filter returns
- * <code>true</code>.
+ * This filter providing conditional OR logic across a list of file filters.
+ * This filter returns {@code true} if one filter in the list return {@code true}. Otherwise, it returns {@code false}.
+ * Checking of the file filter list stops when the first filter returns {@code true}.
*
* @author Decebal Suiu
*/
@@ -37,7 +35,7 @@ public class OrFileFilter implements FileFilter {
private List<FileFilter> fileFilters;
public OrFileFilter() {
- this(new ArrayList<FileFilter>());
+ this(new ArrayList<>());
}
public OrFileFilter(FileFilter... fileFilters) {
@@ -68,7 +66,7 @@ public class OrFileFilter implements FileFilter {
@Override
public boolean accept(File file) {
- if (this.fileFilters.size() == 0) {
+ if (this.fileFilters.isEmpty()) {
return true;
}
diff --git a/pf4j/src/main/java/org/pf4j/util/Unzip.java b/pf4j/src/main/java/org/pf4j/util/Unzip.java
index 7762e47..afde37a 100644
--- a/pf4j/src/main/java/org/pf4j/util/Unzip.java
+++ b/pf4j/src/main/java/org/pf4j/util/Unzip.java
@@ -63,10 +63,14 @@ public class Unzip {
this.destination = destination;
}
+ /**
+ * Extract the content of zip file ({@code source}) to destination directory.
+ * If destination directory already exists it will be deleted before.
+ */
public void extract() throws IOException {
log.debug("Extract content of '{}' to '{}'", source, destination);
- // delete destination file if exists
+ // delete destination directory if exists
if (destination.exists() && destination.isDirectory()) {
FileUtils.delete(destination.toPath());
}
diff --git a/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java
index 2acabee..6383756 100644
--- a/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java
+++ b/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java
@@ -15,9 +15,9 @@
*/
package org.pf4j;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.pf4j.plugin.FailTestPlugin;
import org.pf4j.plugin.TestExtensionPoint;
@@ -28,7 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -40,7 +40,7 @@ public class AbstractExtensionFinderTest {
private PluginManager pluginManager;
- @Before
+ @BeforeEach
public void setUp() {
PluginWrapper pluginStarted = mock(PluginWrapper.class);
when(pluginStarted.getPluginClassLoader()).thenReturn(getClass().getClassLoader());
@@ -57,7 +57,7 @@ public class AbstractExtensionFinderTest {
when(pluginManager.getExtensionFactory()).thenReturn(new DefaultExtensionFactory());
}
- @After
+ @AfterEach
public void tearDown() {
pluginManager = null;
}
diff --git a/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java
new file mode 100644
index 0000000..784d1f9
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/AbstractPluginManagerTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+import org.junit.jupiter.api.Test;
+import org.pf4j.plugin.TestExtension;
+import org.pf4j.plugin.TestExtensionPoint;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author Decebal Suiu
+ */
+public class AbstractPluginManagerTest {
+
+ @Test
+ public void getExtensionsByType() {
+ AbstractPluginManager pluginManager = mock(AbstractPluginManager.class, CALLS_REAL_METHODS);
+
+ ExtensionFinder extensionFinder = mock(ExtensionFinder.class);
+ List<ExtensionWrapper<TestExtensionPoint>> extensionList = new ArrayList<>(1);
+ extensionList.add(new ExtensionWrapper<>(new ExtensionDescriptor(0, TestExtension.class), new DefaultExtensionFactory()));
+ when(extensionFinder.find(TestExtensionPoint.class)).thenReturn(extensionList);
+
+ pluginManager.extensionFinder = extensionFinder;
+ List<TestExtensionPoint> extensions = pluginManager.getExtensions(TestExtensionPoint.class);
+ assertEquals(1, extensions.size());
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java
index a30a4ff..c16839e 100644
--- a/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java
+++ b/pf4j/src/test/java/org/pf4j/CompoundPluginDescriptorFinderTest.java
@@ -15,28 +15,34 @@
*/
package org.pf4j;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.pf4j.plugin.PluginJar;
import org.pf4j.plugin.PluginZip;
+import org.pf4j.plugin.TestPlugin;
-import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* @author Decebal Suiu
*/
public class CompoundPluginDescriptorFinderTest {
- @Rule
- public TemporaryFolder pluginsFolder = new TemporaryFolder();
+ @TempDir
+ Path pluginsPath;
@Test
public void add() {
@@ -49,8 +55,8 @@ public class CompoundPluginDescriptorFinderTest {
@Test
public void find() throws Exception {
- Path pluginPath = pluginsFolder.newFolder("test-plugin-1").toPath();
- Files.write(pluginPath.resolve("plugin.properties"), getPlugin1Properties(), StandardCharsets.UTF_8);
+ Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1"));
+ storePropertiesToPath(getPlugin1Properties(), pluginPath);
PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder()
.add(new PropertiesPluginDescriptorFinder());
@@ -64,31 +70,32 @@ public class CompoundPluginDescriptorFinderTest {
@Test
public void findInJar() throws Exception {
PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder()
- .add(new PropertiesPluginDescriptorFinder());
+ .add(new ManifestPluginDescriptorFinder());
- PluginZip pluginJar = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.jar"), "myPlugin")
+ PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my-plugin-1.2.3.jar"), "myPlugin")
+ .pluginClass(TestPlugin.class.getName())
.pluginVersion("1.2.3")
.build();
PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginJar.path());
assertNotNull(pluginDescriptor);
assertEquals("myPlugin", pluginJar.pluginId());
+ assertEquals(TestPlugin.class.getName(), pluginJar.pluginClass());
assertEquals("1.2.3", pluginJar.pluginVersion());
}
- @Test(expected = PluginException.class)
- public void testNotFound() throws Exception {
+ @Test
+ public void testNotFound() {
PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder();
- Path pluginsPath = pluginsFolder.getRoot().toPath();
- descriptorFinder.find(pluginsPath.resolve("test-plugin-3"));
+ assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3")));
}
@Test
public void testSpaceCharacterInFileName() throws Exception {
- PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder();
- File jar = pluginsFolder.newFile("my plugin-1.2.3.jar");
+ PluginDescriptorFinder descriptorFinder = new CompoundPluginDescriptorFinder()
+ .add(new ManifestPluginDescriptorFinder());
- PluginZip pluginJar = new PluginZip.Builder(jar, "myPlugin")
+ PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("my plugin-1.2.3.jar"), "myPlugin")
.pluginVersion("1.2.3")
.build();
@@ -96,21 +103,24 @@ public class CompoundPluginDescriptorFinderTest {
assertNotNull(pluginDescriptor);
}
- private List<String> getPlugin1Properties() {
- String[] lines = new String[] {
- "plugin.id=test-plugin-1\n"
- + "plugin.version=0.0.1\n"
- + "plugin.description=Test Plugin 1\n"
- + "plugin.provider=Decebal Suiu\n"
- + "plugin.class=org.pf4j.plugin.TestPlugin\n"
- + "plugin.dependencies=test-plugin-2,test-plugin-3@~1.0\n"
- + "plugin.requires=>=1\n"
- + "plugin.license=Apache-2.0\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private Properties getPlugin1Properties() {
+ Map<String, String> map = new LinkedHashMap<>(7);
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName());
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "test-plugin-2,test-plugin-3@~1.0");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, ">=1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_LICENSE, "Apache-2.0");
+
+ return PluginZip.createProperties(map);
+ }
+
+ private void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException {
+ Path path = pluginPath.resolve(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME);
+ try (Writer writer = new OutputStreamWriter(new FileOutputStream(path.toFile()), StandardCharsets.UTF_8)) {
+ properties.store(writer, "");
+ }
}
}
diff --git a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java
index 71ffa93..150828f 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java
@@ -15,26 +15,38 @@
*/
package org.pf4j;
-import org.junit.Test;
-import org.pf4j.plugin.TestExtension;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.pf4j.plugin.FailTestExtension;
+import org.pf4j.plugin.TestExtension;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
/**
- *
* @author Mario Franco
*/
public class DefaultExtensionFactoryTest {
+ private ExtensionFactory extensionFactory;
+
+ @BeforeEach
+ public void setUp() {
+ extensionFactory = new DefaultExtensionFactory();
+ }
+
+ @AfterEach
+ public void tearDown() {
+ extensionFactory = null;
+ }
+
/**
* Test of create method, of class DefaultExtensionFactory.
*/
@Test
public void testCreate() {
- DefaultExtensionFactory instance = new DefaultExtensionFactory();
- Object result = instance.create(TestExtension.class);
- assertNotNull(result);
+ assertNotNull(extensionFactory.create(TestExtension.class));
}
/**
@@ -42,9 +54,7 @@ public class DefaultExtensionFactoryTest {
*/
@Test
public void testCreateFailConstructor() {
- DefaultExtensionFactory instance = new DefaultExtensionFactory();
- Object result = instance.create(FailTestExtension.class);
- assertNull(result);
+ assertThrows(PluginRuntimeException.class, () -> extensionFactory.create(FailTestExtension.class));
}
}
diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java
index f105aa8..eccfca2 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java
@@ -15,15 +15,15 @@
*/
package org.pf4j;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.pf4j.plugin.AnotherFailTestPlugin;
import org.pf4j.plugin.FailTestPlugin;
import org.pf4j.plugin.TestPlugin;
import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java
index 3e6fd04..8cb9b27 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java
@@ -15,21 +15,21 @@
*/
package org.pf4j;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.pf4j.plugin.PluginZip;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -38,14 +38,12 @@ public class DefaultPluginManagerTest {
private DefaultPluginManager pluginManager;
private DefaultPluginDescriptor pluginDescriptor;
private PluginWrapper pluginWrapper;
- private Path pluginsPath;
- @Rule
- public TemporaryFolder pluginsFolder = new TemporaryFolder();
+ @TempDir
+ Path pluginsPath;
- @Before
+ @BeforeEach
public void setUp() throws IOException {
- pluginsPath = pluginsFolder.getRoot().toPath();
pluginManager = new DefaultPluginManager(pluginsPath);
pluginDescriptor = new DefaultPluginDescriptor();
@@ -59,7 +57,7 @@ public class DefaultPluginManagerTest {
pluginWrapper = new PluginWrapper(pluginManager, pluginDescriptor, Files.createTempDirectory("test"), getClass().getClassLoader());
}
- @After
+ @AfterEach
public void tearDown() {
pluginManager = null;
pluginDescriptor = null;
@@ -67,24 +65,24 @@ public class DefaultPluginManagerTest {
}
@Test
- public void validateOK() throws PluginException {
+ public void validateOK() {
pluginManager.validatePluginDescriptor(pluginDescriptor);
}
- @Test(expected = PluginException.class)
- public void validateFailsOnId() throws PluginException {
+ @Test
+ public void validateFailsOnId() {
pluginDescriptor.setPluginId("");
- pluginManager.validatePluginDescriptor(pluginDescriptor);
+ assertThrows(PluginRuntimeException.class, () -> pluginManager.validatePluginDescriptor(pluginDescriptor));
}
- @Test(expected = PluginException.class)
- public void validateFailsOnVersion() throws PluginException {
+ @Test
+ public void validateFailsOnVersion() {
pluginDescriptor.setPluginVersion(null);
- pluginManager.validatePluginDescriptor(pluginDescriptor);
+ assertThrows(PluginRuntimeException.class, () -> pluginManager.validatePluginDescriptor(pluginDescriptor));
}
@Test
- public void validateNoPluginClass() throws PluginException {
+ public void validateNoPluginClass() {
pluginManager.validatePluginDescriptor(pluginDescriptor);
assertEquals(Plugin.class.getName(), pluginDescriptor.getPluginClass());
}
@@ -132,7 +130,7 @@ public class DefaultPluginManagerTest {
*/
@Test
public void testPluginDisabledNoStart() throws IOException {
- new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin")
+ new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin")
.pluginVersion("1.2.3")
.build();
diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java
index 4f39f24..c564543 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultPluginRepositoryTest.java
@@ -15,20 +15,18 @@
*/
package org.pf4j;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.List;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Mario Franco
@@ -36,25 +34,18 @@ import static org.junit.Assert.assertTrue;
*/
public class DefaultPluginRepositoryTest {
- private Path pluginsPath;
+ @TempDir
+ Path pluginsPath;
- @Rule
- public TemporaryFolder pluginsFolder = new TemporaryFolder();
-
- @Before
+ @BeforeEach
public void setUp() throws IOException {
- pluginsPath = pluginsFolder.getRoot().toPath();
-
- pluginsFolder.newFolder("plugin-1");
+ Path plugin1Path = Files.createDirectory(pluginsPath.resolve("plugin-1"));
// Prove that we can delete a folder with a file inside
- Files.createFile(Paths.get(pluginsFolder.getRoot().getAbsolutePath()).resolve("plugin-1").resolve("myfile"));
+ Files.createFile(plugin1Path.resolve("myfile"));
// Create a zip file for plugin-1 to test that it is deleted when plugin is deleted
- Files.createFile(Paths.get(pluginsFolder.getRoot().getAbsolutePath()).resolve("plugin-1.zip"));
- pluginsFolder.newFolder("plugin-2");
- pluginsFolder.newFolder("plugin-3");
- // standard maven/gradle bin folder - these should be skipped in development mode because the cause errors
- pluginsFolder.newFolder("target");
- pluginsFolder.newFolder("build");
+ Files.createFile(pluginsPath.resolve("plugin-1.zip"));
+ Files.createDirectory(pluginsPath.resolve("plugin-2"));
+ Files.createDirectory(pluginsPath.resolve("plugin-3"));
}
/**
@@ -62,29 +53,14 @@ public class DefaultPluginRepositoryTest {
*/
@Test
public void testGetPluginArchives() {
- PluginRepository repository = new DefaultPluginRepository(pluginsPath, false);
+ PluginRepository repository = new DefaultPluginRepository(pluginsPath);
List<Path> pluginPaths = repository.getPluginPaths();
- assertEquals(5, pluginPaths.size());
+ assertEquals(3, pluginPaths.size());
assertPathExists(pluginPaths, pluginsPath.resolve("plugin-1"));
assertPathExists(pluginPaths, pluginsPath.resolve("plugin-2"));
assertPathExists(pluginPaths, pluginsPath.resolve("plugin-3"));
- // when not in development mode we will honor these folders
- assertPathExists(pluginPaths, pluginsPath.resolve("target"));
- assertPathExists(pluginPaths, pluginsPath.resolve("build"));
- }
-
- @Test
- public void testGetPluginArchivesInDevelopmentMode() {
- PluginRepository repository = new DefaultPluginRepository(pluginsPath, true);
-
- List<Path> pluginPaths = repository.getPluginPaths();
-
- // target and build should be ignored
- assertEquals(3, pluginPaths.size());
- assertPathDoesNotExists(pluginPaths, pluginsPath.resolve("target"));
- assertPathDoesNotExists(pluginPaths, pluginsPath.resolve("build"));
}
/**
@@ -92,15 +68,13 @@ public class DefaultPluginRepositoryTest {
*/
@Test
public void testDeletePluginPath() {
- PluginRepository repository = new DefaultPluginRepository(pluginsPath, false);
+ PluginRepository repository = new DefaultPluginRepository(pluginsPath);
assertTrue(Files.exists(pluginsPath.resolve("plugin-1.zip")));
assertTrue(repository.deletePluginPath(pluginsPath.resolve("plugin-1")));
assertFalse(Files.exists(pluginsPath.resolve("plugin-1.zip")));
assertTrue(repository.deletePluginPath(pluginsPath.resolve("plugin-3")));
assertFalse(repository.deletePluginPath(pluginsPath.resolve("plugin-4")));
- assertTrue(repository.deletePluginPath(pluginsPath.resolve("target")));
- assertTrue(repository.deletePluginPath(pluginsPath.resolve("build")));
List<Path> pluginPaths = repository.getPluginPaths();
@@ -109,11 +83,7 @@ public class DefaultPluginRepositoryTest {
}
private void assertPathExists(List<Path> paths, Path path) {
- assertTrue("The directory must contain the file " + path, paths.contains(path));
- }
-
- private void assertPathDoesNotExists(List<Path> paths, Path path) {
- assertFalse("The directory must not contain the file " + path, paths.contains(path));
+ assertTrue(paths.contains(path), "The directory must contain the file " + path);
}
}
diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java
index b3f8d2b..e766735 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultPluginStatusProviderTest.java
@@ -15,20 +15,17 @@
*/
package org.pf4j;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.pf4j.util.FileUtils;
-import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Mario Franco
@@ -36,15 +33,8 @@ import static org.junit.Assert.assertTrue;
*/
public class DefaultPluginStatusProviderTest {
- private Path pluginsPath;
-
- @Rule
- public TemporaryFolder pluginsFolder = new TemporaryFolder();
-
- @Before
- public void setUp() {
- pluginsPath = pluginsFolder.getRoot().toPath();
- }
+ @TempDir
+ Path pluginsPath;
@Test
public void testIsPluginDisabled() throws IOException {
@@ -70,58 +60,59 @@ public class DefaultPluginStatusProviderTest {
}
@Test
- public void testDisablePlugin() throws IOException {
+ public void testDisablePlugin() throws Exception {
createEnabledFile();
createDisabledFile();
PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath);
+ statusProvider.disablePlugin("plugin-1");
- assertTrue(statusProvider.disablePlugin("plugin-1"));
assertTrue(statusProvider.isPluginDisabled("plugin-1"));
assertTrue(statusProvider.isPluginDisabled("plugin-2"));
assertTrue(statusProvider.isPluginDisabled("plugin-3"));
}
@Test
- public void testDisablePluginWithEnableEmpty() throws IOException {
+ public void testDisablePluginWithEnableEmpty() throws Exception {
createDisabledFile();
PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath);
+ statusProvider.disablePlugin("plugin-1");
- assertTrue(statusProvider.disablePlugin("plugin-1"));
assertTrue(statusProvider.isPluginDisabled("plugin-1"));
assertTrue(statusProvider.isPluginDisabled("plugin-2"));
assertFalse(statusProvider.isPluginDisabled("plugin-3"));
}
@Test
- public void testEnablePlugin() throws IOException {
+ public void testEnablePlugin() throws Exception {
createEnabledFile();
PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath);
+ statusProvider.enablePlugin("plugin-2");
- assertTrue(statusProvider.enablePlugin("plugin-2"));
assertFalse(statusProvider.isPluginDisabled("plugin-1"));
assertFalse(statusProvider.isPluginDisabled("plugin-2"));
assertTrue(statusProvider.isPluginDisabled("plugin-3"));
}
@Test
- public void testEnablePluginWithEnableEmpty() {
+ public void testEnablePluginWithEnableEmpty() throws Exception{
PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath);
+ statusProvider.enablePlugin("plugin-2");
- assertTrue(statusProvider.enablePlugin("plugin-2"));
assertFalse(statusProvider.isPluginDisabled("plugin-1"));
assertFalse(statusProvider.isPluginDisabled("plugin-2"));
assertFalse(statusProvider.isPluginDisabled("plugin-3"));
}
@Test
- public void testDisablePluginWithoutDisabledFile() {
+ public void testDisablePluginWithoutDisabledFile() throws Exception {
PluginStatusProvider statusProvider = new DefaultPluginStatusProvider(pluginsPath);
assertFalse(statusProvider.isPluginDisabled("plugin-1"));
- assertTrue(statusProvider.disablePlugin("plugin-1"));
+
+ statusProvider.disablePlugin("plugin-1");
assertTrue(statusProvider.isPluginDisabled("plugin-1"));
}
@@ -129,8 +120,8 @@ public class DefaultPluginStatusProviderTest {
List<String> disabledPlugins = new ArrayList<>();
disabledPlugins.add("plugin-2");
- File disabledFile = pluginsFolder.newFile("disabled.txt");
- FileUtils.writeLines(disabledPlugins, disabledFile);
+ Path disabledPath = pluginsPath.resolve("disabled.txt");
+ FileUtils.writeLines(disabledPlugins, disabledPath.toFile());
}
private void createEnabledFile() throws IOException {
@@ -138,8 +129,8 @@ public class DefaultPluginStatusProviderTest {
enabledPlugins.add("plugin-1");
enabledPlugins.add("plugin-2");
- File enabledFile = pluginsFolder.newFile("enabled.txt");
- FileUtils.writeLines(enabledPlugins, enabledFile);
+ Path enabledPath = pluginsPath.resolve("enabled.txt");
+ FileUtils.writeLines(enabledPlugins, enabledPath.toFile());
}
}
diff --git a/pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java b/pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java
index 795d3cf..3a277db 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultVersionManagerTest.java
@@ -16,10 +16,12 @@
package org.pf4j;
import com.github.zafarkhaja.semver.ParseException;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Decebal Suiu
@@ -28,7 +30,7 @@ public class DefaultVersionManagerTest {
private VersionManager versionManager;
- @Before
+ @BeforeEach
public void init() {
versionManager = new DefaultVersionManager();
}
@@ -39,14 +41,14 @@ public class DefaultVersionManagerTest {
assertTrue(versionManager.checkVersionConstraint("1.4.3", ">=1.4.0 & <1.6.0")); // range
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void nullOrEmptyVersion() {
- assertFalse(versionManager.checkVersionConstraint(null, ">2.0.0"));
+ assertThrows(IllegalArgumentException.class, () -> versionManager.checkVersionConstraint(null, ">2.0.0"));
}
- @Test(expected = ParseException.class)
+ @Test
public void invalidVersion() {
- assertFalse(versionManager.checkVersionConstraint("1.0", ">2.0.0"));
+ assertThrows(ParseException.class, () -> versionManager.checkVersionConstraint("1.0", ">2.0.0"));
}
@Test
diff --git a/pf4j/src/test/java/org/pf4j/DependencyResolverTest.java b/pf4j/src/test/java/org/pf4j/DependencyResolverTest.java
index f7752d4..6e35780 100644
--- a/pf4j/src/test/java/org/pf4j/DependencyResolverTest.java
+++ b/pf4j/src/test/java/org/pf4j/DependencyResolverTest.java
@@ -15,14 +15,16 @@
*/
package org.pf4j;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Decebal Suiu
@@ -31,7 +33,7 @@ public class DependencyResolverTest {
private DependencyResolver resolver;
- @Before
+ @BeforeEach
public void init() {
VersionManager versionManager = new DefaultVersionManager();
resolver = new DependencyResolver(versionManager);
diff --git a/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java
new file mode 100644
index 0000000..20d9129
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/DevelopmentPluginRepositoryTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+/**
+ * @author Decebal Suiu
+ */
+public class DevelopmentPluginRepositoryTest {
+
+ @TempDir
+ Path pluginsPath;
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ // standard maven/gradle bin folder - these should be skipped in development mode because the cause errors
+ Files.createDirectory(pluginsPath.resolve(DevelopmentPluginRepository.MAVEN_BUILD_DIR));
+ Files.createDirectory(pluginsPath.resolve(DevelopmentPluginRepository.GRADLE_BUILD_DIR));
+ }
+
+ @Test
+ public void testGetPluginArchivesInDevelopmentMode() {
+ PluginRepository repository = new DevelopmentPluginRepository(pluginsPath);
+
+ List<Path> pluginPaths = repository.getPluginPaths();
+
+ // target and build should be ignored
+ assertEquals(0, pluginPaths.size());
+ assertPathDoesNotExists(pluginPaths, pluginsPath.resolve(DevelopmentPluginRepository.MAVEN_BUILD_DIR));
+ assertPathDoesNotExists(pluginPaths, pluginsPath.resolve(DevelopmentPluginRepository.GRADLE_BUILD_DIR));
+ }
+
+ private void assertPathDoesNotExists(List<Path> paths, Path path) {
+ assertFalse(paths.contains(path), "The directory must not contain the file " + path);
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java b/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java
index 9edd6b9..47efca8 100644
--- a/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java
+++ b/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java
@@ -15,13 +15,13 @@
*/
package org.pf4j;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.pf4j.processor.ExtensionAnnotationProcessor;
import java.util.Set;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Mario Franco
diff --git a/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java
new file mode 100644
index 0000000..d9ca90a
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/JarPluginManagerTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.pf4j.plugin.PluginJar;
+import org.pf4j.plugin.TestExtension;
+import org.pf4j.plugin.TestExtensionPoint;
+import org.pf4j.plugin.TestPlugin;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class JarPluginManagerTest {
+
+ private PluginJar pluginJar;
+ private JarPluginManager pluginManager;
+
+ @TempDir
+ Path pluginsPath;
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), "test-plugin")
+ .pluginClass(TestPlugin.class.getName())
+ .pluginVersion("1.2.3")
+ .extension(TestExtension.class.getName())
+ .build();
+
+ pluginManager = new JarPluginManager(pluginsPath);
+ }
+
+ @AfterEach
+ public void tearDown() {
+ pluginJar = null;
+ pluginManager = null;
+ }
+
+ @Test
+ public void getExtensions() {
+ pluginManager.loadPlugins();
+ pluginManager.startPlugins();
+
+ List<TestExtensionPoint> extensions = pluginManager.getExtensions(TestExtensionPoint.class);
+ assertEquals(1, extensions.size());
+
+ String something = extensions.get(0).saySomething();
+ assertEquals(new TestExtension().saySomething(), something);
+ }
+
+ @Test
+ public void unloadPlugin() throws Exception {
+ pluginManager.loadPlugins();
+
+ assertEquals(1, pluginManager.getPlugins().size());
+
+ boolean unloaded = pluginManager.unloadPlugin(pluginJar.pluginId());
+ assertTrue(unloaded);
+
+ assertTrue(pluginJar.file().exists());
+ }
+
+ @Test
+ public void deletePlugin() throws Exception {
+ pluginManager.loadPlugins();
+
+ assertEquals(1, pluginManager.getPlugins().size());
+
+ boolean deleted = pluginManager.deletePlugin(pluginJar.pluginId());
+ assertTrue(deleted);
+
+ assertFalse(pluginJar.file().exists());
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java b/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java
new file mode 100644
index 0000000..4501223
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/JarPluginRepositoryTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author Decebal Suiu
+ */
+public class JarPluginRepositoryTest {
+
+ @TempDir
+ Path pluginsPath;
+
+ /**
+ * Test of {@link JarPluginRepository#deletePluginPath(Path)} method.
+ */
+ @Test
+ public void testDeletePluginPath() throws Exception {
+ PluginRepository repository = new JarPluginRepository(pluginsPath);
+
+ Path plugin1Path = Files.createDirectory(pluginsPath.resolve("plugin-1"));
+ Path plugin1JarPath = Files.createFile(pluginsPath.resolve("plugin-1.jar"));
+
+ assertFalse(repository.deletePluginPath(plugin1Path));
+
+ List<Path> pluginPaths = repository.getPluginPaths();
+ assertEquals(1, pluginPaths.size());
+
+ assertTrue(repository.deletePluginPath(plugin1JarPath));
+
+ pluginPaths = repository.getPluginPaths();
+ assertEquals(0, pluginPaths.size());
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java
new file mode 100644
index 0000000..8f5a727
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/LegacyExtensionFinderTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.io.TempDir;
+import org.pf4j.plugin.PluginJar;
+import org.pf4j.plugin.TestExtension;
+import org.pf4j.plugin.TestPlugin;
+
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Set;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.condition.OS.WINDOWS;
+
+public class LegacyExtensionFinderTest {
+
+ @TempDir
+ Path pluginsPath;
+
+ @Test
+ @EnabledOnOs(WINDOWS)
+ public void shouldUnlockFileAfterReadingExtensionsFromPlugin() throws Exception {
+ PluginJar pluginJar = new PluginJar.Builder(pluginsPath.resolve("test-plugin.jar"), "test-plugin")
+ .pluginClass(TestPlugin.class.getName())
+ .pluginVersion("1.2.3")
+ .extension(TestExtension.class.getName())
+ .build();
+
+ assertTrue(pluginJar.file().exists());
+
+ PluginManager pluginManager = new JarPluginManager(pluginsPath);
+ pluginManager.loadPlugins();
+
+ assertEquals(1, pluginManager.getPlugins().size());
+
+ LegacyExtensionFinder extensionFinder = new LegacyExtensionFinder(pluginManager);
+ Map<String, Set<String>> pluginsStorages = extensionFinder.readPluginsStorages();
+ assertNotNull(pluginsStorages);
+
+ pluginManager.unloadPlugin(pluginJar.pluginId());
+ boolean fileDeleted = pluginJar.file().delete();
+
+ Set<String> pluginStorages = pluginsStorages.get(pluginJar.pluginId());
+ assertNotNull(pluginStorages);
+ assertEquals(1, pluginStorages.size());
+ assertThat(pluginStorages, contains(TestExtension.class.getName()));
+ assertTrue(fileDeleted);
+ assertFalse(pluginJar.file().exists());
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java b/pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java
index 57125bd..1acc567 100644
--- a/pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java
+++ b/pf4j/src/test/java/org/pf4j/LegacyExtensionStorageTest.java
@@ -15,7 +15,7 @@
*/
package org.pf4j;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.pf4j.processor.LegacyExtensionStorage;
import java.io.IOException;
@@ -24,7 +24,7 @@ import java.io.StringReader;
import java.util.HashSet;
import java.util.Set;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author Decebal Suiu
diff --git a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java
index c2917e8..e3dac02 100644
--- a/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java
+++ b/pf4j/src/test/java/org/pf4j/LoadPluginsTest.java
@@ -15,42 +15,42 @@
*/
package org.pf4j;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.startsWith;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.pf4j.plugin.PluginZip;
+
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.pf4j.plugin.PluginZip;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
public class LoadPluginsTest {
private DefaultPluginManager pluginManager;
- @Rule
- public TemporaryFolder pluginsFolder = new TemporaryFolder();
+ @TempDir
+ Path pluginsPath;
- @Before
+ @BeforeEach
public void setUp() {
- pluginManager = new DefaultPluginManager(pluginsFolder.getRoot().toPath());
+ pluginManager = new DefaultPluginManager(pluginsPath);
}
@Test
public void load() throws Exception {
- PluginZip pluginZip = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin")
+ PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin")
.pluginVersion("1.2.3")
.build();
@@ -64,31 +64,32 @@ public class LoadPluginsTest {
assertEquals(pluginZip.pluginId(), pluginManager.idForPath(pluginZip.unzippedPath()));
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void loadNonExisting() {
- pluginManager.loadPlugin(Paths.get("nonexisting"));
+ assertThrows(IllegalArgumentException.class, () -> pluginManager.loadPlugin(Paths.get("nonexisting")));
}
- @Test(expected = PluginAlreadyLoadedException.class)
+ @Test
public void loadTwiceFails() throws Exception {
- PluginZip pluginZip = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin")
+ PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin")
.pluginVersion("1.2.3")
.build();
assertNotNull(pluginManager.loadPluginFromPath(pluginZip.path()));
- assertNull(pluginManager.loadPluginFromPath(pluginZip.path()));
+
+ assertThrows(PluginAlreadyLoadedException.class, () -> pluginManager.loadPluginFromPath(pluginZip.path()));
}
@Test
public void loadPluginWithSameIdDifferentPathFails() throws Exception {
String pluginId = "myPlugin";
String pluginVersion = "1.2.3";
- File plugin1Path = pluginsFolder.newFile("my-plugin-1.2.3.zip");
+ Path plugin1Path = pluginsPath.resolve("my-plugin-1.2.3.zip");
PluginZip plugin1 = new PluginZip.Builder(plugin1Path, pluginId)
.pluginVersion(pluginVersion)
.build();
- File plugin2Path = pluginsFolder.newFile("my-plugin-1.2.3-renamed.zip");
+ Path plugin2Path = pluginsPath.resolve("my-plugin-1.2.3-renamed.zip");
PluginZip plugin2 = new PluginZip.Builder(plugin2Path, pluginId)
.pluginVersion(pluginVersion)
.build();
@@ -101,7 +102,7 @@ public class LoadPluginsTest {
// Verify the second plugin is not loaded as it has the same metadata
pluginManager.loadPluginFromPath(plugin2.path());
fail("Expected loadPluginFromPath to fail");
- } catch (PluginException e) {
+ } catch (PluginRuntimeException e) {
// Check the path of the loaded plugin remains the same
PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId);
assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path));
@@ -122,13 +123,13 @@ public class LoadPluginsTest {
public void loadPluginWithSameIdDifferentVersionsFails() throws Exception {
String pluginId = "myPlugin";
String plugin1Version = "1.2.3";
- File plugin1Path = pluginsFolder.newFile("my-plugin-1.2.3.zip");
+ Path plugin1Path = pluginsPath.resolve("my-plugin-1.2.3.zip");
PluginZip plugin1 = new PluginZip.Builder(plugin1Path, pluginId)
.pluginVersion(plugin1Version)
.build();
String plugin2Version = "2.0.0";
- File plugin2Path = pluginsFolder.newFile("my-plugin-2.0.0.zip");
+ Path plugin2Path = pluginsPath.resolve("my-plugin-2.0.0.zip");
PluginZip plugin2 = new PluginZip.Builder(plugin2Path, pluginId)
.pluginVersion(plugin2Version)
.build();
@@ -140,7 +141,7 @@ public class LoadPluginsTest {
// Verify the second plugin is not loaded as it has the same pluginId
pluginManager.loadPluginFromPath(plugin2.path());
fail("Expected loadPluginFromPath to fail");
- } catch (PluginException e) {
+ } catch (PluginRuntimeException e) {
// Check the path and version of the loaded plugin remain the same
PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId);
assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path));
@@ -150,7 +151,7 @@ public class LoadPluginsTest {
@Test
public void loadUnloadLoad() throws Exception {
- PluginZip pluginZip = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin")
+ PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin")
.pluginVersion("1.2.3")
.build();
@@ -169,7 +170,7 @@ public class LoadPluginsTest {
public void upgrade() throws Exception {
String pluginId = "myPlugin";
- new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), pluginId)
+ new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginId)
.pluginVersion("1.2.3")
.build();
@@ -179,7 +180,7 @@ public class LoadPluginsTest {
assertEquals(1, pluginManager.getPlugins().size());
assertEquals(1, pluginManager.getStartedPlugins().size());
- PluginZip pluginZip2 = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-2.0.0.ZIP"), pluginId)
+ PluginZip pluginZip2 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-2.0.0.ZIP"), pluginId)
.pluginVersion("2.0.0")
.build();
@@ -196,12 +197,12 @@ public class LoadPluginsTest {
@Test
public void getRoot() {
- assertEquals(pluginsFolder.getRoot().toPath(), pluginManager.getPluginsRoot());
+ assertEquals(pluginsPath, pluginManager.getPluginsRoot());
}
@Test
- public void notAPlugin() throws Exception {
- pluginsFolder.newFile("not-a-zip");
+ public void notAPlugin() {
+ pluginsPath.resolve("not-a-zip");
pluginManager.loadPlugins();
@@ -210,11 +211,11 @@ public class LoadPluginsTest {
@Test
public void deletePlugin() throws Exception {
- PluginZip pluginZip1 = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin")
+ PluginZip pluginZip1 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin")
.pluginVersion("1.2.3")
.build();
- PluginZip pluginZip3 = new PluginZip.Builder(pluginsFolder.newFile("other-3.0.0.Zip"), "other")
+ PluginZip pluginZip3 = new PluginZip.Builder(pluginsPath.resolve("other-3.0.0.Zip"), "other")
.pluginVersion("3.0.0")
.build();
diff --git a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java
index bc4eb5f..468f2fb 100644
--- a/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java
+++ b/pf4j/src/test/java/org/pf4j/ManifestPluginDescriptorFinderTest.java
@@ -15,19 +15,23 @@
*/
package org.pf4j;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.pf4j.plugin.PluginJar;
+import java.io.FileOutputStream;
import java.io.IOException;
-import java.nio.charset.Charset;
+import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.jar.Manifest;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Mario Franco
@@ -36,42 +40,32 @@ import static org.junit.Assert.*;
public class ManifestPluginDescriptorFinderTest {
private VersionManager versionManager;
- private Path pluginsPath;
- @Rule
- public TemporaryFolder pluginsFolder = new TemporaryFolder();
+ @TempDir
+ Path pluginsPath;
- @Before
+ @BeforeEach
public void setUp() throws IOException {
- pluginsPath = pluginsFolder.getRoot().toPath();
+ Path pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-1"));
+ storeManifestToPath(getPlugin1Manifest(), pluginPath);
- Charset charset = Charset.forName("UTF-8");
-
- Path pluginPath = pluginsFolder.newFolder("test-plugin-1", "classes", "META-INF").toPath();
- Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes());
- Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin1Manifest(), charset);
-
- pluginPath = pluginsFolder.newFolder("test-plugin-2", "classes", "META-INF").toPath();
- Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes());
- Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin2Manifest(), charset);
+ pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-2"));
+ storeManifestToPath(getPlugin2Manifest(), pluginPath);
// empty plugin
- pluginsFolder.newFolder("test-plugin-3");
+ Files.createDirectories(pluginsPath.resolve("test-plugin-3"));
// no plugin class
- pluginPath = pluginsFolder.newFolder("test-plugin-4", "classes", "META-INF").toPath();
- Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes());
- Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin4Manifest(), charset);
+ pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-4"));
+ storeManifestToPath(getPlugin4Manifest(), pluginPath);
// no plugin version
- pluginPath = pluginsFolder.newFolder("test-plugin-5", "classes", "META-INF").toPath();
- Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes());
- Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin5Manifest(), charset);
+ pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-5"));
+ storeManifestToPath(getPlugin5Manifest(), pluginPath);
// no plugin id
- pluginPath = pluginsFolder.newFolder("test-plugin-6", "classes", "META-INF").toPath();
- Files.write(pluginPath.resolve("extensions.idx"), "org.pf4j.demo.hello.HelloPlugin$HelloGreeting".getBytes());
- Files.write(pluginPath.resolve("MANIFEST.MF"), getPlugin6Manifest(), charset);
+ pluginPath = Files.createDirectories(pluginsPath.resolve("test-plugin-6"));
+ storeManifestToPath(getPlugin6Manifest(), pluginPath);
versionManager = new DefaultVersionManager();
}
@@ -110,126 +104,68 @@ public class ManifestPluginDescriptorFinderTest {
/**
* Test of {@link ManifestPluginDescriptorFinder#find(Path)} method.
*/
- @Test(expected = PluginException.class)
- public void testFindNotFound() throws Exception {
+ @Test
+ public void testFindNotFound() {
PluginDescriptorFinder descriptorFinder = new ManifestPluginDescriptorFinder();
- descriptorFinder.find(pluginsPath.resolve("test-plugin-3"));
+ assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3")));
}
- private List<String> getPlugin1Manifest() {
- String[] lines = new String[] {
- "Manifest-Version: 1.0\n"
- + "Implementation-Title: Test Plugin #1\n"
- + "Implementation-Version: 0.10.0-SNAPSHOT\n"
- + "Archiver-Version: Plexus Archiver\n"
- + "Built-By: Mario Franco\n"
- + "Specification-Title: Test Plugin #1\n"
- + "Implementation-Vendor-Id: org.pf4j.demo\n"
- + "Plugin-Version: 0.0.1\n"
- + "Plugin-Id: test-plugin-1\n"
- + "Plugin-Description: Test Plugin 1\n"
- + "Plugin-Provider: Decebal Suiu\n"
- + "Plugin-Class: org.pf4j.plugin.TestPlugin\n"
- + "Plugin-Dependencies: test-plugin-2,test-plugin-3@~1.0\n"
- + "Plugin-Requires: *\n"
- + "Plugin-License: Apache-2.0\n"
- + "Created-By: Apache Maven 3.0.5\n"
- + "Build-Jdk: 1.8.0_45\n"
- + "Specification-Version: 0.10.0-SNAPSHOT\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private Manifest getPlugin1Manifest() {
+ Map<String, String> map = new LinkedHashMap<>(8);
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_DESCRIPTION, "Test Plugin 1");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "test-plugin-2,test-plugin-3@~1.0");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_REQUIRES, "*");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_LICENSE, "Apache-2.0");
+
+ return PluginJar.createManifest(map);
}
- private List<String> getPlugin2Manifest() {
- String[] lines = new String[] {
- "Manifest-Version: 1.0\n"
- + "Plugin-Dependencies: \n"
- + "Implementation-Title: Test Plugin #2\n"
- + "Implementation-Version: 0.10.0-SNAPSHOT\n"
- + "Archiver-Version: Plexus Archiver\n"
- + "Built-By: Mario Franco\n"
- + "Specification-Title: Test Plugin #2\n"
- + "Implementation-Vendor-Id: org.pf4j.demo\n"
- + "Plugin-Version: 0.0.1\n"
- + "Plugin-Id: test-plugin-2\n"
- + "Plugin-Provider: Decebal Suiu\n"
- + "Plugin-Class: org.pf4j.plugin.TestPlugin\n"
- + "Created-By: Apache Maven 3.0.5\n"
- + "Build-Jdk: 1.8.0_45\n"
- + "Specification-Version: 0.10.0-SNAPSHOT\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private Manifest getPlugin2Manifest() {
+ Map<String, String> map = new LinkedHashMap<>(5);
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "");
+
+ return PluginJar.createManifest(map);
}
- private List<String> getPlugin4Manifest() {
- String[] lines = new String[] {
- "Manifest-Version: 1.0\n"
- + "Implementation-Title: Test Plugin #4\n"
- + "Implementation-Version: 0.10.0-SNAPSHOT\n"
- + "Archiver-Version: Plexus Archiver\n"
- + "Built-By: Mario Franco\n"
- + "Specification-Title: Test Plugin #4\n"
- + "Implementation-Vendor-Id: org.pf4j.demo\n"
- + "Plugin-Version: 0.0.1\n"
- + "Plugin-Id: test-plugin-2\n"
- + "Plugin-Provider: Decebal Suiu\n"
- + "Created-By: Apache Maven 3.0.5\n"
- + "Build-Jdk: 1.8.0_45\n"
- + "Specification-Version: 0.10.0-SNAPSHOT\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private Manifest getPlugin4Manifest() {
+ Map<String, String> map = new LinkedHashMap<>(3);
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+
+ return PluginJar.createManifest(map);
}
- private List<String> getPlugin5Manifest() {
- String[] lines = new String[] {
- "Manifest-Version: 1.0\n"
- + "Implementation-Title: Test Plugin #5\n"
- + "Implementation-Version: 0.10.0-SNAPSHOT\n"
- + "Archiver-Version: Plexus Archiver\n"
- + "Built-By: Mario Franco\n"
- + "Specification-Title: Test Plugin #5\n"
- + "Implementation-Vendor-Id: org.pf4j.demo\n"
- + "Plugin-Id: test-plugin-2\n"
- + "Plugin-Provider: Decebal Suiu\n"
- + "Plugin-Class: org.pf4j.plugin.TestPlugin\n"
- + "Created-By: Apache Maven 3.0.5\n"
- + "Build-Jdk: 1.8.0_45\n"
- + "Specification-Version: 0.10.0-SNAPSHOT\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private Manifest getPlugin5Manifest() {
+ Map<String, String> map = new LinkedHashMap<>(3);
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+
+ return PluginJar.createManifest(map);
+ }
+
+ private Manifest getPlugin6Manifest() {
+ Map<String, String> map = new LinkedHashMap<>(2);
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_CLASS, "org.pf4j.plugin.TestPlugin");
+ map.put(ManifestPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+
+ return PluginJar.createManifest(map);
}
- private List<String> getPlugin6Manifest() {
- String[] lines = new String[] {
- "Manifest-Version: 1.0\n"
- + "Implementation-Title: Test Plugin #6\n"
- + "Implementation-Version: 0.10.0-SNAPSHOT\n"
- + "Archiver-Version: Plexus Archiver\n"
- + "Built-By: Mario Franco\n"
- + "Specification-Title: Test Plugin #6\n"
- + "Implementation-Vendor-Id: org.pf4j.demo\n"
- + "Plugin-Provider: Decebal Suiu\n"
- + "Plugin-Class: org.pf4j.plugin.TestPlugin\n"
- + "Created-By: Apache Maven 3.0.5\n"
- + "Build-Jdk: 1.8.0_45\n"
- + "Specification-Version: 0.10.0-SNAPSHOT\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private void storeManifestToPath(Manifest manifest, Path pluginPath) throws IOException {
+ Path path = Files.createDirectory(pluginPath.resolve("META-INF"));
+ try (OutputStream output = new FileOutputStream(path.resolve("MANIFEST.MF").toFile())) {
+ manifest.write(output);
+ }
}
}
diff --git a/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java b/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java
index dbd5fd9..a351c4b 100644
--- a/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java
+++ b/pf4j/src/test/java/org/pf4j/PluginDependencyTest.java
@@ -15,9 +15,12 @@
*/
package org.pf4j;
-import org.junit.Test;
-import static org.junit.Assert.*;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Mario Franco
@@ -32,33 +35,33 @@ public class PluginDependencyTest {
PluginDependency instance = new PluginDependency("test");
assertEquals("test", instance.getPluginId());
assertEquals("*", instance.getPluginVersionSupport());
- assertEquals(false, instance.isOptional());
+ assertFalse(instance.isOptional());
instance = new PluginDependency("test@");
assertEquals("test", instance.getPluginId());
assertEquals("*", instance.getPluginVersionSupport());
- assertEquals(false, instance.isOptional());
+ assertFalse(instance.isOptional());
instance = new PluginDependency("test?");
assertEquals("test", instance.getPluginId());
assertEquals("*", instance.getPluginVersionSupport());
- assertEquals(true, instance.isOptional());
+ assertTrue(instance.isOptional());
instance = new PluginDependency("test?@");
assertEquals("test", instance.getPluginId());
assertEquals("*", instance.getPluginVersionSupport());
- assertEquals(true, instance.isOptional());
+ assertTrue(instance.isOptional());
instance = new PluginDependency("test@1.0");
assertEquals("test", instance.getPluginId());
assertEquals("1.0", instance.getPluginVersionSupport());
- assertEquals(false, instance.isOptional());
+ assertFalse(instance.isOptional());
assertEquals("PluginDependency [pluginId=test, pluginVersionSupport=1.0, optional=false]", instance.toString());
instance = new PluginDependency("test?@1.0");
assertEquals("test", instance.getPluginId());
assertEquals("1.0", instance.getPluginVersionSupport());
- assertEquals(true, instance.isOptional());
+ assertTrue(instance.isOptional());
assertEquals("PluginDependency [pluginId=test, pluginVersionSupport=1.0, optional=true]", instance.toString());
}
diff --git a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java
index 377d5ca..bc91a7f 100644
--- a/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java
+++ b/pf4j/src/test/java/org/pf4j/PropertiesPluginDescriptorFinderTest.java
@@ -15,55 +15,57 @@
*/
package org.pf4j;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.pf4j.plugin.PluginZip;
+import org.pf4j.plugin.TestPlugin;
+import java.io.FileOutputStream;
import java.io.IOException;
-import java.nio.charset.Charset;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class PropertiesPluginDescriptorFinderTest {
private VersionManager versionManager;
- private Path pluginsPath;
- @Rule
- public TemporaryFolder pluginsFolder = new TemporaryFolder();
+ @TempDir
+ Path pluginsPath;
- @Before
+ @BeforeEach
public void setUp() throws IOException {
- pluginsPath = pluginsFolder.getRoot().toPath();
+ Path pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-1"));
+ storePropertiesToPath(getPlugin1Properties(), pluginPath);
- Charset charset = Charset.forName("UTF-8");
-
- Path pluginPath = pluginsFolder.newFolder("test-plugin-1").toPath();
- Files.write(pluginPath.resolve("plugin.properties"), getPlugin1Properties(), charset);
-
- pluginPath = pluginsFolder.newFolder("test-plugin-2").toPath();
- Files.write(pluginPath.resolve("plugin.properties"), getPlugin2Properties(), charset);
+ pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-2"));
+ storePropertiesToPath(getPlugin2Properties(), pluginPath);
// empty plugin
- pluginsFolder.newFolder("test-plugin-3");
+ Files.createDirectories(pluginsPath.resolve("test-plugin-3"));
// no plugin class
- pluginPath = pluginsFolder.newFolder("test-plugin-4").toPath();
- Files.write(pluginPath.resolve("plugin.properties"), getPlugin4Properties(), charset);
+ pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-4"));
+ storePropertiesToPath(getPlugin4Properties(), pluginPath);
// no plugin version
- pluginPath = pluginsFolder.newFolder("test-plugin-5").toPath();
- Files.write(pluginPath.resolve("plugin.properties"), getPlugin5Properties(), charset);
+ pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-5"));
+ storePropertiesToPath(getPlugin5Properties(), pluginPath);
// no plugin id
- pluginPath = pluginsFolder.newFolder("test-plugin-6").toPath();
- Files.write(pluginPath.resolve("plugin.properties"), getPlugin6Properties(), charset);
+ pluginPath = Files.createDirectory(pluginsPath.resolve("test-plugin-6"));
+ storePropertiesToPath(getPlugin6Properties(), pluginPath);
versionManager = new DefaultVersionManager();
}
@@ -77,7 +79,7 @@ public class PropertiesPluginDescriptorFinderTest {
assertEquals("test-plugin-1", plugin1.getPluginId());
assertEquals("Test Plugin 1", plugin1.getPluginDescription());
- assertEquals("org.pf4j.plugin.TestPlugin", plugin1.getPluginClass());
+ assertEquals(TestPlugin.class.getName(), plugin1.getPluginClass());
assertEquals("0.0.1", plugin1.getVersion());
assertEquals("Decebal Suiu", plugin1.getProvider());
assertEquals(2, plugin1.getDependencies().size());
@@ -91,7 +93,7 @@ public class PropertiesPluginDescriptorFinderTest {
assertEquals("test-plugin-2", plugin2.getPluginId());
assertEquals("", plugin2.getPluginDescription());
- assertEquals("org.pf4j.plugin.TestPlugin", plugin2.getPluginClass());
+ assertEquals(TestPlugin.class.getName(), plugin2.getPluginClass());
assertEquals("0.0.1", plugin2.getVersion());
assertEquals("Decebal Suiu", plugin2.getProvider());
assertEquals(0, plugin2.getDependencies().size());
@@ -99,98 +101,75 @@ public class PropertiesPluginDescriptorFinderTest {
assertTrue(versionManager.checkVersionConstraint("1.0.0", plugin2.getRequires()));
}
- @Test(expected = PluginException.class)
- public void testNotFound() throws Exception {
+ @Test
+ public void testNotFound() {
PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder();
- descriptorFinder.find(pluginsPath.resolve("test-plugin-3"));
+ assertThrows(PluginRuntimeException.class, () -> descriptorFinder.find(pluginsPath.resolve("test-plugin-3")));
}
- @Test
- public void findInJar() throws Exception {
- PluginZip pluginJar = new PluginZip.Builder(pluginsFolder.newFile("my-plugin-1.2.3.jar"), "myPlugin")
- .pluginVersion("1.2.3")
- .build();
+ private Properties getPlugin1Properties() {
+ Map<String, String> map = new LinkedHashMap<>(8);
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName());
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_DESCRIPTION, "Test Plugin 1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "test-plugin-2,test-plugin-3@~1.0");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, ">=1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_LICENSE, "Apache-2.0");
+
+ return PluginZip.createProperties(map);
+ }
- assertTrue(Files.exists(pluginJar.path()));
+ private Properties getPlugin2Properties() {
+ Map<String, String> map = new LinkedHashMap<>(5);
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName());
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "");
- PluginDescriptorFinder descriptorFinder = new PropertiesPluginDescriptorFinder();
- PluginDescriptor pluginDescriptor = descriptorFinder.find(pluginJar.path());
- assertNotNull(pluginDescriptor);
- assertEquals("myPlugin", pluginJar.pluginId());
- assertEquals("1.2.3", pluginJar.pluginVersion());
+ return PluginZip.createProperties(map);
}
- private List<String> getPlugin1Properties() {
- String[] lines = new String[] {
- "plugin.id=test-plugin-1\n"
- + "plugin.version=0.0.1\n"
- + "plugin.description=Test Plugin 1\n"
- + "plugin.provider=Decebal Suiu\n"
- + "plugin.class=org.pf4j.plugin.TestPlugin\n"
- + "plugin.dependencies=test-plugin-2,test-plugin-3@~1.0\n"
- + "plugin.requires=>=1\n"
- + "plugin.license=Apache-2.0\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
- }
+ private Properties getPlugin4Properties() {
+ Map<String, String> map = new LinkedHashMap<>(5);
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*");
- private List<String> getPlugin2Properties() {
- String[] lines = new String[] {
- "plugin.id=test-plugin-2\n"
- + "plugin.version=0.0.1\n"
- + "plugin.provider=Decebal Suiu\n"
- + "plugin.class=org.pf4j.plugin.TestPlugin\n"
- + "plugin.dependencies=\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ return PluginZip.createProperties(map);
}
- private List<String> getPlugin4Properties() {
- String[] lines = new String[] {
- "plugin.id=test-plugin-2\n"
- + "plugin.version=0.0.1\n"
- + "plugin.provider=Decebal Suiu\n"
- + "plugin.dependencies=\n"
- + "plugin.requires=*\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private Properties getPlugin5Properties() {
+ Map<String, String> map = new LinkedHashMap<>(5);
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_ID, "test-plugin-2");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName());
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*");
+
+ return PluginZip.createProperties(map);
}
- private List<String> getPlugin5Properties() {
- String[] lines = new String[] {
- "plugin.id=test-plugin-2\n"
- + "plugin.provider=Decebal Suiu\n"
- + "plugin.class=org.pf4j.plugin.TestPlugin\n"
- + "plugin.dependencies=\n"
- + "plugin.requires=*\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private Properties getPlugin6Properties() {
+ Map<String, String> map = new LinkedHashMap<>(5);
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_CLASS, TestPlugin.class.getName());
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_VERSION, "0.0.1");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_PROVIDER, "Decebal Suiu");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_DEPENDENCIES, "");
+ map.put(PropertiesPluginDescriptorFinder.PLUGIN_REQUIRES, "*");
+
+ return PluginZip.createProperties(map);
}
- private List<String> getPlugin6Properties() {
- String[] lines = new String[] {
- "plugin.version=0.0.1\n"
- + "plugin.provider=Decebal Suiu\n"
- + "plugin.class=org.pf4j.plugin.TestPlugin\n"
- + "plugin.dependencies=\n"
- + "plugin.requires=*\n"
- + "\n"
- + ""
- };
-
- return Arrays.asList(lines);
+ private void storePropertiesToPath(Properties properties, Path pluginPath) throws IOException {
+ Path path = pluginPath.resolve(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME);
+ try (Writer writer = new OutputStreamWriter(new FileOutputStream(path.toFile()), StandardCharsets.UTF_8)) {
+ properties.store(writer, "");
+ }
}
}
diff --git a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java
index 500dd84..80e7ab0 100644
--- a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java
+++ b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java
@@ -15,11 +15,12 @@
*/
package org.pf4j;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.pf4j.plugin.FailTestExtension;
import org.pf4j.plugin.TestExtension;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertSame;
/**
* @author Decebal Suiu
diff --git a/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java b/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java
new file mode 100644
index 0000000..ff55967
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/plugin/ClassDataProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j.plugin;
+
+/**
+ * Defines the interface for classes that know to supply class data for a class name.
+ * The idea is to have the possibility to retrieve the data for a class from different sources:
+ * <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);
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java b/pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java
new file mode 100644
index 0000000..ef0eaf9
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/plugin/DefaultClassDataProvider.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j.plugin;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Get class data from the class path.
+ *
+ * @author Decebal Suiu
+ */
+public class DefaultClassDataProvider implements ClassDataProvider {
+
+ @Override
+ public byte[] getClassData(String className) {
+ String path = className.replace('.', '/') + ".class";
+ InputStream classDataStream = getClass().getClassLoader().getResourceAsStream(path);
+ if (classDataStream == null) {
+ throw new RuntimeException("Cannot find class data");
+ }
+
+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+ copyStream(classDataStream, outputStream);
+ return outputStream.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ private void copyStream(InputStream in, OutputStream out) throws IOException {
+ byte[] buffer = new byte[1024];
+
+ int bytesRead;
+ while ((bytesRead = in.read(buffer)) != -1) {
+ out.write(buffer, 0, bytesRead);
+ }
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java b/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java
index 9cc37e0..13b51ee 100644
--- a/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java
+++ b/pf4j/src/test/java/org/pf4j/plugin/FailTestExtension.java
@@ -26,4 +26,9 @@ public class FailTestExtension implements TestExtensionPoint {
public FailTestExtension(String name) {
}
+ @Override
+ public String saySomething() {
+ return "I am a fail test extension";
+ }
+
}
diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java
new file mode 100644
index 0000000..a75b68f
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/plugin/PluginJar.java
@@ -0,0 +1,200 @@
+/*
+ * 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();
+ }
+ }
+ jarOutputStream.close();
+ }
+
+ 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();
+ }
+ }
+
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java
index f069365..f34d84a 100644
--- a/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java
+++ b/pf4j/src/test/java/org/pf4j/plugin/PluginZip.java
@@ -15,44 +15,54 @@
*/
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 zip/jar file.
- * The "plugin.properties" file is created on the fly from the information supplied in Builder.
+ * Represents a plugin {@code zip} file.
+ * The {@code plugin.properties} file is created on the fly from the information supplied in {@link Builder}.
*
* @author Decebal Suiu
*/
public class PluginZip {
- private final File file;
+ private final Path path;
private final String pluginId;
+ private final String pluginClass;
private final String pluginVersion;
protected PluginZip(Builder builder) {
- this.file = builder.file;
+ this.path = builder.path;
this.pluginId = builder.pluginId;
+ this.pluginClass = builder.pluginClass;
this.pluginVersion = builder.pluginVersion;
}
- public File file() {
- return file;
+ public Path path() {
+ return path;
}
- public Path path() {
- return file.toPath();
+ public File file() {
+ return path.toFile();
}
public String pluginId() {
return pluginId;
}
+ public String pluginClass() {
+ return pluginClass;
+ }
+
public String pluginVersion() {
return pluginVersion;
}
@@ -64,24 +74,59 @@ public class PluginZip {
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 File file;
+ private final Path path;
private final String pluginId;
+ private String pluginClass;
private String pluginVersion;
+ private Map<String, String> properties = new LinkedHashMap<>();
- public Builder(File file, String pluginId) {
- this.file = file;
+ 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;
+ }
+
public PluginZip build() throws IOException {
createPropertiesFile();
@@ -89,15 +134,20 @@ public class PluginZip {
}
protected void createPropertiesFile() throws IOException {
- Properties properties = new Properties();
- properties.setProperty("plugin.id", pluginId);
- properties.setProperty("plugin.version", pluginVersion);
- properties.setProperty("plugin.class", "org.pf4j.plugin.TestPlugin");
-
- ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(file));
- ZipEntry propertiesFile = new ZipEntry("plugin.properties");
+ 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);
+ }
+
+ ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(path.toFile()));
+ ZipEntry propertiesFile = new ZipEntry(PropertiesPluginDescriptorFinder.DEFAULT_PROPERTIES_FILE_NAME);
outputStream.putNextEntry(propertiesFile);
- properties.store(outputStream, "");
+ createProperties(map).store(outputStream, "");
outputStream.closeEntry();
outputStream.close();
}
diff --git a/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java b/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java
index 5f48c9a..83bc0b5 100644
--- a/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java
+++ b/pf4j/src/test/java/org/pf4j/plugin/TestExtension.java
@@ -23,4 +23,9 @@ import org.pf4j.Extension;
@Extension
public class TestExtension implements TestExtensionPoint {
+ @Override
+ public String saySomething() {
+ return "I am a test extension";
+ }
+
}
diff --git a/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java b/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java
index a33ac40..d29a7ab 100644
--- a/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java
+++ b/pf4j/src/test/java/org/pf4j/plugin/TestExtensionPoint.java
@@ -22,4 +22,6 @@ import org.pf4j.ExtensionPoint;
*/
public interface TestExtensionPoint extends ExtensionPoint {
+ String saySomething();
+
}
diff --git a/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java b/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java
index 2c450a0..ac16b23 100644
--- a/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java
+++ b/pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java
@@ -16,19 +16,23 @@
package org.pf4j.processor;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import javax.annotation.processing.Filer;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.IOException;
import java.io.StringReader;
-import java.util.*;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
-import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
/**
@@ -46,7 +50,6 @@ public class ServiceProviderExtensionStorageTest {
assertThat(entries.contains("World"), is(true));
}
-
@Test
public void ensureReadingExtensionsProducesCorrectListOfExtensions() {
final StringReader file = new StringReader("#hello\n World");
@@ -56,6 +59,7 @@ public class ServiceProviderExtensionStorageTest {
given(processor.getExtensions()).willReturn(extensions);
ServiceProviderExtensionStorage extensionStorage = new ServiceProviderExtensionStorage(processor) {
+
@Override
protected Filer getFiler() {
try {
@@ -72,6 +76,7 @@ public class ServiceProviderExtensionStorageTest {
throw new IllegalStateException("Shouldn't have gotten here");
}
}
+
};
Map<String, Set<String>> read = extensionStorage.read();
diff --git a/pf4j/src/test/java/org/pf4j/util/DirectedGraphTest.java b/pf4j/src/test/java/org/pf4j/util/DirectedGraphTest.java
new file mode 100644
index 0000000..44b8c54
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/util/DirectedGraphTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2015 Decebal Suiu
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pf4j.util;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author Decebal Suiu
+ */
+public class DirectedGraphTest {
+
+ private static DirectedGraph<Character> graph;
+
+ @BeforeAll
+ public static void setUp() {
+ graph = new DirectedGraph<>();
+
+ // add vertex
+ graph.addVertex('A');
+ graph.addVertex('B');
+ graph.addVertex('C');
+ graph.addVertex('D');
+ graph.addVertex('E');
+ graph.addVertex('F');
+ graph.addVertex('G');
+
+ // add edges
+ graph.addEdge('A', 'B');
+ graph.addEdge('B', 'C');
+ graph.addEdge('B', 'F');
+ graph.addEdge('D', 'E');
+ graph.addEdge('F', 'G');
+ }
+
+ @Test
+ public void reverseTopologicalSort() {
+ List<Character> result = graph.reverseTopologicalSort();
+ List<Character> expected = Arrays.asList('C', 'G', 'F', 'B', 'A', 'E', 'D');
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void topologicalSort() {
+ List<Character> result = graph.topologicalSort();
+ List<Character> expected = Arrays.asList('D', 'E', 'A', 'B', 'F', 'G', 'C');
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void inDegree() {
+ Map<Character, Integer> result = graph.inDegree();
+ Map<Character, Integer> expected = new HashMap<>(7);
+ expected.put('A', 0);
+ expected.put('B', 1);
+ expected.put('C', 1);
+ expected.put('D', 0);
+ expected.put('E', 1);
+ expected.put('F', 1);
+ expected.put('G', 1);
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void outDegree() {
+ Map<Character, Integer> result = graph.outDegree();
+ Map<Character, Integer> expected = new HashMap<>(7);
+ expected.put('A', 1);
+ expected.put('B', 2);
+ expected.put('C', 0);
+ expected.put('D', 1);
+ expected.put('E', 0);
+ expected.put('F', 1);
+ expected.put('G', 0);
+ assertEquals(expected, result);
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java
index 76d0c2e..5f9a3a7 100644
--- a/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java
+++ b/pf4j/src/test/java/org/pf4j/util/FileUtilsTest.java
@@ -15,24 +15,24 @@
*/
package org.pf4j.util;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.pf4j.plugin.PluginZip;
import java.nio.file.Files;
import java.nio.file.Path;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class FileUtilsTest {
- @Rule
- public TemporaryFolder testFolder = new TemporaryFolder();
+ @TempDir
+ Path pluginsPath;
@Test
public void expandIfZip() throws Exception {
- PluginZip pluginZip = new PluginZip.Builder(testFolder.newFile("my-plugin-1.2.3.zip"), "myPlugin")
+ PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin")
.pluginVersion("1.2.3")
.build();
@@ -41,10 +41,10 @@ public class FileUtilsTest {
assertTrue(Files.exists(unzipped.resolve("plugin.properties")));
// File without .suffix
- Path extra = testFolder.newFile("extra").toPath();
+ Path extra = pluginsPath.resolve("extra");
assertEquals(extra, FileUtils.expandIfZip(extra));
// Folder
- Path folder = testFolder.newFile("folder").toPath();
+ Path folder = pluginsPath.resolve("folder");
assertEquals(folder, FileUtils.expandIfZip(folder));
}
diff --git a/pom.xml b/pom.xml
index d4540d7..add6723 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-parent</artifactId>
- <version>2.7.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>PF4J Parent</name>
<description>Plugin Framework for Java</description>
@@ -43,11 +43,12 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <java.version>1.7</java.version>
+ <maven.compiler.release>8</maven.compiler.release>
+
<slf4j.version>1.7.25</slf4j.version>
<asm.version>7.1</asm.version>
- <junit.version>4.12</junit.version>
+ <junit.version>5.4.0</junit.version>
<hamcrest.version>2.1</hamcrest.version>
<mockito.version>2.24.0</mockito.version>
<cobertura.version>2.7</cobertura.version>
@@ -66,8 +67,6 @@
<version>3.8.0</version>
<configuration>
<showWarnings>true</showWarnings>
- <source>${java.version}</source>
- <target>${java.version}</target>
</configuration>
</plugin>
@@ -161,6 +160,7 @@
<modules>
<module>pf4j</module>
<module>demo</module>
+ <module>maven-archetypes/quickstart</module>
</modules>
<profiles>