Browse Source

a first version related to enable-disable plugin

pull/8/merge
Decebal Suiu 11 years ago
parent
commit
746ac803b8
  1. 34
      demo/app/src/main/java/ro/fortsoft/pf4j/demo/Boot.java
  2. 6
      demo/disabled.txt
  3. 6
      demo/enabled.txt
  4. 124
      pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
  5. 32
      pf4j/src/main/java/ro/fortsoft/pf4j/PluginClassLoader.java
  6. 28
      pf4j/src/main/java/ro/fortsoft/pf4j/PluginClasspath.java
  7. 27
      pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java
  8. 34
      pf4j/src/main/java/ro/fortsoft/pf4j/PluginState.java
  9. 22
      pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java

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

@ -1,11 +1,11 @@
/*
* Copyright 2012 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.
@ -26,24 +26,30 @@ import ro.fortsoft.pf4j.demo.api.Greeting;
* @author Decebal Suiu
*/
public class Boot {
public static void main(String[] args) {
// print logo
printLogo();
// create the plugin manager
final PluginManager pluginManager = new DefaultPluginManager();
// load and start (active/resolved) the plugins
// 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
// retrieves the extensions for Greeting extension point
List<Greeting> greetings = pluginManager.getExtensions(Greeting.class);
System.out.println(String.format("### Found %d extensions for the extension point '%s'", greetings.size(), Greeting.class.getName()));
for (Greeting greeting : greetings) {
System.out.println(">>> " + greeting.getGreeting());
}
// stop the plugins
pluginManager.stopPlugins();
/*
@ -53,15 +59,15 @@ public class Boot {
public void run() {
pluginManager.stopPlugins();
}
});
*/
}
}
private static void printLogo() {
System.out.println(StringUtils.repeat("#", 40));
System.out.println(StringUtils.center("PF4J-DEMO", 40));
System.out.println(StringUtils.repeat("#", 40));
System.out.println(StringUtils.repeat("#", 40));
}
}

6
demo/disabled.txt

@ -1,6 +0,0 @@
########################################
# - load all plugins except these
# - add one plugin id on each line
# - put this file in plugins folder
########################################
welcome-plugin

6
demo/enabled.txt

@ -1,6 +0,0 @@
########################################
# - load only these plugins
# - add one plugin id on each line
# - put this file in plugins folder
########################################
welcome-plugin

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

@ -127,6 +127,18 @@ public class DefaultPluginManager implements PluginManager {
return new ArrayList<PluginWrapper>(plugins.values());
}
@Override
public List<PluginWrapper> getPlugins(PluginState pluginState) {
List<PluginWrapper> plugins= new ArrayList<PluginWrapper>();
for (PluginWrapper plugin : getPlugins()) {
if (pluginState.equals(plugin.getPluginState())) {
plugins.add(plugin);
}
}
return plugins;
}
@Override
public List<PluginWrapper> getResolvedPlugins() {
return resolvedPlugins;
@ -182,14 +194,17 @@ public class DefaultPluginManager implements PluginManager {
@Override
public void startPlugins() {
for (PluginWrapper pluginWrapper : resolvedPlugins) {
try {
log.info("Start plugin '{}'", pluginWrapper.getDescriptor().getPluginId());
pluginWrapper.getPlugin().start();
pluginWrapper.setPluginState(PluginState.STARTED);
startedPlugins.add(pluginWrapper);
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
if (!isPluginDisabled(pluginDescriptor.getPluginId())) {
try {
log.info("Start plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
pluginWrapper.getPlugin().start();
pluginWrapper.setPluginState(PluginState.STARTED);
startedPlugins.add(pluginWrapper);
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
}
}
}
@ -201,15 +216,24 @@ public class DefaultPluginManager implements PluginManager {
if (!plugins.containsKey(pluginId)) {
throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));
}
PluginWrapper pluginWrapper = plugins.get(pluginId);
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
if (pluginWrapper.getPluginState().equals(PluginState.STARTED)) {
log.debug("Already started plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
return PluginState.STARTED;
}
for (PluginDependency dependency : pluginDescriptor.getDependencies()) {
// test for disabled plugin
if (isPluginDisabled(pluginDescriptor.getPluginId())) {
// do nothing
return pluginWrapper.getPluginState();
}
for (PluginDependency dependency : pluginDescriptor.getDependencies()) {
startPlugin(dependency.getPluginId());
}
try {
log.info("Start plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
pluginWrapper.getPlugin().start();
@ -218,6 +242,7 @@ public class DefaultPluginManager implements PluginManager {
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
return pluginWrapper.getPluginState();
}
@ -232,14 +257,16 @@ public class DefaultPluginManager implements PluginManager {
while (itr.hasNext()) {
PluginWrapper pluginWrapper = itr.next();
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
try {
log.info("Stop plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
pluginWrapper.getPlugin().stop();
pluginWrapper.setPluginState(PluginState.STOPPED);
itr.remove();
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
if (!isPluginDisabled(pluginDescriptor.getPluginId())) {
try {
log.info("Stop plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
pluginWrapper.getPlugin().stop();
pluginWrapper.setPluginState(PluginState.STOPPED);
itr.remove();
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
}
}
}
@ -251,15 +278,24 @@ public class DefaultPluginManager implements PluginManager {
if (!plugins.containsKey(pluginId)) {
throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));
}
PluginWrapper pluginWrapper = plugins.get(pluginId);
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
if (pluginWrapper.getPluginState().equals(PluginState.STOPPED)) {
log.debug("Already stopped plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
return PluginState.STOPPED;
}
// test for disabled plugin
if (isPluginDisabled(pluginDescriptor.getPluginId())) {
// do nothing
return pluginWrapper.getPluginState();
}
for (PluginDependency dependency : pluginDescriptor.getDependencies()) {
stopPlugin(dependency.getPluginId());
}
try {
log.info("Stop plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
pluginWrapper.getPlugin().stop();
@ -268,6 +304,7 @@ public class DefaultPluginManager implements PluginManager {
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
return pluginWrapper.getPluginState();
}
@ -365,9 +402,46 @@ public class DefaultPluginManager implements PluginManager {
} catch (IllegalArgumentException e) {
// ignore not found exceptions because this method is recursive
}
return false;
}
@Override
public boolean disablePlugin(String pluginId) {
if (plugins.containsKey(pluginId)) {
log.debug("Unloading plugin {}", pluginId);
unloadPlugin(pluginId);
}
if (disabledPlugins.add(pluginId)) {
try {
FileUtils.writeLines(disabledPlugins, new File(pluginsDirectory, "disabled.txt"));
return true;
} catch (IOException e) {
log.error("Failed to disable plugin {}", pluginId, e);
}
}
return false;
}
@Override
public boolean enablePlugin(String pluginId) {
if (!disabledPlugins.remove(pluginId)) {
log.debug("Plugin {} was not disabled", pluginId);
return true;
}
try {
FileUtils.writeLines(disabledPlugins, new File(pluginsDirectory, "disabled.txt"));
return true;
} catch (IOException e) {
log.error("Failed to enable plugin {}", pluginId, e);
}
return false;
}
@Override
public boolean deletePlugin(String pluginId) {
if (!plugins.containsKey(pluginId)) {
@ -495,7 +569,8 @@ public class DefaultPluginManager implements PluginManager {
return new PluginClasspath();
}
protected boolean isPluginDisabled(String pluginId) {
@Override
public boolean isPluginDisabled(String pluginId) {
if (enabledPlugins.isEmpty()) {
return disabledPlugins.contains(pluginId);
}
@ -575,12 +650,6 @@ public class DefaultPluginManager implements PluginManager {
String pluginClassName = pluginDescriptor.getPluginClass();
log.debug("Class '{}' for plugin '{}'", pluginClassName, pluginPath);
// test for disabled plugin
if (isPluginDisabled(pluginDescriptor.getPluginId())) {
log.info("Plugin '{}' is disabled", pluginPath);
return null;
}
// load plugin
log.debug("Loading plugin '{}'", pluginPath);
PluginLoader pluginLoader = new PluginLoader(this, pluginDescriptor, pluginDirectory, pluginClasspath);
@ -591,6 +660,13 @@ public class DefaultPluginManager implements PluginManager {
log.debug("Creating wrapper for plugin '{}'", pluginPath);
PluginWrapper pluginWrapper = new PluginWrapper(pluginDescriptor, pluginPath, pluginLoader.getPluginClassLoader());
pluginWrapper.setRuntimeMode(getRuntimeMode());
/*
// test for disabled plugin
if (isPluginDisabled(pluginDescriptor.getPluginId())) {
log.info("Plugin '{}' is disabled", pluginPath);
pluginWrapper.setPluginState(PluginState.DISABLED);
}
*/
log.debug("Created wrapper '{}' for plugin '{}'", pluginWrapper, pluginPath);
String pluginId = pluginDescriptor.getPluginId();

32
pf4j/src/main/java/ro/fortsoft/pf4j/PluginClassLoader.java

@ -1,24 +1,27 @@
/*
* Copyright 2012 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.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
/**
* One instance of this class should be created by plugin manager for every available plug-in.
*
*
* @author Decebal Suiu
*/
public class PluginClassLoader extends URLClassLoader {
@ -29,10 +32,10 @@ public class PluginClassLoader extends URLClassLoader {
private PluginManager pluginManager;
private PluginDescriptor pluginDescriptor;
public PluginClassLoader(PluginManager pluginManager, PluginDescriptor pluginDescriptor, ClassLoader parent) {
super(new URL[0], parent);
this.pluginManager = pluginManager;
this.pluginDescriptor = pluginDescriptor;
}
@ -91,4 +94,21 @@ public class PluginClassLoader extends URLClassLoader {
return super.loadClass(className);
}
@Override
public URL getResource(String name) {
if (pluginManager.isPluginDisabled(pluginDescriptor.getPluginId())) {
return null;
}
return super.getResource(name);
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
if (pluginManager.isPluginDisabled(pluginDescriptor.getPluginId())) {
return Collections.emptyEnumeration();
}
return super.getResources(name);
}
}

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

@ -1,11 +1,11 @@
/*
* 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.
@ -16,25 +16,25 @@ import java.util.ArrayList;
import java.util.List;
/**
* The classpath of the plugin after it was unpacked.
* It contains classes directories and lib directories (directories that contains jars).
* All directories are relativ to plugin repository.
* The default values are "classes" and "lib".
*
* The classpath of the plugin after it was unpacked.
* It contains classes directories and lib directories (directories that contains jars).
* All directories are relative to plugin repository.
* The default values are "classes" and "lib".
*
* @author Decebal Suiu
*/
public class PluginClasspath {
private static final String DEFAULT_CLASSES_DIRECTORY = "classes";
private static final String DEFAULT_LIB_DIRECTORY = "lib";
protected List<String> classesDirectories;
protected List<String> libDirectories;
public PluginClasspath() {
classesDirectories = new ArrayList<String>();
libDirectories = new ArrayList<String>();
addResources();
}
@ -53,10 +53,10 @@ public class PluginClasspath {
public void setLibDirectories(List<String> libDirectories) {
this.libDirectories = libDirectories;
}
protected void addResources() {
classesDirectories.add(DEFAULT_CLASSES_DIRECTORY);
libDirectories.add(DEFAULT_LIB_DIRECTORY);
libDirectories.add(DEFAULT_LIB_DIRECTORY);
}
}

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

@ -28,15 +28,20 @@ public interface PluginManager {
*/
public List<PluginWrapper> getPlugins();
/**
* Retrieves all plugins with this state.
*/
public List<PluginWrapper> getPlugins(PluginState pluginState);
/**
* Retrieves all resolved plugins (with resolved dependency).
*/
public List<PluginWrapper> getResolvedPlugins();
public List<PluginWrapper> getResolvedPlugins();
/**
* Retrieves all unresolved plugins (with unresolved dependency).
*/
public List<PluginWrapper> getUnresolvedPlugins();
public List<PluginWrapper> getUnresolvedPlugins();
/**
* Retrieves all started plugins.
@ -88,6 +93,24 @@ public interface PluginManager {
*/
public boolean unloadPlugin(String pluginId);
public boolean isPluginDisabled(String pluginId);
/**
* Disables a plugin from being loaded.
*
* @param pluginId
* @return true if plugin is disabled
*/
public boolean disablePlugin(String pluginId);
/**
* Enables a plugin that has previously been disabled.
*
* @param pluginId
* @return true if plugin is enabled
*/
public boolean enablePlugin(String pluginId);
/**
* Deletes a plugin.
*

34
pf4j/src/main/java/ro/fortsoft/pf4j/PluginState.java

@ -1,11 +1,11 @@
/*
* Copyright 2012 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.
@ -18,19 +18,37 @@ package ro.fortsoft.pf4j;
public class PluginState {
public static final PluginState CREATED = new PluginState("CREATED");
public static final PluginState INITIALIZED = new PluginState("INITIALIZED");
// public static final PluginState INITIALIZED = new PluginState("INITIALIZED");
// public static final PluginState DISABLED = new PluginState("DISABLED");
public static final PluginState STARTED = new PluginState("STARTED");
public static final PluginState STOPPED = new PluginState("STOPPED");
public static final PluginState DESTROYED = new PluginState("DESTROYED");
public static final PluginState FAILED = new PluginState("FAILED");
// public static final PluginState DESTROYED = new PluginState("DESTROYED");
// public static final PluginState FAILED = new PluginState("FAILED");
private String status;
private PluginState(String status) {
this.status = status;
}
@Override
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PluginState that = (PluginState) o;
if (!status.equals(that.status)) return false;
return true;
}
@Override
public int hashCode() {
return status.hashCode();
}
@Override
public String toString() {
return status;
}

22
pf4j/src/main/java/ro/fortsoft/pf4j/util/FileUtils.java

@ -12,11 +12,9 @@
*/
package ro.fortsoft.pf4j.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -50,6 +48,21 @@ public class FileUtils {
return lines;
}
public static void writeLines(Collection<String> lines, File file) throws IOException {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file));
for (String line : lines) {
writer.write(line);
writer.write('\n');
}
} finally {
if (writer != null) {
writer.close();
}
}
}
/**
* Delete a file or recursively delete a folder.
*
@ -71,6 +84,7 @@ public class FileUtils {
}
}
success |= fileOrFolder.delete();
return success;
}
}

Loading…
Cancel
Save