Browse Source

add RuntimeMode with DEVELOPMENT and DEPLOYMENT values and working on DEVELOPMENT mode

pull/3/head
Decebal Suiu 11 years ago
parent
commit
6df8db4c34
  1. 33
      README.md
  2. 80
      demo/app/src/main/java/ro/fortsoft/pf4j/demo/Boot.java
  3. 14
      demo/plugins/plugin1/pom.xml
  4. 10
      demo/plugins/plugin1/src/main/java/ro/fortsoft/pf4j/demo/welcome/WelcomePlugin.java
  5. 16
      demo/plugins/plugin2/pom.xml
  6. 3
      demo/plugins/plugin2/src/main/java/ro/fortsoft/pf4j/demo/hello/HelloPlugin.java
  7. 69
      demo/plugins/pom.xml
  8. 130
      pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
  9. 36
      pf4j/src/main/java/ro/fortsoft/pf4j/DevelopmentPluginClasspath.java
  10. 13
      pf4j/src/main/java/ro/fortsoft/pf4j/PluginClasspath.java
  11. 5
      pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java
  12. 9
      pf4j/src/main/java/ro/fortsoft/pf4j/PluginWrapper.java
  13. 55
      pf4j/src/main/java/ro/fortsoft/pf4j/RuntimeMode.java

33
README.md

@ -61,8 +61,8 @@ It's very simple to add pf4j in your application:
In above code, I created a **DefaultPluginManager** (it's the default implementation for In above code, I created a **DefaultPluginManager** (it's the default implementation for
**PluginManager** interface) that loads and starts all active(resolved) plugins. **PluginManager** interface) that loads and starts all active(resolved) plugins.
Each available plugin is loaded using a **PluginClassLoader**. Each available plugin is loaded using a different java class loader, **PluginClassLoader**.
The **PluginClassLoader** contains only classes found in _classes_ and _lib_ folders of plugin and runtime classes and libraries of the required plugins. The **PluginClassLoader** contains only classes found in **PluginClasspath** (default _classes_ and _lib_ folders) of plugin and runtime classes and libraries of the required/dependent plugins.
The plugins are stored in a folder. You can specify the plugins folder in the constructor of DefaultPluginManager. If the plugins folder is not specified The plugins are stored in a folder. You can specify the plugins folder in the constructor of DefaultPluginManager. If the plugins folder is not specified
than the location is returned by `System.getProperty("pf4j.pluginsDir", "plugins")`. than the location is returned by `System.getProperty("pf4j.pluginsDir", "plugins")`.
@ -71,12 +71,12 @@ The structure of plugins folder is:
* plugin2.zip (or plugin2 folder) * plugin2.zip (or plugin2 folder)
In plugins folder you can put a plugin as folder or archive file (zip). In plugins folder you can put a plugin as folder or archive file (zip).
A plugin folder has this structure: A plugin folder has this structure by default:
* `classes` folder * `classes` folder
* `lib` folder (optional - if the plugin used third party libraries) * `lib` folder (optional - if the plugin used third party libraries)
The plugin manager searches plugins metadata using a **PluginDescriptorFinder**. The plugin manager searches plugins metadata using a **PluginDescriptorFinder**.
**DefaultPluginDescriptorFinder** lookups plugins descriptors in MANIFEST.MF file. **DefaultPluginDescriptorFinder** is a "link" to **ManifestPluginDescriptorFinder** that lookups plugins descriptors in MANIFEST.MF file.
In this case the `classes/META-INF/MANIFEST.MF` file looks like: In this case the `classes/META-INF/MANIFEST.MF` file looks like:
Manifest-Version: 1.0 Manifest-Version: 1.0
@ -102,7 +102,7 @@ You can define an extension point in your application using **ExtensionPoint** i
} }
Another important internal component is **ExtensionFinder** that describes how plugin manager discovers extensions for extensions points. Another important internal component is **ExtensionFinder** that describes how plugin manager discovers extensions for extensions points.
**DefaultExtensionFinder** looks up extensions using **Extension** annotation. **DefaultExtensionFinder** is a "link" to **SezpozExtensionFinder** that looks up extensions using **Extension** annotation.
public class WelcomePlugin extends Plugin { public class WelcomePlugin extends Plugin {
@ -135,7 +135,7 @@ The output is:
>>> Welcome >>> Welcome
>>> Hello >>> Hello
You can inject your custom component (for example PluginDescriptorFinder, ExtensionFinder) in DefaultPluginManager just override createXXX methods (factory method pattern). You can inject your custom component (for example PluginDescriptorFinder, ExtensionFinder, PluginClasspath, ...) in DefaultPluginManager just override createXXX methods (factory method pattern).
Example: Example:
@ -154,6 +154,23 @@ and in plugin respository you must have a plugin.properties file with the below
For more information please see the demo sources. For more information please see the demo sources.
Development runtime mode
--------------------------
PF4J can run in two modes: **DEVELOPMENT** and **DEPLOYMENT**.
The DEPLOYMENT(default) mode is the standard workflow for plugins creation: create a new maven module for each plugin, codding the plugin (declares new extension points and/or
add new extensions), pack the plugin in a zip file, deploy the zip file to plugins folder. These operations are time consuming and from this reason I introduced the DEVELOPMENT runtime mode.
The main advantage of DEVELOPMENT runtime mode for a plugin developer is that he/she is not enforced to pack and deploy the plugins. In DEVELOPMENT mode you can developing plugins in a simple and fast mode.
Lets describe how DEVELOPMENT runtime mode works.
First, you can change the runtime mode using the "pf4j.mode" system property or overriding __DefaultPluginManager.getRuntimeMode()__.
For example I run the pf4j demo in eclipse in DEVELOPMENT mode adding only `"-Dpf4j.mode=development"` to the pf4j demo launcher.
You can retrieve the current runtime mode using __PluginManager.getRuntimeMode()__ or in your Plugin implementation with __getWrapper().getRuntimeMode()__(see [WelcomeMessage](https://github.com/decebals/pf4j/blob/master/demo/plugins/plugin1/src/main/java/ro/fortsoft/pf4j/demo/welcome/WelcomePlugin.java)).
The DefaultPluginManager determines automatically the correct runtime mode and for DEVELOPMENT mode overrides some components(pluginsDirectory is "../plugins", PropertiesPluginDescriptorFinder as PluginDescriptorFinder, DevelopmentPluginClasspath as PluginClassPath).
Another advantage of DEVELOPMENT runtime mode is that you can execute some code lines only in this mode (for example more debug messages).
For more details see the demo application.
Enable/Disable plugins Enable/Disable plugins
------------------- -------------------
In theory, it's a relation **1:N** between an extension point and the extensions for this extension point. In theory, it's a relation **1:N** between an extension point and the extensions for this extension point.
@ -191,8 +208,8 @@ If a file with enabled.txt exists than disabled.txt is ignored. See enabled.txt
Demo Demo
------------------- -------------------
I have a tiny demo application. The demo application is in demo folder. I have a tiny demo application. The demo application is in demo folder.
In demo/api folder I declared an extension point (_Greeting_). In demo/api folder I declared an extension point ( _Greeting_).
In demo/plugin* I implemented two plugins: plugin1, plugin2 (each plugin adds an extension for _Greeting_). In demo/plugins I implemented two plugins: plugin1, plugin2 (each plugin adds an extension for _Greeting_).
To run the demo application use: To run the demo application use:

80
demo/app/src/main/java/ro/fortsoft/pf4j/demo/Boot.java

@ -12,19 +12,12 @@
*/ */
package ro.fortsoft.pf4j.demo; package ro.fortsoft.pf4j.demo;
import java.io.File;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import ro.fortsoft.pf4j.DefaultPluginManager; import ro.fortsoft.pf4j.DefaultPluginManager;
import ro.fortsoft.pf4j.PluginClasspath;
import ro.fortsoft.pf4j.PluginDescriptorFinder;
import ro.fortsoft.pf4j.PluginManager; import ro.fortsoft.pf4j.PluginManager;
import ro.fortsoft.pf4j.PropertiesPluginDescriptorFinder;
import ro.fortsoft.pf4j.demo.api.Greeting; import ro.fortsoft.pf4j.demo.api.Greeting;
/** /**
@ -39,7 +32,7 @@ public class Boot {
printLogo(); printLogo();
// create the plugin manager // create the plugin manager
final PluginManager pluginManager = createPluginManager(); final PluginManager pluginManager = new DefaultPluginManager();
// load and start (active/resolved) the plugins // load and start (active/resolved) the plugins
pluginManager.loadPlugins(); pluginManager.loadPlugins();
@ -65,81 +58,10 @@ public class Boot {
*/ */
} }
private static PluginManager createPluginManager() {
// retrieves the pf4j runtime mode
String modeAsString = System.getProperty("pf4j.mode", RuntimeMode.PROD.toString());
RuntimeMode mode = RuntimeMode.byName(modeAsString);
System.out.println("PF4J runtime mode: '" + mode + "'");
// create the plugin manager depending on runtime mode
PluginManager pluginManager = null;
if (mode == RuntimeMode.PROD) {
pluginManager = new DefaultPluginManager();
} else if (mode == RuntimeMode.DEV) {
// run from eclipse IDE (for example)
pluginManager = new DefaultPluginManager(new File("../plugins")) {
@Override
protected PluginClasspath createPluginClasspath() {
PluginClasspath pluginClasspath = super.createPluginClasspath();
// modify plugin classes
List<String> pluginClasses = pluginClasspath.getClassesDirectories();
pluginClasses.clear();
pluginClasses.add("target/classes");
return pluginClasspath;
}
@Override
protected PluginDescriptorFinder createPluginDescriptorFinder() {
return new PropertiesPluginDescriptorFinder();
}
};
}
return pluginManager;
}
private static void printLogo() { private static void printLogo() {
System.out.println(StringUtils.repeat("#", 40)); System.out.println(StringUtils.repeat("#", 40));
System.out.println(StringUtils.center("PF4J-DEMO", 40)); System.out.println(StringUtils.center("PF4J-DEMO", 40));
System.out.println(StringUtils.repeat("#", 40)); System.out.println(StringUtils.repeat("#", 40));
} }
public enum RuntimeMode {
DEV("dev"), // development
PROD("prod"); // production
private final String name;
private static final Map<String, RuntimeMode> map = new HashMap<String, RuntimeMode>();
static {
for (RuntimeMode mode : RuntimeMode.values()) {
map.put(mode.name, mode);
}
}
private RuntimeMode(final String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
public static RuntimeMode byName(String name) {
if (map.containsKey(name)) {
return map.get(name);
}
throw new NoSuchElementException("Cannot found PF4J runtime mode with name '" + name + "'");
}
}
} }

14
demo/plugins/plugin1/pom.xml

@ -114,17 +114,9 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>ro.fortsoft.pf4j</groupId> <groupId>commons-lang</groupId>
<artifactId>pf4j</artifactId> <artifactId>commons-lang</artifactId>
<version>${project.version}</version> <version>2.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ro.fortsoft.pf4j.demo</groupId>
<artifactId>pf4j-demo-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>

10
demo/plugins/plugin1/src/main/java/ro/fortsoft/pf4j/demo/welcome/WelcomePlugin.java

@ -12,9 +12,12 @@
*/ */
package ro.fortsoft.pf4j.demo.welcome; package ro.fortsoft.pf4j.demo.welcome;
import org.apache.commons.lang.StringUtils;
import ro.fortsoft.pf4j.Extension; import ro.fortsoft.pf4j.Extension;
import ro.fortsoft.pf4j.Plugin; import ro.fortsoft.pf4j.Plugin;
import ro.fortsoft.pf4j.PluginWrapper; import ro.fortsoft.pf4j.PluginWrapper;
import ro.fortsoft.pf4j.RuntimeMode;
import ro.fortsoft.pf4j.demo.api.Greeting; import ro.fortsoft.pf4j.demo.api.Greeting;
/** /**
@ -26,10 +29,16 @@ public class WelcomePlugin extends Plugin {
super(wrapper); super(wrapper);
} }
@Override
public void start() { public void start() {
System.out.println("WelcomePlugin.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() { public void stop() {
System.out.println("WelcomePlugin.stop()"); System.out.println("WelcomePlugin.stop()");
} }
@ -37,6 +46,7 @@ public class WelcomePlugin extends Plugin {
@Extension @Extension
public static class WelcomeGreeting implements Greeting { public static class WelcomeGreeting implements Greeting {
@Override
public String getGreeting() { public String getGreeting() {
return "Welcome"; return "Welcome";
} }

16
demo/plugins/plugin2/pom.xml

@ -112,20 +112,4 @@
</plugins> </plugins>
</build> </build>
<dependencies>
<dependency>
<groupId>ro.fortsoft.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ro.fortsoft.pf4j.demo</groupId>
<artifactId>pf4j-demo-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project> </project>

3
demo/plugins/plugin2/src/main/java/ro/fortsoft/pf4j/demo/hello/HelloPlugin.java

@ -28,10 +28,12 @@ public class HelloPlugin extends Plugin {
super(wrapper); super(wrapper);
} }
@Override
public void start() { public void start() {
System.out.println("HelloPlugin.start()"); System.out.println("HelloPlugin.start()");
} }
@Override
public void stop() { public void stop() {
System.out.println("HelloPlugin.stop()"); System.out.println("HelloPlugin.stop()");
} }
@ -39,6 +41,7 @@ public class HelloPlugin extends Plugin {
@Extension @Extension
public static class HelloGreeting implements Greeting { public static class HelloGreeting implements Greeting {
@Override
public String getGreeting() { public String getGreeting() {
return "Hello"; return "Hello";
} }

69
demo/plugins/pom.xml

@ -27,6 +27,59 @@
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
</resource> </resource>
</resources> </resources>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeScope>provided</excludeScope>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<versionRange>[2.0,)</versionRange>
<goals>
<goal>copy-dependencies</goal>
</goals>
</pluginExecutionFilter>
<action>
<!--
<execute/>
-->
<execute>
<runOnIncremental>true</runOnIncremental>
<runOnConfiguration>true</runOnConfiguration>
</execute>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build> </build>
<modules> <modules>
@ -34,4 +87,20 @@
<module>plugin2</module> <module>plugin2</module>
</modules> </modules>
<dependencies>
<dependency>
<groupId>ro.fortsoft.pf4j</groupId>
<artifactId>pf4j</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ro.fortsoft.pf4j.demo</groupId>
<artifactId>pf4j-demo-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project> </project>

130
pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java

@ -16,6 +16,7 @@ import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -42,16 +43,19 @@ public class DefaultPluginManager implements PluginManager {
private static final Logger log = LoggerFactory.getLogger(DefaultPluginManager.class); private static final Logger log = LoggerFactory.getLogger(DefaultPluginManager.class);
public static final String DEFAULT_PLUGINS_DIRECTORY = "plugins";
public static final String DEVELOPMENT_PLUGINS_DIRECTORY = "../plugins";
/** /**
* The plugins repository. * The plugins repository.
*/ */
private File pluginsDirectory; private File pluginsDirectory;
private final ExtensionFinder extensionFinder; private ExtensionFinder extensionFinder;
private final PluginDescriptorFinder pluginDescriptorFinder; private PluginDescriptorFinder pluginDescriptorFinder;
private final PluginClasspath pluginClasspath; private PluginClasspath pluginClasspath;
/** /**
* A map of plugins this manager is responsible for (the key is the 'pluginId'). * A map of plugins this manager is responsible for (the key is the 'pluginId').
@ -92,10 +96,18 @@ public class DefaultPluginManager implements PluginManager {
protected CompoundClassLoader compoundClassLoader; protected CompoundClassLoader compoundClassLoader;
/** /**
* Th plugins directory is supplied by System.getProperty("pf4j.pluginsDir", "plugins"). * Cache value for the runtime mode. No need to re-read it because it wont change at
* runtime.
*/
private RuntimeMode runtimeMode;
/**
* The plugins directory is supplied by System.getProperty("pf4j.pluginsDir", "plugins").
*/ */
public DefaultPluginManager() { public DefaultPluginManager() {
this(new File(System.getProperty("pf4j.pluginsDir", "plugins"))); this.pluginsDirectory = createPluginsDirectory();
initialize();
} }
/** /**
@ -107,32 +119,7 @@ public class DefaultPluginManager implements PluginManager {
public DefaultPluginManager(File pluginsDirectory) { public DefaultPluginManager(File pluginsDirectory) {
this.pluginsDirectory = pluginsDirectory; this.pluginsDirectory = pluginsDirectory;
plugins = new HashMap<String, PluginWrapper>(); initialize();
pluginClassLoaders = new HashMap<String, PluginClassLoader>();
pathToIdMap = new HashMap<String, String>();
unresolvedPlugins = new ArrayList<PluginWrapper>();
resolvedPlugins = new ArrayList<PluginWrapper>();
startedPlugins = new ArrayList<PluginWrapper>();
disabledPlugins = new ArrayList<String>();
compoundClassLoader = new CompoundClassLoader();
pluginClasspath = createPluginClasspath();
pluginDescriptorFinder = createPluginDescriptorFinder();
extensionFinder = createExtensionFinder();
try {
// create a list with plugin identifiers that should be only accepted by this manager (whitelist from plugins/enabled.txt file)
enabledPlugins = FileUtils.readLines(new File(pluginsDirectory, "enabled.txt"), true);
log.info("Enabled plugins: {}", enabledPlugins);
// create a list with plugin identifiers that should not be accepted by this manager (blacklist from plugins/disabled.txt file)
disabledPlugins = FileUtils.readLines(new File(pluginsDirectory, "disabled.txt"), true);
log.info("Disabled plugins: {}", disabledPlugins);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
System.setProperty("pf4j.pluginsDir", pluginsDirectory.getAbsolutePath());
} }
@Override @Override
@ -223,6 +210,7 @@ public class DefaultPluginManager implements PluginManager {
filterList.add(new NotFileFilter(createHiddenPluginFilter())); filterList.add(new NotFileFilter(createHiddenPluginFilter()));
FileFilter pluginsFilter = new AndFileFilter(filterList); FileFilter pluginsFilter = new AndFileFilter(filterList);
File[] directories = pluginsDirectory.listFiles(pluginsFilter); File[] directories = pluginsDirectory.listFiles(pluginsFilter);
log.debug("Possible plugins: {}", Arrays.asList(directories));
if (directories.length == 0) { if (directories.length == 0) {
log.info("No plugins"); log.info("No plugins");
return; return;
@ -264,6 +252,20 @@ public class DefaultPluginManager implements PluginManager {
return extensions; return extensions;
} }
@Override
public RuntimeMode getRuntimeMode() {
if (runtimeMode == null) {
// retrieves the runtime mode from system
String modeAsString = System.getProperty("pf4j.mode", RuntimeMode.DEPLOYMENT.toString());
runtimeMode = RuntimeMode.byName(modeAsString);
log.info("PF4J runtime mode: '" + runtimeMode + "'");
}
return runtimeMode;
}
/** /**
* Retrieves the {@link PluginWrapper} that loaded the given class 'clazz'. * Retrieves the {@link PluginWrapper} that loaded the given class 'clazz'.
*/ */
@ -280,8 +282,15 @@ public class DefaultPluginManager implements PluginManager {
/** /**
* Add the possibility to override the PluginDescriptorFinder. * Add the possibility to override the PluginDescriptorFinder.
* By default if getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a
* PropertiesPluginDescriptorFinder is returned else this method returns
* DefaultPluginDescriptorFinder.
*/ */
protected PluginDescriptorFinder createPluginDescriptorFinder() { protected PluginDescriptorFinder createPluginDescriptorFinder() {
if (RuntimeMode.DEVELOPMENT.equals(getRuntimeMode())) {
return new PropertiesPluginDescriptorFinder();
}
return new DefaultPluginDescriptorFinder(pluginClasspath); return new DefaultPluginDescriptorFinder(pluginClasspath);
} }
@ -294,8 +303,15 @@ public class DefaultPluginManager implements PluginManager {
/** /**
* Add the possibility to override the PluginClassPath. * Add the possibility to override the PluginClassPath.
* By default if getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a
* DevelopmentPluginClasspath is returned else this method returns
* PluginClasspath.
*/ */
protected PluginClasspath createPluginClasspath() { protected PluginClasspath createPluginClasspath() {
if (RuntimeMode.DEVELOPMENT.equals(getRuntimeMode())) {
return new DevelopmentPluginClasspath();
}
return new PluginClasspath(); return new PluginClasspath();
} }
@ -311,6 +327,57 @@ public class DefaultPluginManager implements PluginManager {
return new HiddenFilter(); return new HiddenFilter();
} }
/**
* Add the possibility to override the plugins directory.
* If a "pf4j.pluginsDir" system property is defined than this method returns
* that directory.
* If getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a
* DEVELOPMENT_PLUGINS_DIRECTORY ("../plugins") is returned else this method returns
* DEFAULT_PLUGINS_DIRECTORY ("plugins").
* @return
*/
protected File createPluginsDirectory() {
String pluginsDir = System.getProperty("pf4j.pluginsDir");
if (pluginsDir == null) {
if (RuntimeMode.DEVELOPMENT.equals(getRuntimeMode())) {
pluginsDir = DEVELOPMENT_PLUGINS_DIRECTORY;
} else {
pluginsDir = DEFAULT_PLUGINS_DIRECTORY;
}
}
return new File(pluginsDir);
}
private void initialize() {
plugins = new HashMap<String, PluginWrapper>();
pluginClassLoaders = new HashMap<String, PluginClassLoader>();
pathToIdMap = new HashMap<String, String>();
unresolvedPlugins = new ArrayList<PluginWrapper>();
resolvedPlugins = new ArrayList<PluginWrapper>();
startedPlugins = new ArrayList<PluginWrapper>();
disabledPlugins = new ArrayList<String>();
compoundClassLoader = new CompoundClassLoader();
pluginClasspath = createPluginClasspath();
pluginDescriptorFinder = createPluginDescriptorFinder();
extensionFinder = createExtensionFinder();
try {
// create a list with plugin identifiers that should be only accepted by this manager (whitelist from plugins/enabled.txt file)
enabledPlugins = FileUtils.readLines(new File(pluginsDirectory, "enabled.txt"), true);
log.info("Enabled plugins: {}", enabledPlugins);
// create a list with plugin identifiers that should not be accepted by this manager (blacklist from plugins/disabled.txt file)
disabledPlugins = FileUtils.readLines(new File(pluginsDirectory, "disabled.txt"), true);
log.info("Disabled plugins: {}", disabledPlugins);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
System.setProperty("pf4j.pluginsDir", pluginsDirectory.getAbsolutePath());
}
private void loadPlugin(File pluginDirectory) throws PluginException { private void loadPlugin(File pluginDirectory) throws PluginException {
// try to load the plugin // try to load the plugin
String pluginName = pluginDirectory.getName(); String pluginName = pluginDirectory.getName();
@ -343,6 +410,7 @@ public class DefaultPluginManager implements PluginManager {
// create the plugin wrapper // create the plugin wrapper
log.debug("Creating wrapper for plugin '{}'", pluginPath); log.debug("Creating wrapper for plugin '{}'", pluginPath);
PluginWrapper pluginWrapper = new PluginWrapper(pluginDescriptor, pluginPath, pluginLoader.getPluginClassLoader()); PluginWrapper pluginWrapper = new PluginWrapper(pluginDescriptor, pluginPath, pluginLoader.getPluginClassLoader());
pluginWrapper.setRuntimeMode(getRuntimeMode());
log.debug("Created wrapper '{}' for plugin '{}'", pluginWrapper, pluginPath); log.debug("Created wrapper '{}' for plugin '{}'", pluginWrapper, pluginPath);
String pluginId = pluginDescriptor.getPluginId(); String pluginId = pluginDescriptor.getPluginId();

36
pf4j/src/main/java/ro/fortsoft/pf4j/DevelopmentPluginClasspath.java

@ -0,0 +1,36 @@
/*
* Copyright 2013 Decebal Suiu
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
* the License. You may obtain a copy of the License in the LICENSE file, or 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 ro.fortsoft.pf4j;
/**
* Overwrite classes directories to "target/classes" and lib directories to "target/lib".
*
* @author Decebal Suiu
*/
public class DevelopmentPluginClasspath extends PluginClasspath {
private static final String DEVELOPMENT_CLASSES_DIRECTORY = "target/classes";
private static final String DEVELOPMENT_LIB_DIRECTORY = "target/lib";
public DevelopmentPluginClasspath() {
super();
}
@Override
protected void addResources() {
classesDirectories.add(DEVELOPMENT_CLASSES_DIRECTORY);
libDirectories.add(DEVELOPMENT_LIB_DIRECTORY);
}
}

13
pf4j/src/main/java/ro/fortsoft/pf4j/PluginClasspath.java

@ -28,16 +28,14 @@ public class PluginClasspath {
private static final String DEFAULT_CLASSES_DIRECTORY = "classes"; private static final String DEFAULT_CLASSES_DIRECTORY = "classes";
private static final String DEFAULT_LIB_DIRECTORY = "lib"; private static final String DEFAULT_LIB_DIRECTORY = "lib";
private List<String> classesDirectories; protected List<String> classesDirectories;
private List<String> libDirectories; protected List<String> libDirectories;
public PluginClasspath() { public PluginClasspath() {
classesDirectories = new ArrayList<String>(); classesDirectories = new ArrayList<String>();
libDirectories = new ArrayList<String>(); libDirectories = new ArrayList<String>();
// add defaults addResources();
classesDirectories.add(DEFAULT_CLASSES_DIRECTORY);
libDirectories.add(DEFAULT_LIB_DIRECTORY);
} }
public List<String> getClassesDirectories() { public List<String> getClassesDirectories() {
@ -56,4 +54,9 @@ public class PluginClasspath {
this.libDirectories = libDirectories; this.libDirectories = libDirectories;
} }
protected void addResources() {
classesDirectories.add(DEFAULT_CLASSES_DIRECTORY);
libDirectories.add(DEFAULT_LIB_DIRECTORY);
}
} }

5
pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java

@ -61,4 +61,9 @@ public interface PluginManager {
public <T> List<T> getExtensions(Class<T> type); public <T> List<T> getExtensions(Class<T> type);
/**
* The runtime mode. Must currently be either DEVELOPMENT or DEPLOYMENT.
*/
public RuntimeMode getRuntimeMode();
} }

9
pf4j/src/main/java/ro/fortsoft/pf4j/PluginWrapper.java

@ -27,6 +27,7 @@ public class PluginWrapper {
PluginClassLoader pluginClassLoader; PluginClassLoader pluginClassLoader;
Plugin plugin; Plugin plugin;
PluginState pluginState; PluginState pluginState;
RuntimeMode runtimeMode;
public PluginWrapper(PluginDescriptor descriptor, String pluginPath, PluginClassLoader pluginClassLoader) { public PluginWrapper(PluginDescriptor descriptor, String pluginPath, PluginClassLoader pluginClassLoader) {
this.descriptor = descriptor; this.descriptor = descriptor;
@ -74,6 +75,10 @@ public class PluginWrapper {
return pluginState; return pluginState;
} }
public RuntimeMode getRuntimeMode() {
return runtimeMode;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
@ -115,6 +120,10 @@ public class PluginWrapper {
this.pluginState = pluginState; this.pluginState = pluginState;
} }
void setRuntimeMode(RuntimeMode runtimeMode) {
this.runtimeMode = runtimeMode;
}
private Plugin createPluginInstance() throws Exception { private Plugin createPluginInstance() throws Exception {
String pluginClassName = descriptor.getPluginClass(); String pluginClassName = descriptor.getPluginClass();
Class<?> pluginClass = pluginClassLoader.loadClass(pluginClassName); Class<?> pluginClass = pluginClassLoader.loadClass(pluginClassName);

55
pf4j/src/main/java/ro/fortsoft/pf4j/RuntimeMode.java

@ -0,0 +1,55 @@
/*
* Copyright 2013 Decebal Suiu
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with
* the License. You may obtain a copy of the License in the LICENSE file, or 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 ro.fortsoft.pf4j;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* @author Decebal Suiu
*/
public enum RuntimeMode {
DEVELOPMENT("development"), // development
DEPLOYMENT("deployment"); // deployment
private final String name;
private static final Map<String, RuntimeMode> map = new HashMap<String, RuntimeMode>();
static {
for (RuntimeMode mode : RuntimeMode.values()) {
map.put(mode.name, mode);
}
}
private RuntimeMode(final String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
public static RuntimeMode byName(String name) {
if (map.containsKey(name)) {
return map.get(name);
}
throw new NoSuchElementException("Cannot found PF4J runtime mode with name '" + name +
"'. Must be 'development' or 'deployment'.");
}
}
Loading…
Cancel
Save