From 776e4e2390bffacec0e20236bfa986f866a14424 Mon Sep 17 00:00:00 2001 From: Anton Keks Date: Thu, 31 Jan 2013 22:37:12 +0200 Subject: [PATCH] more sophisticated plugin loader --- TODO | 1 - .../ipscan/core/plugins/PluginLoader.java | 87 ++++++++++++++++--- 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/TODO b/TODO index b7ea415c..396ff9d4 100644 --- a/TODO +++ b/TODO @@ -11,7 +11,6 @@ Before 3.0: * add new fetchers by configuration of PortTextFetcher * startup as root option * compile librocksaw for mac and linux64 -* plugin loader * public XSL for XMLExporter * Easier adding/removing of columns to the result table (without resetting the results) diff --git a/src/net/azib/ipscan/core/plugins/PluginLoader.java b/src/net/azib/ipscan/core/plugins/PluginLoader.java index cf5cb126..b2a2c6cd 100644 --- a/src/net/azib/ipscan/core/plugins/PluginLoader.java +++ b/src/net/azib/ipscan/core/plugins/PluginLoader.java @@ -3,24 +3,85 @@ package net.azib.ipscan.core.plugins; import net.azib.ipscan.config.LoggerFactory; import org.picocontainer.MutablePicoContainer; +import java.io.File; +import java.io.FilenameFilter; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.jar.Manifest; import java.util.logging.Logger; +/** + * Loads plugins using two ways: + * + * In either way, all plugins must implement {@link Pluggable} and one or more of the concrete interfaces. + */ public class PluginLoader { static final Logger LOG = LoggerFactory.getLogger(); public void addTo(MutablePicoContainer container) { - String plugins = System.getProperty("ipscan.plugins"); - if (plugins != null) { - String[] classes = plugins.split("\\s*,\\s*"); - for (String className : classes) { - try { - Class clazz = Class.forName(className); - container.registerComponentImplementation(clazz); - } - catch (ClassNotFoundException e) { - LOG.warning("Unable to load plugin: " + className); - } - } - } + loadPluginsSpecifiedInSystemProperties(container); + loadPluginJars(container); } + + private void loadPluginsSpecifiedInSystemProperties(MutablePicoContainer container) { + String plugins = System.getProperty("ipscan.plugins"); + if (plugins != null) { + loadPluginClasses(container, getClass().getClassLoader(), plugins); + } + } + + private void loadPluginClasses(MutablePicoContainer container, ClassLoader classLoader, String csvNames) { + String[] classes = csvNames.split("\\s*,\\s*"); + for (String className : classes) { + try { + Class clazz = Class.forName(className, true, classLoader); + if (Pluggable.class.isAssignableFrom(clazz)) + container.registerComponentImplementation(clazz); + else + LOG.warning("Plugin class " + clazz.getName() + " is not assignable to " + Pluggable.class.getName()); + } + catch (ClassNotFoundException e) { + LOG.warning("Unable to load plugin: " + className); + } + } + } + + private void loadPluginJars(MutablePicoContainer container) { + String ownPath = PluginLoader.class.getResource("PluginLoader.class").getFile(); + if (ownPath.startsWith("file:")) ownPath = ownPath.substring("file:".length()); + if (ownPath.indexOf('!') >= 0) ownPath = ownPath.substring(0, ownPath.indexOf('!')); + final File ownFile = new File(ownPath); + + File[] jars = ownFile.getParentFile().listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".jar") && !name.equals(ownFile.getName()); + } + }); + + for (File jar : jars) { + try { + URLClassLoader loader = new URLClassLoader(new URL[] {jar.toURI().toURL()}, PluginLoader.class.getClassLoader()); + Manifest manifest = new Manifest(loader.getResourceAsStream("META-INF/MANIFEST.MF")); + + String className = manifest.getMainAttributes().getValue("IPScan-Plugin"); + if (className != null) loadPluginClasses(container, loader, className); + + String classNames = manifest.getMainAttributes().getValue("IPScan-Plugins"); + if (classNames != null) loadPluginClasses(container, loader, classNames); + } + catch (Exception e) { + LOG.warning("Failed to load plugin jar " + jar + ": " + e); + } + } + } }