Browse Source

Merge remote-tracking branch 'origin/master'

pull/186/head
Decebal Suiu 7 years ago
parent
commit
b7a858835f
  1. 62
      demo_gradle/README.md
  2. 5
      demo_gradle/api/build.gradle
  3. 27
      demo_gradle/app/build.gradle
  4. 14
      demo_gradle/app/src/main/java/org/pf4j/demo/Boot.java
  5. 20
      demo_gradle/build.gradle
  6. 2
      demo_gradle/gradle.properties
  7. 32
      demo_gradle/plugins/build.gradle
  8. 30
      demo_gradle/plugins/plugin1/build.gradle
  9. 6
      demo_gradle/plugins/plugin1/gradle.properties
  10. 5
      demo_gradle/plugins/plugin1/plugin.properties
  11. 30
      demo_gradle/plugins/plugin2/build.gradle
  12. 6
      demo_gradle/plugins/plugin2/gradle.properties
  13. 5
      demo_gradle/plugins/plugin2/plugin.properties
  14. 31
      demo_gradle/plugins/plugin3/build.gradle
  15. 6
      demo_gradle/plugins/plugin3/gradle.properties
  16. 9
      demo_gradle/settings.gradle
  17. 211
      pf4j/src/main/java/org/pf4j/DefaultPluginDescriptor.java
  18. 2
      pf4j/src/main/java/org/pf4j/DefaultPluginManager.java
  19. 6
      pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java
  20. 154
      pf4j/src/main/java/org/pf4j/PluginDescriptor.java
  21. 6
      pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java
  22. 4
      pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java
  23. 20
      pf4j/src/test/java/org/pf4j/DependencyResolverTest.java
  24. 82
      pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java

62
demo_gradle/README.md

@ -0,0 +1,62 @@
# PF4J Gradle Demo
This demo assumes that you know the basics of Gradle (Please look at [gradle](https://gradle.org/) for more info)
### Setup/Build
1. Clone the repo
2. Go to demo_gradle `cd demo_gradle`
3. run `gradle build`
* This will produce one jar, named app-plugin-demo-uberjar.jar, located in the `app/build/libs/` directory and three plugins zips located in `build/plugins` directory.
* The plugins are `plugin-hello-plugin-0.0.1.zip`, `plugin-KotlinPlugin-1.0.0.zip` and `plugin-welcome-plugin-0.0.1.zip`
### Run the demo
1. Run
```
java -jar -Dpf4j.pluginsDir=build/plugins app/build/libs/app-plugin-demo-uberjar.jar
```
* pf4j.pluginsDir: is where the plugins are located
2. The demo's output should look similar to: (Please see `Boot#main()` for more details)
```
demo_gradle $ java -jar -Dpf4j.pluginsDir=build/plugins app/build/libs/app-plugin-demo-uberjar.jar
[main] INFO org.pf4j.demo.Boot - ########################################
[main] INFO org.pf4j.demo.Boot - PF4J-DEMO
[main] INFO org.pf4j.demo.Boot - ########################################
[main] INFO org.pf4j.DefaultPluginStatusProvider - Enabled plugins: []
[main] INFO org.pf4j.DefaultPluginStatusProvider - Disabled plugins: []
[main] INFO org.pf4j.DefaultPluginManager - PF4J version 0.0.0 in 'deployment' mode
[main] INFO org.pf4j.AbstractPluginManager - Plugin 'welcome-plugin@0.0.1' resolved
[main] INFO org.pf4j.AbstractPluginManager - Plugin 'KotlinPlugin@1.0.0' resolved
[main] INFO org.pf4j.AbstractPluginManager - Plugin 'hello-plugin@0.0.1' resolved
[main] INFO org.pf4j.AbstractPluginManager - Start plugin 'welcome-plugin@0.0.1'
[main] INFO org.pf4j.demo.welcome.WelcomePlugin - WelcomePlugin.start()
[main] INFO org.pf4j.demo.welcome.WelcomePlugin - WELCOMEPLUGIN
[main] INFO org.pf4j.AbstractPluginManager - Start plugin 'KotlinPlugin@1.0.0'
[main] INFO org.pf4j.demo.kotlin.KotlinPlugin - KotlinPlugin.start()
[main] INFO org.pf4j.demo.kotlin.KotlinPlugin - KOTLINPLUGIN
[main] INFO org.pf4j.AbstractPluginManager - Start plugin 'hello-plugin@0.0.1'
[main] INFO org.pf4j.demo.hello.HelloPlugin - HelloPlugin.start()
[main] INFO org.pf4j.demo.Boot - Plugindirectory:
[main] INFO org.pf4j.demo.Boot - build/plugins
[main] INFO org.pf4j.demo.Boot - Found 3 extensions for extension point 'org.pf4j.demo.api.Greeting'
[main] INFO org.pf4j.demo.Boot - >>> Whazzup
[main] INFO org.pf4j.demo.Boot - >>> Welcome
[main] INFO org.pf4j.demo.Boot - >>> Hello
[main] INFO org.pf4j.demo.Boot - Extensions added by plugin 'welcome-plugin':
[main] INFO org.pf4j.demo.Boot - Extensions added by plugin 'KotlinPlugin':
[main] INFO org.pf4j.demo.Boot - Extensions added by plugin 'hello-plugin':
[main] INFO org.pf4j.AbstractPluginManager - Stop plugin 'hello-plugin@0.0.1'
[main] INFO org.pf4j.demo.hello.HelloPlugin - HelloPlugin.stop()
[main] INFO org.pf4j.AbstractPluginManager - Stop plugin 'KotlinPlugin@1.0.0'
[main] INFO org.pf4j.demo.kotlin.KotlinPlugin - KotlinPlugin.stop()
[main] INFO org.pf4j.AbstractPluginManager - Stop plugin 'welcome-plugin@0.0.1'
[main] INFO org.pf4j.demo.welcome.WelcomePlugin - WelcomePlugin.stop()
```

5
demo_gradle/api/build.gradle

@ -1,5 +1,6 @@
dependencies { dependencies {
compile 'org.pf4j:pf4j:2.0.0-SNAPSHOT' compile group: 'org.pf4j', name: 'pf4j', version: "${pf4jVersion}"
compile 'org.apache.commons:commons-lang3:3.0' compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.5'
testCompile group: 'junit', name: 'junit', version: '4.+' testCompile group: 'junit', name: 'junit', version: '4.+'
} }

27
demo_gradle/app/build.gradle

@ -4,13 +4,28 @@ mainClassName = 'org.pf4j.demo.Boot'
dependencies { dependencies {
compile project(':api') compile project(':api')
compile 'org.pf4j:pf4j:2.0.0-SNAPSHOT' compile group: 'org.pf4j', name: 'pf4j', version: "${pf4jVersion}"
compile 'org.apache.commons:commons-lang3:3.5' compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.5'
testCompile group: 'junit', name: 'junit', version: '4.+'
compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25' compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25'
testCompile group: 'junit', name: 'junit', version: '4.+'
} }
jar { task uberjar(type: Jar, dependsOn: ['compileJava']) {
baseName = 'Plugin Demo' zip64 true
version = '0.1.0' from configurations.runtime.asFileTree.files.collect {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
zipTree(it)
}
from files(sourceSets.main.output.classesDir)
from files(sourceSets.main.resources)
manifest {
attributes 'Main-Class': mainClassName
} }
baseName = "${project.name}-plugin-demo"
classifier = "uberjar"
}

14
demo_gradle/app/src/main/java/org/pf4j/demo/Boot.java

@ -16,6 +16,9 @@
package org.pf4j.demo; package org.pf4j.demo;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.pf4j.CompoundPluginDescriptorFinder;
import org.pf4j.ManifestPluginDescriptorFinder;
import org.pf4j.PropertiesPluginDescriptorFinder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.pf4j.DefaultPluginManager; import org.pf4j.DefaultPluginManager;
@ -38,7 +41,16 @@ public class Boot {
printLogo(); printLogo();
// create the plugin manager // create the plugin manager
final PluginManager pluginManager = new DefaultPluginManager(); final PluginManager pluginManager = new DefaultPluginManager() {
@Override
protected CompoundPluginDescriptorFinder createPluginDescriptorFinder() {
return new CompoundPluginDescriptorFinder()
// Demo is using the Manifest file
// PropertiesPluginDescriptorFinder is commented out just to avoid error log
//.add(new PropertiesPluginDescriptorFinder())
.add(new ManifestPluginDescriptorFinder());
}
};
// load the plugins // load the plugins
pluginManager.loadPlugins(); pluginManager.loadPlugins();

20
demo_gradle/build.gradle

@ -6,21 +6,9 @@ subprojects {
mavenCentral() mavenCentral()
} }
} }
// plugin location
ext.pluginsDir = rootProject.buildDir.path + '/plugins'
task build(dependsOn: [':app:uberjar'])
task copyPlugins() {
doLast {
delete 'app/plugins'
mkdir 'app/plugins'
subprojects.each { p ->
if (p.path.contains(":plugins/")) {
System.out.println("Copying plugin from " + p.path);
copy {
from p.projectDir.toString() + '/build/libs'
into 'app/plugins'
include '*.zip'
}
}
}
}
}

2
demo_gradle/gradle.properties

@ -0,0 +1,2 @@
# PF4J
pf4jVersion=2.0.0

32
demo_gradle/plugins/build.gradle

@ -0,0 +1,32 @@
subprojects {
jar {
manifest {
attributes 'Plugin-Class': "${pluginClass}",
'Plugin-Id': "${pluginId}",
'Plugin-Version': "${version}",
'Plugin-Provider': "${pluginProvider}"
}
}
task plugin(type: Jar) {
baseName = "plugin-${pluginId}"
into('classes') {
with jar
}
into('lib') {
from configurations.compile
}
extension('zip')
}
task assemblePlugin(type: Copy) {
from plugin
into pluginsDir
}
}
task assemblePlugins(type: Copy) {
dependsOn subprojects.assemblePlugin
}
build.dependsOn project.tasks.assemblePlugins

30
demo_gradle/plugins/plugin1/build.gradle

@ -1,33 +1,9 @@
jar {
baseName = 'WelcomePlugin'
version = '0.1.0'
manifest {
attributes 'Plugin-Class': 'org.pf4j.demo.welcome.WelcomePlugin',
'Plugin-Id': 'WelcomePlugin',
'Plugin-Version': '1.0.0',
'Plugin-Provider': 'Decebal Suiu'
}
}
task plugin(type: Jar) {
baseName = 'WelcomePlugin'
version = '0.1.0'
into('classes') {
with jar
}
into('lib') {
from configurations.compile
}
extension('zip')
}
assemble.dependsOn plugin
dependencies { dependencies {
compileOnly project(':api')
// compileOnly important!!! We do not want to put the api into the zip file since the main program has it already! // compileOnly important!!! We do not want to put the api into the zip file since the main program has it already!
compile('org.pf4j:pf4j:2.0.0-SNAPSHOT') { compileOnly project(':api')
compileOnly(group: 'org.pf4j', name: 'pf4j', version: "${pf4jVersion}") {
exclude group: "org.slf4j" exclude group: "org.slf4j"
} }
compile 'org.apache.commons:commons-lang3:3.5' compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.5'
testCompile group: 'junit', name: 'junit', version: '4.+' testCompile group: 'junit', name: 'junit', version: '4.+'
} }

6
demo_gradle/plugins/plugin1/gradle.properties

@ -0,0 +1,6 @@
version=0.0.1
pluginId=welcome-plugin
pluginClass=org.pf4j.demo.welcome.WelcomePlugin
pluginProvider=Decebal Suiu
pluginDependencies=

5
demo_gradle/plugins/plugin1/plugin.properties

@ -1,5 +0,0 @@
plugin.id=welcome-plugin
plugin.class=org.pf4j.demo.welcome.WelcomePlugin
plugin.version=0.0.1
plugin.provider=Decebal Suiu
plugin.dependencies=

30
demo_gradle/plugins/plugin2/build.gradle

@ -1,33 +1,9 @@
jar {
baseName = 'HelloPlugin'
version = '0.1.0'
manifest {
attributes 'Plugin-Class': 'org.pf4j.demo.hello.HelloPlugin',
'Plugin-Id': 'HelloPlugin',
'Plugin-Version': '1.0.0',
'Plugin-Provider': 'Decebal Suiu'
}
}
task plugin(type: Jar) {
baseName = 'HelloPlugin'
version = '0.1.0'
into('classes') {
with jar
}
into('lib') {
from configurations.compile
}
extension('zip')
}
assemble.dependsOn plugin
dependencies { dependencies {
compileOnly project(':api')
// compileOnly important!!! We do not want to put the api into the zip file since the main program has it already! // compileOnly important!!! We do not want to put the api into the zip file since the main program has it already!
compile('org.pf4j:pf4j:2.0.0-SNAPSHOT') { compileOnly project(':api')
compileOnly(group: 'org.pf4j', name: 'pf4j', version: "${pf4jVersion}") {
exclude group: "org.slf4j" exclude group: "org.slf4j"
} }
compile 'org.apache.commons:commons-lang3:3.5' compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.5'
testCompile group: 'junit', name: 'junit', version: '4.+' testCompile group: 'junit', name: 'junit', version: '4.+'
} }

6
demo_gradle/plugins/plugin2/gradle.properties

@ -0,0 +1,6 @@
version=0.0.1
pluginId=hello-plugin
pluginClass=org.pf4j.demo.hello.HelloPlugin
pluginProvider=Decebal Suiu
pluginDependencies=

5
demo_gradle/plugins/plugin2/plugin.properties

@ -1,5 +0,0 @@
plugin.id=hello-plugin
plugin.class=org.pf4j.demo.hello.HelloPlugin
plugin.version=0.0.1
plugin.provider=Decebal Suiu
plugin.dependencies=

31
demo_gradle/plugins/plugin3/build.gradle

@ -9,30 +9,6 @@ buildscript {
} }
} }
jar {
baseName = 'KotlinPlugin'
version = '0.1.0'
manifest {
attributes 'Plugin-Class': 'org.pf4j.demo.kotlin.KotlinPlugin',
'Plugin-Id': 'KotlinPlugin',
'Plugin-Version': '1.0.0',
'Plugin-Provider': 'Anindya Chatterjee'
}
}
task plugin(type: Jar) {
baseName = 'KotlinPlugin'
version = '0.1.0'
into('classes') {
with jar
}
into('lib') {
from configurations.compile
}
extension('zip')
}
assemble.dependsOn plugin
apply plugin: 'kotlin' apply plugin: 'kotlin'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
@ -42,10 +18,11 @@ repositories {
dependencies { dependencies {
compileOnly project(':api') compileOnly project(':api')
kapt('org.pf4j:pf4j:2.0.0-SNAPSHOT') { compileOnly(group: 'org.pf4j', name: 'pf4j', version: "${pf4jVersion}") {
exclude group: "org.slf4j" exclude group: "org.slf4j"
} }
compile 'org.apache.commons:commons-lang3:3.5' compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.5'
testCompile group: 'junit', name: 'junit', version: '4.+'
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
testCompile group: 'junit', name: 'junit', version: '4.+'
} }

6
demo_gradle/plugins/plugin3/gradle.properties

@ -0,0 +1,6 @@
version=1.0.0
pluginId=KotlinPlugin
pluginClass=org.pf4j.demo.kotlin.KotlinPlugin
pluginProvider=Anindya Chatterjee
pluginDependencies=

9
demo_gradle/settings.gradle

@ -1,5 +1,8 @@
include 'api' include 'api'
include 'app' include 'app'
include 'plugins/plugin1'
include 'plugins/plugin2' include 'plugins'
include 'plugins/plugin3'
include 'plugins:plugin1'
include 'plugins:plugin2'
include 'plugins:plugin3'

211
pf4j/src/main/java/org/pf4j/DefaultPluginDescriptor.java

@ -0,0 +1,211 @@
/*
* Copyright 2012 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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* A plugin descriptor contains information about a plug-in obtained
* from the manifest (META-INF) file.
*
* @author Decebal Suiu
*/
public class DefaultPluginDescriptor implements PluginDescriptor {
private String pluginId;
private String pluginDescription;
private String pluginClass;
private String version;
private String requires = "*"; // SemVer format
private String provider;
private List<PluginDependency> dependencies;
private String license;
public DefaultPluginDescriptor() {
dependencies = new ArrayList<>();
}
/**
* @param pluginId
* @param pluginDescription
* @param pluginClass
* @param version
* @param requires
* @param provider
* @param license
*/
public DefaultPluginDescriptor(String pluginId, String pluginDescription, String pluginClass, String version, String requires, String provider, String license) {
this();
this.pluginId = pluginId;
this.pluginDescription = pluginDescription;
this.pluginClass = pluginClass;
this.version = version;
this.requires = requires;
this.provider = provider;
this.license = license;
}
public void addDependency(PluginDependency dependency) {
this.dependencies.add(dependency);
}
/**
* Returns the unique identifier of this plugin.
*/
@Override
public String getPluginId() {
return pluginId;
}
/**
* Returns the description of this plugin.
*/
@Override
public String getPluginDescription() {
return pluginDescription;
}
/**
* Returns the name of the class that implements Plugin interface.
*/
@Override
public String getPluginClass() {
return pluginClass;
}
/**
* Returns the version of this plugin.
*/
@Override
public String getVersion() {
return version;
}
/**
* Returns string version of requires
*
* @return String with requires expression on SemVer format
*/
@Override
public String getRequires() {
return requires;
}
/**
* Returns the provider name of this plugin.
*/
@Override
public String getProvider() {
return provider;
}
/**
* Returns the legal license of this plugin, e.g. "Apache-2.0", "MIT" etc
*/
@Override
public String getLicense() {
return license;
}
/**
* Returns all dependencies declared by this plugin.
* Returns an empty array if this plugin does not declare any require.
*/
@Override
public List<PluginDependency> getDependencies() {
return dependencies;
}
@Override
public String toString() {
return "PluginDescriptor [pluginId=" + pluginId + ", pluginClass="
+ pluginClass + ", version=" + version + ", provider="
+ provider + ", dependencies=" + dependencies + ", description="
+ pluginDescription + ", requires=" + requires + ", license="
+ license + "]";
}
protected DefaultPluginDescriptor setPluginId(String pluginId) {
this.pluginId = pluginId;
return this;
}
protected PluginDescriptor setPluginDescription(String pluginDescription) {
this.pluginDescription = pluginDescription;
return this;
}
protected PluginDescriptor setPluginClass(String pluginClassName) {
this.pluginClass = pluginClassName;
return this;
}
protected DefaultPluginDescriptor setPluginVersion(String version) {
this.version = version;
return this;
}
protected PluginDescriptor setProvider(String provider) {
this.provider = provider;
return this;
}
protected PluginDescriptor setRequires(String requires) {
this.requires = requires;
return this;
}
protected PluginDescriptor setDependencies(String dependencies) {
if (dependencies != null) {
dependencies = dependencies.trim();
if (dependencies.isEmpty()) {
this.dependencies = Collections.emptyList();
} else {
this.dependencies = new ArrayList<>();
String[] tokens = dependencies.split(",");
for (String dependency : tokens) {
dependency = dependency.trim();
if (!dependency.isEmpty()) {
this.dependencies.add(new PluginDependency(dependency));
}
}
if (this.dependencies.isEmpty()) {
this.dependencies = Collections.emptyList();
}
}
} else {
this.dependencies = Collections.emptyList();
}
return this;
}
public PluginDescriptor setLicense(String license) {
this.license = license;
return this;
}
}

2
pf4j/src/main/java/org/pf4j/DefaultPluginManager.java

@ -52,7 +52,7 @@ public class DefaultPluginManager extends AbstractPluginManager {
} }
@Override @Override
protected CompoundPluginDescriptorFinder createPluginDescriptorFinder() { protected PluginDescriptorFinder createPluginDescriptorFinder() {
return new CompoundPluginDescriptorFinder() return new CompoundPluginDescriptorFinder()
.add(new PropertiesPluginDescriptorFinder()) .add(new PropertiesPluginDescriptorFinder())
.add(new ManifestPluginDescriptorFinder()); .add(new ManifestPluginDescriptorFinder());

6
pf4j/src/main/java/org/pf4j/ManifestPluginDescriptorFinder.java

@ -88,7 +88,7 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder {
} }
protected PluginDescriptor createPluginDescriptor(Manifest manifest) { protected PluginDescriptor createPluginDescriptor(Manifest manifest) {
PluginDescriptor pluginDescriptor = createPluginDescriptorInstance(); DefaultPluginDescriptor pluginDescriptor = createPluginDescriptorInstance();
// TODO validate !!! // TODO validate !!!
Attributes attributes = manifest.getMainAttributes(); Attributes attributes = manifest.getMainAttributes();
@ -125,8 +125,8 @@ public class ManifestPluginDescriptorFinder implements PluginDescriptorFinder {
return pluginDescriptor; return pluginDescriptor;
} }
protected PluginDescriptor createPluginDescriptorInstance() { protected DefaultPluginDescriptor createPluginDescriptorInstance() {
return new PluginDescriptor(); return new DefaultPluginDescriptor();
} }
} }

154
pf4j/src/main/java/org/pf4j/PluginDescriptor.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2012 Decebal Suiu * Copyright 2015 Decebal Suiu
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -15,8 +15,6 @@
*/ */
package org.pf4j; package org.pf4j;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -25,153 +23,21 @@ import java.util.List;
* *
* @author Decebal Suiu * @author Decebal Suiu
*/ */
public class PluginDescriptor { public interface PluginDescriptor {
private String pluginId; String getPluginId();
private String pluginDescription;
private String pluginClass;
private String version;
private String requires = "*"; // SemVer format
private String provider;
private List<PluginDependency> dependencies;
private String license;
public PluginDescriptor() { String getPluginDescription();
dependencies = new ArrayList<>();
}
/**
* Returns the unique identifier of this plugin.
*/
public String getPluginId() {
return pluginId;
}
/**
* Returns the description of this plugin.
*/
public String getPluginDescription() {
return pluginDescription;
}
/**
* Returns the name of the class that implements Plugin interface.
*/
public String getPluginClass() {
return pluginClass;
}
/**
* Returns the version of this plugin.
*/
public String getVersion() {
return version;
}
/** String getPluginClass();
* Returns string version of requires
* @return String with requires expression on SemVer format
*/
public String getRequires() {
return requires;
}
/** String getVersion();
* Returns the provider name of this plugin.
*/
public String getProvider() {
return provider;
}
/** String getRequires();
* Returns the legal license of this plugin, e.g. "Apache-2.0", "MIT" etc
*/
public String getLicense() {
return license;
}
/** String getProvider();
* Returns all dependencies declared by this plugin.
* Returns an empty array if this plugin does not declare any require.
*/
public List<PluginDependency> getDependencies() {
return dependencies;
}
@Override String getLicense();
public String toString() {
return "PluginDescriptor [pluginId=" + pluginId + ", pluginClass="
+ pluginClass + ", version=" + version + ", provider="
+ provider + ", dependencies=" + dependencies + ", description="
+ pluginDescription + ", requires=" + requires + ", license="
+ license + "]";
}
PluginDescriptor setPluginId(String pluginId) {
this.pluginId = pluginId;
return this;
}
PluginDescriptor setPluginDescription(String pluginDescription) {
this.pluginDescription = pluginDescription;
return this;
}
PluginDescriptor setPluginClass(String pluginClassName) {
this.pluginClass = pluginClassName;
return this;
}
PluginDescriptor setPluginVersion(String version) {
this.version = version;
return this;
}
PluginDescriptor setProvider(String provider) {
this.provider = provider;
return this;
}
PluginDescriptor setRequires(String requires) {
this.requires = requires;
return this;
}
PluginDescriptor setDependencies(String dependencies) {
if (dependencies != null) {
dependencies = dependencies.trim();
if (dependencies.isEmpty()) {
this.dependencies = Collections.emptyList();
} else {
this.dependencies = new ArrayList<>();
String[] tokens = dependencies.split(",");
for (String dependency : tokens) {
dependency = dependency.trim();
if (!dependency.isEmpty()) {
this.dependencies.add(new PluginDependency(dependency));
}
}
if (this.dependencies.isEmpty()) {
this.dependencies = Collections.emptyList();
}
}
} else {
this.dependencies = Collections.emptyList();
}
return this;
}
public PluginDescriptor setLicense(String license) {
this.license = license;
return this;
}
List<PluginDependency> getDependencies();
} }

6
pf4j/src/main/java/org/pf4j/PropertiesPluginDescriptorFinder.java

@ -95,7 +95,7 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder
} }
protected PluginDescriptor createPluginDescriptor(Properties properties) { protected PluginDescriptor createPluginDescriptor(Properties properties) {
PluginDescriptor pluginDescriptor = createPluginDescriptorInstance(); DefaultPluginDescriptor pluginDescriptor = createPluginDescriptorInstance();
// TODO validate !!! // TODO validate !!!
String id = properties.getProperty("plugin.id"); String id = properties.getProperty("plugin.id");
@ -132,8 +132,8 @@ public class PropertiesPluginDescriptorFinder implements PluginDescriptorFinder
return pluginDescriptor; return pluginDescriptor;
} }
protected PluginDescriptor createPluginDescriptorInstance() { protected DefaultPluginDescriptor createPluginDescriptorInstance() {
return new PluginDescriptor(); return new DefaultPluginDescriptor();
} }
} }

4
pf4j/src/test/java/org/pf4j/DefaultPluginManagerTest.java

@ -27,13 +27,13 @@ import static org.junit.Assert.assertTrue;
public class DefaultPluginManagerTest { public class DefaultPluginManagerTest {
private PluginDescriptor pd1 = null; private DefaultPluginDescriptor pd1 = null;
private DefaultPluginManager pluginManager = new DefaultPluginManager(); private DefaultPluginManager pluginManager = new DefaultPluginManager();
private PluginWrapper pw1; private PluginWrapper pw1;
@Before @Before
public void init() throws IOException { public void init() throws IOException {
pd1 = new PluginDescriptor(); pd1 = new DefaultPluginDescriptor();
pd1.setPluginId("myPlugin"); pd1.setPluginId("myPlugin");
pd1.setPluginVersion("1.2.3"); pd1.setPluginVersion("1.2.3");
pd1.setPluginClass("foo"); pd1.setPluginClass("foo");

20
pf4j/src/test/java/org/pf4j/DependencyResolverTest.java

@ -40,11 +40,11 @@ public class DependencyResolverTest {
@Test @Test
public void sortedPlugins() { public void sortedPlugins() {
// create incomplete plugin descriptor (ignore some attributes) // create incomplete plugin descriptor (ignore some attributes)
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
.setDependencies("p2"); .setDependencies("p2");
PluginDescriptor pd2 = new PluginDescriptor() PluginDescriptor pd2 = new DefaultPluginDescriptor()
.setPluginId("p2") .setPluginId("p2")
.setPluginVersion("0.0.0"); // needed in "checkDependencyVersion" method .setPluginVersion("0.0.0"); // needed in "checkDependencyVersion" method
@ -60,7 +60,7 @@ public class DependencyResolverTest {
@Test @Test
public void notFoundDependencies() throws Exception { public void notFoundDependencies() throws Exception {
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
.setDependencies("p2, p3"); .setDependencies("p2, p3");
@ -75,17 +75,17 @@ public class DependencyResolverTest {
@Test @Test
public void cyclicDependencies() { public void cyclicDependencies() {
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
.setPluginVersion("0.0.0") .setPluginVersion("0.0.0")
.setDependencies("p2"); .setDependencies("p2");
PluginDescriptor pd2 = new PluginDescriptor() PluginDescriptor pd2 = new DefaultPluginDescriptor()
.setPluginId("p2") .setPluginId("p2")
.setPluginVersion("0.0.0") .setPluginVersion("0.0.0")
.setDependencies("p3"); .setDependencies("p3");
PluginDescriptor pd3 = new PluginDescriptor() PluginDescriptor pd3 = new DefaultPluginDescriptor()
.setPluginId("p3") .setPluginId("p3")
.setPluginVersion("0.0.0") .setPluginVersion("0.0.0")
.setDependencies("p1"); .setDependencies("p1");
@ -102,12 +102,12 @@ public class DependencyResolverTest {
@Test @Test
public void wrongDependencyVersion() { public void wrongDependencyVersion() {
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
// .setDependencies("p2@2.0.0"); // simple version // .setDependencies("p2@2.0.0"); // simple version
.setDependencies("p2@>=1.5.0 & <1.6.0"); // range version .setDependencies("p2@>=1.5.0 & <1.6.0"); // range version
PluginDescriptor pd2 = new PluginDescriptor() PluginDescriptor pd2 = new DefaultPluginDescriptor()
.setPluginId("p2") .setPluginId("p2")
.setPluginVersion("1.4.0"); .setPluginVersion("1.4.0");
@ -122,11 +122,11 @@ public class DependencyResolverTest {
@Test @Test
public void goodDependencyVersion() { public void goodDependencyVersion() {
PluginDescriptor pd1 = new PluginDescriptor() PluginDescriptor pd1 = new DefaultPluginDescriptor()
.setPluginId("p1") .setPluginId("p1")
.setDependencies("p2@2.0.0"); .setDependencies("p2@2.0.0");
PluginDescriptor pd2 = new PluginDescriptor() PluginDescriptor pd2 = new DefaultPluginDescriptor()
.setPluginId("p2") .setPluginId("p2")
.setPluginVersion("2.0.0"); .setPluginVersion("2.0.0");

82
pf4j/src/test/java/org/pf4j/processor/ServiceProviderExtensionStorageTest.java

@ -0,0 +1,82 @@
/*
* 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.processor;
import org.junit.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 static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
/**
* @author Josiah Haswell
*/
public class ServiceProviderExtensionStorageTest {
@Test
public void ensureServiceProviderExtensionStorageReadWorks() throws IOException {
final StringReader file = new StringReader("#hello\n World");
final Set<String> entries = new HashSet<>();
ServiceProviderExtensionStorage.read(file, entries);
assertThat(entries.size(), is(1));
assertThat(entries.contains("World"), is(true));
}
@Test
public void ensureReadingExtensionsProducesCorrectListOfExtensions() {
final StringReader file = new StringReader("#hello\n World");
final ExtensionAnnotationProcessor processor = mock(ExtensionAnnotationProcessor.class);
final Map<String, Set<String>> extensions = new HashMap<>();
extensions.put("hello", Collections.singleton("world"));
given(processor.getExtensions()).willReturn(extensions);
ServiceProviderExtensionStorage extensionStorage = new ServiceProviderExtensionStorage(processor) {
@Override
protected Filer getFiler() {
try {
Filer filer = mock(Filer.class);
FileObject fileObject = mock(FileObject.class);
given(fileObject.openReader(true)).willReturn(file);
given(filer.getResource(
any(StandardLocation.class),
any(String.class),
any(String.class)
)).willReturn(fileObject);
return filer;
} catch(IOException ex) {
throw new IllegalStateException("Shouldn't have gotten here");
}
}
};
Map<String, Set<String>> read = extensionStorage.read();
assertThat(read.containsKey("hello"), is(true));
assertThat(read.get("hello"), is(Collections.singleton("World")));
}
}
Loading…
Cancel
Save