aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDecebal Suiu <decebal.suiu@gmail.com>2014-04-09 17:33:58 +0300
committerDecebal Suiu <decebal.suiu@gmail.com>2014-04-09 17:33:58 +0300
commit7e00f212b15a07584bf0130272761675302c1116 (patch)
tree40b91ea1b89536641a07f782789e60038f2c8bbc
parent5287be5438801f66c529bf41ac1631d346906d37 (diff)
downloadpf4j-7e00f212b15a07584bf0130272761675302c1116.tar.gz
pf4j-7e00f212b15a07584bf0130272761675302c1116.zip
add listeners to plugin state changes
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java6
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java113
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionFinder.java2
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/PluginLoader.java25
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java4
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/PluginStateEvent.java57
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/PluginStateListener.java29
-rw-r--r--pf4j/src/main/java/ro/fortsoft/pf4j/PluginWrapper.java3
8 files changed, 186 insertions, 53 deletions
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java
index c31f5d3..295d5c8 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultExtensionFinder.java
@@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory;
*
* @author Decebal Suiu
*/
-public class DefaultExtensionFinder implements ExtensionFinder {
+public class DefaultExtensionFinder implements ExtensionFinder, PluginStateListener {
private static final Logger log = LoggerFactory.getLogger(DefaultExtensionFinder.class);
@@ -95,8 +95,8 @@ public class DefaultExtensionFinder implements ExtensionFinder {
return entries.get(pluginId);
}
- @Override
- public void reset() {
+ public void pluginStateChanged(PluginStateEvent event) {
+ // TODO optimize (do only for some transitions)
// clear cache
entries = null;
}
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
index cf02045..47dce71 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/DefaultPluginManager.java
@@ -78,6 +78,11 @@ public class DefaultPluginManager implements PluginManager {
private List<String> disabledPlugins;
/**
+ * The registered {@link PluginStateListener}s.
+ */
+ private List<PluginStateListener> pluginStateListeners;
+
+ /**
* Cache value for the runtime mode. No need to re-read it because it wont change at
* runtime.
*/
@@ -143,7 +148,7 @@ public class DefaultPluginManager implements PluginManager {
@Override
public String loadPlugin(File pluginArchiveFile) {
- if (pluginArchiveFile == null || !pluginArchiveFile.exists()) {
+ if ((pluginArchiveFile == null) || !pluginArchiveFile.exists()) {
throw new IllegalArgumentException(String.format("Specified plugin %s does not exist!", pluginArchiveFile));
}
@@ -153,7 +158,7 @@ public class DefaultPluginManager implements PluginManager {
} catch (IOException e) {
log.error(e.getMessage(), e);
}
- if (pluginDirectory == null || !pluginDirectory.exists()) {
+ if ((pluginDirectory == null) || !pluginDirectory.exists()) {
throw new IllegalArgumentException(String.format("Failed to expand %s", pluginArchiveFile));
}
@@ -162,7 +167,9 @@ public class DefaultPluginManager implements PluginManager {
// TODO uninstalled plugin dependencies?
unresolvedPlugins.remove(pluginWrapper);
resolvedPlugins.add(pluginWrapper);
- extensionFinder.reset();
+
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, null));
+
return pluginWrapper.getDescriptor().getPluginId();
} catch (PluginException e) {
log.error(e.getMessage(), e);
@@ -185,6 +192,8 @@ public class DefaultPluginManager implements PluginManager {
pluginWrapper.getPlugin().start();
pluginWrapper.setPluginState(PluginState.STARTED);
startedPlugins.add(pluginWrapper);
+
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
@@ -201,17 +210,18 @@ public class DefaultPluginManager implements PluginManager {
throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));
}
- PluginWrapper pluginWrapper = plugins.get(pluginId);
+ PluginWrapper pluginWrapper = getPlugin(pluginId);
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
- if (PluginState.STARTED == pluginWrapper.getPluginState()) {
+ PluginState pluginState = pluginWrapper.getPluginState();
+ if (PluginState.STARTED == pluginState) {
log.debug("Already started plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
return PluginState.STARTED;
}
- if (PluginState.DISABLED == pluginWrapper.getPluginState()) {
+ if (PluginState.DISABLED == pluginState) {
// automatically enable plugin on manual plugin start
if (!enablePlugin(pluginId)) {
- return pluginWrapper.getPluginState();
+ return pluginState;
}
}
@@ -224,7 +234,9 @@ public class DefaultPluginManager implements PluginManager {
pluginWrapper.getPlugin().start();
pluginWrapper.setPluginState(PluginState.STARTED);
startedPlugins.add(pluginWrapper);
- } catch (PluginException e) {
+
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
+ } catch (PluginException e) {
log.error(e.getMessage(), e);
}
@@ -241,13 +253,16 @@ public class DefaultPluginManager implements PluginManager {
Iterator<PluginWrapper> itr = startedPlugins.iterator();
while (itr.hasNext()) {
PluginWrapper pluginWrapper = itr.next();
- if (PluginState.STARTED == pluginWrapper.getPluginState()) {
+ PluginState pluginState = pluginWrapper.getPluginState();
+ if (PluginState.STARTED == pluginState) {
try {
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
log.info("Stop plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
pluginWrapper.getPlugin().stop();
pluginWrapper.setPluginState(PluginState.STOPPED);
itr.remove();
+
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
@@ -264,17 +279,18 @@ public class DefaultPluginManager implements PluginManager {
throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));
}
- PluginWrapper pluginWrapper = plugins.get(pluginId);
+ PluginWrapper pluginWrapper = getPlugin(pluginId);
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
- if (PluginState.STOPPED == pluginWrapper.getPluginState()) {
+ PluginState pluginState = pluginWrapper.getPluginState();
+ if (PluginState.STOPPED == pluginState) {
log.debug("Already stopped plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
return PluginState.STOPPED;
}
// test for disabled plugin
- if (PluginState.DISABLED == pluginWrapper.getPluginState()) {
+ if (PluginState.DISABLED == pluginState) {
// do nothing
- return pluginWrapper.getPluginState();
+ return pluginState;
}
for (PluginDependency dependency : pluginDescriptor.getDependencies()) {
@@ -286,6 +302,8 @@ public class DefaultPluginManager implements PluginManager {
pluginWrapper.getPlugin().stop();
pluginWrapper.setPluginState(PluginState.STOPPED);
startedPlugins.remove(pluginWrapper);
+
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
} catch (PluginException e) {
log.error(e.getMessage(), e);
}
@@ -353,12 +371,12 @@ public class DefaultPluginManager implements PluginManager {
@Override
public boolean unloadPlugin(String pluginId) {
try {
- PluginState state = stopPlugin(pluginId);
- if (PluginState.STOPPED != state) {
+ PluginState pluginState = stopPlugin(pluginId);
+ if (PluginState.STOPPED != pluginState) {
return false;
}
- PluginWrapper pluginWrapper = plugins.get(pluginId);
+ PluginWrapper pluginWrapper = getPlugin(pluginId);
PluginDescriptor descriptor = pluginWrapper.getDescriptor();
List<PluginDependency> dependencies = descriptor.getDependencies();
for (PluginDependency dependency : dependencies) {
@@ -371,7 +389,8 @@ public class DefaultPluginManager implements PluginManager {
plugins.remove(pluginId);
resolvedPlugins.remove(pluginWrapper);
pathToIdMap.remove(pluginWrapper.getPluginPath());
- extensionFinder.reset();
+
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
// remove the classloader
if (pluginClassLoaders.containsKey(pluginId)) {
@@ -398,17 +417,18 @@ public class DefaultPluginManager implements PluginManager {
}
- PluginWrapper pluginWrapper = plugins.get(pluginId);
+ PluginWrapper pluginWrapper = getPlugin(pluginId);
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
-
- if (PluginState.DISABLED == getPlugin(pluginId).getPluginState()) {
+ PluginState pluginState = pluginWrapper.getPluginState();
+ if (PluginState.DISABLED == pluginState) {
log.debug("Already disabled plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
return true;
}
if (PluginState.STOPPED == stopPlugin(pluginId)) {
- getPlugin(pluginId).setPluginState(PluginState.DISABLED);
- extensionFinder.reset();
+ pluginWrapper.setPluginState(PluginState.DISABLED);
+
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, PluginState.STOPPED));
if (disabledPlugins.add(pluginId)) {
try {
@@ -432,10 +452,10 @@ public class DefaultPluginManager implements PluginManager {
throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));
}
- PluginWrapper pluginWrapper = plugins.get(pluginId);
+ PluginWrapper pluginWrapper = getPlugin(pluginId);
PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();
-
- if (PluginState.DISABLED != getPlugin(pluginId).getPluginState()) {
+ PluginState pluginState = pluginWrapper.getPluginState();
+ if (PluginState.DISABLED != pluginState) {
log.debug("Plugin plugin '{}:{}' is not disabled", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
return true;
}
@@ -449,8 +469,9 @@ public class DefaultPluginManager implements PluginManager {
return false;
}
- getPlugin(pluginId).setPluginState(PluginState.CREATED);
- extensionFinder.reset();
+ pluginWrapper.setPluginState(PluginState.CREATED);
+
+ firePluginStateEvent(new PluginStateEvent(this, pluginWrapper, pluginState));
log.info("Enabled plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());
@@ -462,10 +483,10 @@ public class DefaultPluginManager implements PluginManager {
if (!plugins.containsKey(pluginId)) {
throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));
}
- PluginWrapper pw = getPlugin(pluginId);
- PluginState state = stopPlugin(pluginId);
- if (PluginState.STOPPED != state) {
+ PluginWrapper pluginWrapper = getPlugin(pluginId);
+ PluginState pluginState = stopPlugin(pluginId);
+ if (PluginState.STOPPED != pluginState) {
log.error("Failed to stop plugin {} on delete", pluginId);
return false;
}
@@ -475,14 +496,14 @@ public class DefaultPluginManager implements PluginManager {
return false;
}
- File pluginFolder = new File(pluginsDirectory, pw.getPluginPath());
+ File pluginFolder = new File(pluginsDirectory, pluginWrapper.getPluginPath());
File pluginZip = null;
FileFilter zipFilter = new ZipFileFilter();
File[] zipFiles = pluginsDirectory.listFiles(zipFilter);
if (zipFiles != null) {
// strip prepended / from the plugin path
- String dirName = pw.getPluginPath().substring(1);
+ String dirName = pluginWrapper.getPluginPath().substring(1);
// find the zip file that matches the plugin path
for (File zipFile : zipFiles) {
String name = zipFile.getName().substring(0, zipFile.getName().lastIndexOf('.'));
@@ -499,6 +520,7 @@ public class DefaultPluginManager implements PluginManager {
if (pluginZip != null && pluginZip.exists()) {
FileUtils.delete(pluginZip);
}
+
return true;
}
@@ -551,10 +573,21 @@ public class DefaultPluginManager implements PluginManager {
}
}
log.warn("Failed to find the plugin for {}", clazz);
+
return null;
}
- /**
+ @Override
+ public synchronized void addPluginStateListener(PluginStateListener listener) {
+ pluginStateListeners.add(listener);
+ }
+
+ @Override
+ public synchronized void removePluginStateListener(PluginStateListener listener) {
+ pluginStateListeners.remove(listener);
+ }
+
+ /**
* Add the possibility to override the PluginDescriptorFinder.
* By default if getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a
* PropertiesPluginDescriptorFinder is returned else this method returns
@@ -572,7 +605,10 @@ public class DefaultPluginManager implements PluginManager {
* Add the possibility to override the ExtensionFinder.
*/
protected ExtensionFinder createExtensionFinder() {
- return new DefaultExtensionFinder(this);
+ DefaultExtensionFinder extensionFinder = new DefaultExtensionFinder(this);
+ addPluginStateListener(extensionFinder);
+
+ return extensionFinder;
}
/**
@@ -632,6 +668,8 @@ public class DefaultPluginManager implements PluginManager {
startedPlugins = new ArrayList<PluginWrapper>();
disabledPlugins = new ArrayList<String>();
+ pluginStateListeners = new ArrayList<PluginStateListener>();
+
pluginClasspath = createPluginClasspath();
pluginDescriptorFinder = createPluginDescriptorFinder();
extensionFinder = createExtensionFinder();
@@ -739,4 +777,11 @@ public class DefaultPluginManager implements PluginManager {
}
}
+ private synchronized void firePluginStateEvent(PluginStateEvent event) {
+ for (PluginStateListener listener : pluginStateListeners) {
+ log.debug("Fire '{}' to '{}'", event, listener);
+ listener.pluginStateChanged(event);
+ }
+ }
+
}
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionFinder.java b/pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionFinder.java
index c518566..7236b49 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionFinder.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/ExtensionFinder.java
@@ -30,6 +30,4 @@ public interface ExtensionFinder {
*/
public Set<String> findClassNames(String pluginId);
- public void reset();
-
}
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginLoader.java b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginLoader.java
index 8bd2daa..03e7683 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginLoader.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginLoader.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.
@@ -46,10 +46,11 @@ class PluginLoader {
public PluginLoader(PluginManager pluginManager, PluginDescriptor pluginDescriptor, File pluginRepository, PluginClasspath pluginClasspath) {
this.pluginRepository = pluginRepository;
- this.pluginClasspath = pluginClasspath;
- ClassLoader parent = getClass().getClassLoader();
- pluginClassLoader = new PluginClassLoader(pluginManager, pluginDescriptor, parent);
- log.debug("Created class loader {}", pluginClassLoader);
+ this.pluginClasspath = pluginClasspath;
+
+ ClassLoader parent = getClass().getClassLoader();
+ pluginClassLoader = new PluginClassLoader(pluginManager, pluginDescriptor, parent);
+ log.debug("Created class loader '{}'", pluginClassLoader);
}
public File getPluginRepository() {
@@ -70,15 +71,15 @@ class PluginLoader {
private boolean loadClasses() {
List<String> classesDirectories = pluginClasspath.getClassesDirectories();
-
+
// add each classes directory to plugin class loader
for (String classesDirectory : classesDirectories) {
// make 'classesDirectory' absolute
File file = new File(pluginRepository, classesDirectory).getAbsoluteFile();
-
+
if (file.exists() && file.isDirectory()) {
log.debug("Found '{}' directory", file.getPath());
-
+
try {
pluginClassLoader.addURL(file.toURI().toURL());
log.debug("Added '{}' to the class loader path", file);
@@ -98,12 +99,12 @@ class PluginLoader {
*/
private boolean loadJars() {
List<String> libDirectories = pluginClasspath.getLibDirectories();
-
+
// add each jars directory to plugin class loader
for (String libDirectory : libDirectories) {
// make 'libDirectory' absolute
File file = new File(pluginRepository, libDirectory).getAbsoluteFile();
-
+
// collect all jars from current lib directory in jars variable
Vector<File> jars = new Vector<File>();
getJars(jars, file);
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java
index f656313..daf6fbf 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginManager.java
@@ -137,4 +137,8 @@ public interface PluginManager {
*/
public RuntimeMode getRuntimeMode();
+ public void addPluginStateListener(PluginStateListener listener);
+
+ public void removePluginStateListener(PluginStateListener listener);
+
}
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginStateEvent.java b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginStateEvent.java
new file mode 100644
index 0000000..bea202e
--- /dev/null
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginStateEvent.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 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.EventObject;
+
+/**
+ * @author Decebal Suiu
+ */
+public class PluginStateEvent extends EventObject {
+
+ private PluginWrapper plugin;
+ private PluginState oldState;
+
+ public PluginStateEvent(PluginManager source, PluginWrapper plugin, PluginState oldState) {
+ super(source);
+
+ this.plugin = plugin;
+ this.oldState = oldState;
+ }
+
+ @Override
+ public PluginManager getSource() {
+ return (PluginManager) super.getSource();
+ }
+
+ public PluginWrapper getPlugin() {
+ return plugin;
+ }
+
+ public PluginState getPluginState() {
+ return plugin.getPluginState();
+ }
+
+ public PluginState getOldState() {
+ return oldState;
+ }
+
+ @Override
+ public String toString() {
+ return "PluginStateEvent [plugin=" + plugin.getPluginId() +
+ ", newState=" + getPluginState() +
+ ", oldState=" + oldState +
+ ']';
+ }
+
+}
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginStateListener.java b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginStateListener.java
new file mode 100644
index 0000000..4af2e91
--- /dev/null
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginStateListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 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.EventListener;
+
+/**
+ * PluginStateListener defines the interface for an object that listens to plugin state changes.
+ *
+ * @author Decebal Suiu
+ */
+public interface PluginStateListener extends EventListener {
+
+ /**
+ * Invoked when a plugin's state (for example DISABLED, STARTED) is changed.
+ */
+ public void pluginStateChanged(PluginStateEvent event);
+
+}
diff --git a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginWrapper.java b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginWrapper.java
index b2ab37d..da9908a 100644
--- a/pf4j/src/main/java/ro/fortsoft/pf4j/PluginWrapper.java
+++ b/pf4j/src/main/java/ro/fortsoft/pf4j/PluginWrapper.java
@@ -119,8 +119,7 @@ public class PluginWrapper {
@Override
public String toString() {
- return "PluginWrapper [descriptor=" + descriptor + ", pluginPath="
- + pluginPath + "]";
+ return "PluginWrapper [descriptor=" + descriptor + ", pluginPath=" + pluginPath + "]";
}
void setPluginState(PluginState pluginState) {