forked from I2P_Developers/i2p.i2p
classpath for plugins
This commit is contained in:
@ -2,6 +2,9 @@ package net.i2p.router.web;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -39,6 +42,7 @@ public class PluginStarter implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void startPlugins(RouterContext ctx) {
|
static void startPlugins(RouterContext ctx) {
|
||||||
|
Log log = ctx.logManager().getLog(PluginStarter.class);
|
||||||
Properties props = pluginProperties();
|
Properties props = pluginProperties();
|
||||||
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
||||||
String name = (String)iter.next();
|
String name = (String)iter.next();
|
||||||
@ -47,9 +51,9 @@ public class PluginStarter implements Runnable {
|
|||||||
String app = name.substring(PluginStarter.PREFIX.length(), name.lastIndexOf(PluginStarter.ENABLED));
|
String app = name.substring(PluginStarter.PREFIX.length(), name.lastIndexOf(PluginStarter.ENABLED));
|
||||||
try {
|
try {
|
||||||
if (!startPlugin(ctx, app))
|
if (!startPlugin(ctx, app))
|
||||||
System.err.println("Failed to start plugin: " + app);
|
log.error("Failed to start plugin: " + app);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("Failed to start plugin: " + app + ' ' + e);
|
log.error("Failed to start plugin: " + app, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,9 +62,10 @@ public class PluginStarter implements Runnable {
|
|||||||
|
|
||||||
/** @return true on success */
|
/** @return true on success */
|
||||||
static boolean startPlugin(RouterContext ctx, String appName) throws Exception {
|
static boolean startPlugin(RouterContext ctx, String appName) throws Exception {
|
||||||
|
Log log = ctx.logManager().getLog(PluginStarter.class);
|
||||||
File pluginDir = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName);
|
File pluginDir = new File(ctx.getAppDir(), PluginUpdateHandler.PLUGIN_DIR + '/' + appName);
|
||||||
if ((!pluginDir.exists()) || (!pluginDir.isDirectory())) {
|
if ((!pluginDir.exists()) || (!pluginDir.isDirectory())) {
|
||||||
System.err.println("Cannot start nonexistent plugin: " + appName);
|
log.error("Cannot start nonexistent plugin: " + appName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +96,7 @@ public class PluginStarter implements Runnable {
|
|||||||
WebAppStarter.startWebApp(ctx, server, warName, path);
|
WebAppStarter.startWebApp(ctx, server, warName, path);
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
System.err.println("Error resolving '" + fileNames[i] + "' in '" + webappDir);
|
log.error("Error resolving '" + fileNames[i] + "' in '" + webappDir, ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,6 +162,15 @@ public class PluginStarter implements Runnable {
|
|||||||
argVal[i] = argVal[i].replace("$PLUGIN", pluginDir.getAbsolutePath());
|
argVal[i] = argVal[i].replace("$PLUGIN", pluginDir.getAbsolutePath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (app.classpath != null) {
|
||||||
|
String cp = new String(app.classpath);
|
||||||
|
if (cp.indexOf("$") >= 0) {
|
||||||
|
cp = cp.replace("$I2P", ctx.getBaseDir().getAbsolutePath());
|
||||||
|
cp = cp.replace("$CONFIG", ctx.getConfigDir().getAbsolutePath());
|
||||||
|
cp = cp.replace("$PLUGIN", pluginDir.getAbsolutePath());
|
||||||
|
}
|
||||||
|
addToClasspath(cp, app.clientName, log);
|
||||||
|
}
|
||||||
if (app.delay == 0) {
|
if (app.delay == 0) {
|
||||||
// run this guy now
|
// run this guy now
|
||||||
LoadClientAppsJob.runClient(app.className, app.clientName, argVal, log);
|
LoadClientAppsJob.runClient(app.className, app.clientName, argVal, log);
|
||||||
@ -166,4 +180,38 @@ public class PluginStarter implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perhaps there's an easy way to use Thread.setContextClassLoader()
|
||||||
|
* but I don't see how to make it magically get used for everything.
|
||||||
|
* So add this to the whole JVM's classpath.
|
||||||
|
*/
|
||||||
|
private static void addToClasspath(String classpath, String clientName, Log log) {
|
||||||
|
StringTokenizer tok = new StringTokenizer(classpath, ",");
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
String elem = tok.nextToken().trim();
|
||||||
|
File f = new File(elem);
|
||||||
|
if (!f.isAbsolute()) {
|
||||||
|
log.error("Plugin client " + clientName + " classpath element is not absolute: " + f);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
log.error("INFO: Adding plugin classpath: " + f);
|
||||||
|
addPath(f.toURI().toURL());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Plugin client " + clientName + " bad classpath element: " + f, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http://jimlife.wordpress.com/2007/12/19/java-adding-new-classpath-at-runtime/
|
||||||
|
*/
|
||||||
|
public static void addPath(URL u) throws Exception {
|
||||||
|
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
||||||
|
Class urlClass = URLClassLoader.class;
|
||||||
|
Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
|
||||||
|
method.setAccessible(true);
|
||||||
|
method.invoke(urlClassLoader, new Object[]{u});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ public class ClientAppConfig {
|
|||||||
public String args;
|
public String args;
|
||||||
public long delay;
|
public long delay;
|
||||||
public boolean disabled;
|
public boolean disabled;
|
||||||
|
/** @since 0.7.12 */
|
||||||
|
public String classpath;
|
||||||
|
|
||||||
public ClientAppConfig(String cl, String client, String a, long d, boolean dis) {
|
public ClientAppConfig(String cl, String client, String a, long d, boolean dis) {
|
||||||
className = cl;
|
className = cl;
|
||||||
clientName = client;
|
clientName = client;
|
||||||
@ -41,6 +44,12 @@ public class ClientAppConfig {
|
|||||||
disabled = dis;
|
disabled = dis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.7.12 */
|
||||||
|
public ClientAppConfig(String cl, String client, String a, long d, boolean dis, String cp) {
|
||||||
|
this(cl, client, a, d, dis);
|
||||||
|
classpath = cp;
|
||||||
|
}
|
||||||
|
|
||||||
public static File configFile(I2PAppContext ctx) {
|
public static File configFile(I2PAppContext ctx) {
|
||||||
String clientConfigFile = ctx.getProperty(PROP_CLIENT_CONFIG_FILENAME, DEFAULT_CLIENT_CONFIG_FILENAME);
|
String clientConfigFile = ctx.getProperty(PROP_CLIENT_CONFIG_FILENAME, DEFAULT_CLIENT_CONFIG_FILENAME);
|
||||||
File cfgFile = new File(clientConfigFile);
|
File cfgFile = new File(clientConfigFile);
|
||||||
@ -104,6 +113,7 @@ public class ClientAppConfig {
|
|||||||
String delayStr = clientApps.getProperty(PREFIX + i + ".delay");
|
String delayStr = clientApps.getProperty(PREFIX + i + ".delay");
|
||||||
String onBoot = clientApps.getProperty(PREFIX + i + ".onBoot");
|
String onBoot = clientApps.getProperty(PREFIX + i + ".onBoot");
|
||||||
String disabled = clientApps.getProperty(PREFIX + i + ".startOnLoad");
|
String disabled = clientApps.getProperty(PREFIX + i + ".startOnLoad");
|
||||||
|
String classpath = clientApps.getProperty(PREFIX + i + ".classpath");
|
||||||
i++;
|
i++;
|
||||||
boolean dis = disabled != null && "false".equals(disabled);
|
boolean dis = disabled != null && "false".equals(disabled);
|
||||||
|
|
||||||
@ -115,11 +125,12 @@ public class ClientAppConfig {
|
|||||||
if (delayStr != null && !onStartup)
|
if (delayStr != null && !onStartup)
|
||||||
try { delay = 1000*Integer.parseInt(delayStr); } catch (NumberFormatException nfe) {}
|
try { delay = 1000*Integer.parseInt(delayStr); } catch (NumberFormatException nfe) {}
|
||||||
|
|
||||||
rv.add(new ClientAppConfig(className, clientName, args, delay, dis));
|
rv.add(new ClientAppConfig(className, clientName, args, delay, dis, classpath));
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** classpath not supported */
|
||||||
public static void writeClientAppConfig(RouterContext ctx, List apps) {
|
public static void writeClientAppConfig(RouterContext ctx, List apps) {
|
||||||
File cfgFile = configFile(ctx);
|
File cfgFile = configFile(ctx);
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
|
Reference in New Issue
Block a user