/*\r
* Copyright 2012 Decebal Suiu\r
- * \r
+ *\r
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with\r
* the License. You may obtain a copy of the License in the LICENSE file, or at:\r
- * \r
+ *\r
* http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
+ *\r
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on\r
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the\r
* specific language governing permissions and limitations under the License.\r
import java.util.Arrays;\r
import java.util.Collections;\r
import java.util.HashMap;\r
+import java.util.Iterator;\r
import java.util.List;\r
import java.util.Map;\r
\r
public class DefaultPluginManager implements PluginManager {\r
\r
private static final Logger log = LoggerFactory.getLogger(DefaultPluginManager.class);\r
- \r
+\r
public static final String DEFAULT_PLUGINS_DIRECTORY = "plugins";\r
public static final String DEVELOPMENT_PLUGINS_DIRECTORY = "../plugins";\r
\r
private File pluginsDirectory;\r
\r
private ExtensionFinder extensionFinder;\r
- \r
+\r
private PluginDescriptorFinder pluginDescriptorFinder;\r
- \r
+\r
private PluginClasspath pluginClasspath;\r
- \r
+\r
/**\r
* A map of plugins this manager is responsible for (the key is the 'pluginId').\r
*/\r
* A list with resolved plugins (resolved dependency).\r
*/\r
private List<PluginWrapper> resolvedPlugins;\r
- \r
+\r
/**\r
* A list with started plugins.\r
*/\r
private List<PluginWrapper> startedPlugins;\r
- \r
+\r
private List<String> enabledPlugins;\r
private List<String> disabledPlugins;\r
- \r
+\r
/**\r
- * A compound class loader of resolved plugins. \r
+ * A compound class loader of resolved plugins.\r
*/\r
protected CompoundClassLoader compoundClassLoader;\r
- \r
+\r
/**\r
* Cache value for the runtime mode. No need to re-read it because it wont change at\r
* runtime.\r
*/\r
private RuntimeMode runtimeMode;\r
- \r
+\r
/**\r
* The plugins directory is supplied by System.getProperty("pf4j.pluginsDir", "plugins").\r
*/\r
public DefaultPluginManager() {\r
this.pluginsDirectory = createPluginsDirectory();\r
- \r
+\r
initialize();\r
}\r
- \r
+\r
/**\r
* Constructs DefaultPluginManager which the given plugins directory.\r
*\r
*/\r
public DefaultPluginManager(File pluginsDirectory) {\r
this.pluginsDirectory = pluginsDirectory;\r
- \r
+\r
initialize();\r
}\r
\r
public List<PluginWrapper> getStartedPlugins() {\r
return startedPlugins;\r
}\r
- \r
+\r
/**\r
* Start all active plugins.\r
*/\r
}\r
}\r
\r
+ /**\r
+ * Start the specified plugin and it's dependencies.\r
+ */\r
+ @Override\r
+ public PluginState startPlugin(String pluginId) {\r
+ if (!plugins.containsKey(pluginId)) {\r
+ throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));\r
+ }\r
+ PluginWrapper pluginWrapper = plugins.get(pluginId);\r
+ PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();\r
+ if (pluginWrapper.getPluginState().equals(PluginState.STARTED)) {\r
+ log.debug("Already started plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());\r
+ return PluginState.STARTED;\r
+ }\r
+ for (PluginDependency dependency : pluginDescriptor.getDependencies()) {\r
+ startPlugin(dependency.getPluginId());\r
+ }\r
+ try {\r
+ log.info("Start plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());\r
+ pluginWrapper.getPlugin().start();\r
+ pluginWrapper.setPluginState(PluginState.STARTED);\r
+ startedPlugins.add(pluginWrapper);\r
+ } catch (PluginException e) {\r
+ log.error(e.getMessage(), e);\r
+ }\r
+ return pluginWrapper.getPluginState();\r
+ }\r
+\r
/**\r
* Stop all active plugins.\r
*/\r
public void stopPlugins() {\r
// stop started plugins in reverse order\r
Collections.reverse(startedPlugins);\r
- for (PluginWrapper pluginWrapper : startedPlugins) {\r
+ Iterator<PluginWrapper> itr = startedPlugins.iterator();\r
+ while (itr.hasNext()) {\r
+ PluginWrapper pluginWrapper = itr.next();\r
+ PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();\r
try {\r
- log.info("Stop plugin '{}'", pluginWrapper.getDescriptor().getPluginId());\r
+ log.info("Stop plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());\r
pluginWrapper.getPlugin().stop();\r
pluginWrapper.setPluginState(PluginState.STOPPED);\r
+ itr.remove();\r
} catch (PluginException e) {\r
log.error(e.getMessage(), e);\r
}\r
}\r
}\r
\r
+ /**\r
+ * Stop the specified plugin and it's dependencies.\r
+ */\r
+ @Override\r
+ public PluginState stopPlugin(String pluginId) {\r
+ if (!plugins.containsKey(pluginId)) {\r
+ throw new IllegalArgumentException(String.format("Unknown pluginId %s", pluginId));\r
+ }\r
+ PluginWrapper pluginWrapper = plugins.get(pluginId);\r
+ PluginDescriptor pluginDescriptor = pluginWrapper.getDescriptor();\r
+ if (pluginWrapper.getPluginState().equals(PluginState.STOPPED)) {\r
+ log.debug("Already stopped plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());\r
+ return PluginState.STOPPED;\r
+ }\r
+ for (PluginDependency dependency : pluginDescriptor.getDependencies()) {\r
+ stopPlugin(dependency.getPluginId());\r
+ }\r
+ try {\r
+ log.info("Stop plugin '{}:{}'", pluginDescriptor.getPluginId(), pluginDescriptor.getVersion());\r
+ pluginWrapper.getPlugin().stop();\r
+ pluginWrapper.setPluginState(PluginState.STOPPED);\r
+ startedPlugins.remove(pluginWrapper);\r
+ } catch (PluginException e) {\r
+ log.error(e.getMessage(), e);\r
+ }\r
+ return pluginWrapper.getPluginState();\r
+ }\r
+\r
/**\r
* Load plugins.\r
*/\r
for (ExtensionWrapper<T> extensionWrapper : extensionsWrapper) {\r
extensions.add(extensionWrapper.getInstance());\r
}\r
- \r
+\r
return extensions;\r
}\r
- \r
+\r
@Override\r
public RuntimeMode getRuntimeMode() {\r
if (runtimeMode == null) {\r
- // retrieves the runtime mode from system \r
+ // retrieves the runtime mode from system\r
String modeAsString = System.getProperty("pf4j.mode", RuntimeMode.DEPLOYMENT.toString());\r
runtimeMode = RuntimeMode.byName(modeAsString);\r
\r
log.info("PF4J runtime mode is '{}'", runtimeMode);\r
\r
}\r
- \r
+\r
return runtimeMode;\r
}\r
- \r
+\r
/**\r
* Retrieves the {@link PluginWrapper} that loaded the given class 'clazz'.\r
*/\r
return plugin;\r
}\r
}\r
- \r
+\r
return null;\r
}\r
\r
/**\r
- * Add the possibility to override the PluginDescriptorFinder. \r
- * By default if getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a \r
- * PropertiesPluginDescriptorFinder is returned else this method returns \r
+ * Add the possibility to override the PluginDescriptorFinder.\r
+ * By default if getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a\r
+ * PropertiesPluginDescriptorFinder is returned else this method returns\r
* DefaultPluginDescriptorFinder.\r
*/\r
protected PluginDescriptorFinder createPluginDescriptorFinder() {\r
if (RuntimeMode.DEVELOPMENT.equals(getRuntimeMode())) {\r
return new PropertiesPluginDescriptorFinder();\r
}\r
- \r
+\r
return new DefaultPluginDescriptorFinder(pluginClasspath);\r
}\r
\r
/**\r
- * Add the possibility to override the ExtensionFinder. \r
+ * Add the possibility to override the ExtensionFinder.\r
*/\r
protected ExtensionFinder createExtensionFinder() {\r
return new DefaultExtensionFinder(compoundClassLoader);\r
}\r
\r
/**\r
- * Add the possibility to override the PluginClassPath. \r
- * By default if getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a \r
- * DevelopmentPluginClasspath is returned else this method returns \r
+ * Add the possibility to override the PluginClassPath.\r
+ * By default if getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a\r
+ * DevelopmentPluginClasspath is returned else this method returns\r
* PluginClasspath.\r
*/\r
protected PluginClasspath createPluginClasspath() {\r
if (RuntimeMode.DEVELOPMENT.equals(getRuntimeMode())) {\r
return new DevelopmentPluginClasspath();\r
}\r
- \r
+\r
return new PluginClasspath();\r
}\r
- \r
+\r
protected boolean isPluginDisabled(String pluginId) {\r
if (enabledPlugins.isEmpty()) {\r
return disabledPlugins.contains(pluginId);\r
}\r
- \r
+\r
return !enabledPlugins.contains(pluginId);\r
}\r
- \r
+\r
protected FileFilter createHiddenPluginFilter() {\r
return new HiddenFilter();\r
}\r
- \r
+\r
/**\r
* Add the possibility to override the plugins directory.\r
* If a "pf4j.pluginsDir" system property is defined than this method returns\r
* that directory.\r
- * If getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a \r
- * DEVELOPMENT_PLUGINS_DIRECTORY ("../plugins") is returned else this method returns \r
+ * If getRuntimeMode() returns RuntimeMode.DEVELOPMENT than a\r
+ * DEVELOPMENT_PLUGINS_DIRECTORY ("../plugins") is returned else this method returns\r
* DEFAULT_PLUGINS_DIRECTORY ("plugins").\r
* @return\r
*/\r
pluginsDir = DEFAULT_PLUGINS_DIRECTORY;\r
}\r
}\r
- \r
+\r
return new File(pluginsDir);\r
}\r
- \r
+\r
private void initialize() {\r
plugins = new HashMap<String, PluginWrapper>();\r
pluginClassLoaders = new HashMap<String, PluginClassLoader>();\r
startedPlugins = new ArrayList<PluginWrapper>();\r
disabledPlugins = new ArrayList<String>();\r
compoundClassLoader = new CompoundClassLoader();\r
- \r
+\r
pluginClasspath = createPluginClasspath();\r
pluginDescriptorFinder = createPluginDescriptorFinder();\r
extensionFinder = createExtensionFinder();\r
// create a list with plugin identifiers that should be only accepted by this manager (whitelist from plugins/enabled.txt file)\r
enabledPlugins = FileUtils.readLines(new File(pluginsDirectory, "enabled.txt"), true);\r
log.info("Enabled plugins: {}", enabledPlugins);\r
- \r
+\r
// create a list with plugin identifiers that should not be accepted by this manager (blacklist from plugins/disabled.txt file)\r
disabledPlugins = FileUtils.readLines(new File(pluginsDirectory, "disabled.txt"), true);\r
log.info("Disabled plugins: {}", disabledPlugins);\r
PluginLoader pluginLoader = new PluginLoader(this, pluginDescriptor, pluginDirectory, pluginClasspath);\r
pluginLoader.load();\r
log.debug("Loaded plugin '{}'", pluginPath);\r
- \r
+\r
// create the plugin wrapper\r
log.debug("Creating wrapper for plugin '{}'", pluginPath);\r
PluginWrapper pluginWrapper = new PluginWrapper(pluginDescriptor, pluginPath, pluginLoader.getPluginClassLoader());\r
log.info("Plugin '{}' resolved", pluginWrapper.getDescriptor().getPluginId());\r
}\r
}\r
- \r
+\r
}\r