more sophisticated plugin loader

This commit is contained in:
Anton Keks 2013-01-31 22:37:12 +02:00
parent 5a19920dde
commit 776e4e2390
2 changed files with 74 additions and 14 deletions

1
TODO
View File

@ -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)

View File

@ -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:
* <ul>
* <li>
* Classes listed in <code>ipscan.plugins</code> system property.
* The classes themselves must reside on the application's classpath - useful for development.
* </li>
* <li>
* Jar files residing in the same directory as ipscan's binary file (jar or exe).
* These jar files must have their classes listed in <code>META-INF/MANIFEST.MF</code> as <code>IPScan-Plugins</code>.
* </li>
* </ul>
* 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);
}
}
}
}