forked from I2P_Developers/i2p.i2p
* Clients:
- Negative delay means run immediately and inline - Add methods to test class and run inline, to propagate errors to the console - Add javadoc for clients.config format - Use new methods for plugins
This commit is contained in:
@ -180,7 +180,7 @@ public class PluginStarter implements Runnable {
|
|||||||
* @return true on success
|
* @return true on success
|
||||||
* @throws just about anything, caller would be wise to catch Throwable
|
* @throws just about anything, caller would be wise to catch Throwable
|
||||||
*/
|
*/
|
||||||
static boolean stopPlugin(RouterContext ctx, String appName) throws IOException {
|
static boolean stopPlugin(RouterContext ctx, String appName) throws Exception {
|
||||||
Log log = ctx.logManager().getLog(PluginStarter.class);
|
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())) {
|
||||||
@ -228,7 +228,7 @@ public class PluginStarter implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return true on success - caller should call stopPlugin() first */
|
/** @return true on success - caller should call stopPlugin() first */
|
||||||
static boolean deletePlugin(RouterContext ctx, String appName) throws IOException {
|
static boolean deletePlugin(RouterContext ctx, String appName) throws Exception {
|
||||||
Log log = ctx.logManager().getLog(PluginStarter.class);
|
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())) {
|
||||||
@ -348,8 +348,12 @@ public class PluginStarter implements Runnable {
|
|||||||
} catch (IOException ioe) {}
|
} catch (IOException ioe) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param action "start" or "stop" or "uninstall" */
|
/**
|
||||||
private static void runClientApps(RouterContext ctx, File pluginDir, List<ClientAppConfig> apps, String action) {
|
* @param action "start" or "stop" or "uninstall"
|
||||||
|
* @throws just about anything if an app has a delay less than zero, caller would be wise to catch Throwable
|
||||||
|
* If no apps have a delay less than zero, it shouldn't throw anything
|
||||||
|
*/
|
||||||
|
private static void runClientApps(RouterContext ctx, File pluginDir, List<ClientAppConfig> apps, String action) throws Exception {
|
||||||
Log log = ctx.logManager().getLog(PluginStarter.class);
|
Log log = ctx.logManager().getLog(PluginStarter.class);
|
||||||
for(ClientAppConfig app : apps) {
|
for(ClientAppConfig app : apps) {
|
||||||
if (action.equals("start") && app.disabled)
|
if (action.equals("start") && app.disabled)
|
||||||
@ -388,10 +392,18 @@ public class PluginStarter implements Runnable {
|
|||||||
}
|
}
|
||||||
addToClasspath(cp, app.clientName, log);
|
addToClasspath(cp, app.clientName, log);
|
||||||
}
|
}
|
||||||
if (app.delay == 0 || !action.equals("start")) {
|
|
||||||
|
if (app.delay < 0 && action.equals("start")) {
|
||||||
|
// this will throw exceptions
|
||||||
|
LoadClientAppsJob.runClientInline(app.className, app.clientName, argVal, log);
|
||||||
|
} else if (app.delay == 0 || !action.equals("start")) {
|
||||||
|
// quick check, will throw ClassNotFoundException on error
|
||||||
|
LoadClientAppsJob.testClient(app.className);
|
||||||
// run this guy now
|
// run this guy now
|
||||||
LoadClientAppsJob.runClient(app.className, app.clientName, argVal, log);
|
LoadClientAppsJob.runClient(app.className, app.clientName, argVal, log);
|
||||||
} else {
|
} else {
|
||||||
|
// quick check, will throw ClassNotFoundException on error
|
||||||
|
LoadClientAppsJob.testClient(app.className);
|
||||||
// wait before firing it up
|
// wait before firing it up
|
||||||
ctx.jobQueue().addJob(new LoadClientAppsJob.DelayedRunClient(ctx, app.className, app.clientName, argVal, app.delay));
|
ctx.jobQueue().addJob(new LoadClientAppsJob.DelayedRunClient(ctx, app.className, app.clientName, argVal, app.delay));
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,49 @@ import net.i2p.router.RouterContext;
|
|||||||
* so they can be used both by LoadClientAppsJob and by the configuration
|
* so they can be used both by LoadClientAppsJob and by the configuration
|
||||||
* page in the router console.
|
* page in the router console.
|
||||||
*
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* clients.config format:
|
||||||
|
*
|
||||||
|
* Lines are of the form clientApp.x.prop=val, where x is the app number.
|
||||||
|
* App numbers MUST start with 0 and be consecutive.
|
||||||
|
*
|
||||||
|
* Properties are as follows:
|
||||||
|
* main: Full class name. Required. The main() method in this
|
||||||
|
* class will be run.
|
||||||
|
* name: Name to be displayed on console.
|
||||||
|
* args: Arguments to the main class, separated by spaces or tabs.
|
||||||
|
* Arguments containing spaces or tabs may be quoted with ' or "
|
||||||
|
* delay: Seconds before starting, default 120
|
||||||
|
* onBoot: {true|false}, default false, forces a delay of 0,
|
||||||
|
* overrides delay setting
|
||||||
|
* startOnLoad: {true|false} Is the client to be run at all?
|
||||||
|
* Default true
|
||||||
|
*
|
||||||
|
* The following additional properties are used only by plugins:
|
||||||
|
* stopargs: Arguments to stop the client.
|
||||||
|
* uninstallargs: Arguments to stop the client.
|
||||||
|
* classpath: Additional classpath elements for the client,
|
||||||
|
* separated by commas.
|
||||||
|
*
|
||||||
|
* The following substitutions are made in the args, stopargs,
|
||||||
|
* uninstallargs, and classpath lines, for plugins only:
|
||||||
|
* $I2P: The base I2P install directory
|
||||||
|
* $CONFIG: The user's configuration directory (e.g. ~/.i2p)
|
||||||
|
* $PLUGIN: This plugin's directory (e.g. ~/.i2p/plugins/foo)
|
||||||
|
*
|
||||||
|
* All properties except "main" are optional.
|
||||||
|
* Lines starting with "#" are comments.
|
||||||
|
*
|
||||||
|
* If the delay is less than zero, the client is run immediately,
|
||||||
|
* in the same thread, so that exceptions may be propagated to the console.
|
||||||
|
* In this case, the client should either throw an exception, return quickly,
|
||||||
|
* or spawn its own thread.
|
||||||
|
* If the delay is greater than or equal to zero, it will be run
|
||||||
|
* in a new thread, and exceptions will be logged but not propagated
|
||||||
|
* to the console.
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class ClientAppConfig {
|
public class ClientAppConfig {
|
||||||
/** wait 2 minutes before starting up client apps */
|
/** wait 2 minutes before starting up client apps */
|
||||||
|
@ -11,7 +11,7 @@ import net.i2p.util.I2PThread;
|
|||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run any client applications specified in the router.config. If any clientApp
|
* Run any client applications specified in clients.config. If any clientApp
|
||||||
* contains the config property ".onBoot=true" it'll be launched immediately, otherwise
|
* contains the config property ".onBoot=true" it'll be launched immediately, otherwise
|
||||||
* it'll get queued up for starting 2 minutes later.
|
* it'll get queued up for starting 2 minutes later.
|
||||||
*
|
*
|
||||||
@ -40,7 +40,7 @@ public class LoadClientAppsJob extends JobImpl {
|
|||||||
if (app.disabled)
|
if (app.disabled)
|
||||||
continue;
|
continue;
|
||||||
String argVal[] = parseArgs(app.args);
|
String argVal[] = parseArgs(app.args);
|
||||||
if (app.delay == 0) {
|
if (app.delay <= 0) {
|
||||||
// run this guy now
|
// run this guy now
|
||||||
runClient(app.className, app.clientName, argVal, _log);
|
runClient(app.className, app.clientName, argVal, _log);
|
||||||
} else {
|
} else {
|
||||||
@ -118,6 +118,36 @@ public class LoadClientAppsJob extends JobImpl {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use to test if the class is present,
|
||||||
|
* to propagate an error back to the user,
|
||||||
|
* since runClient() runs in a separate thread.
|
||||||
|
*
|
||||||
|
* @since 0.7.13
|
||||||
|
*/
|
||||||
|
public static void testClient(String className) throws ClassNotFoundException {
|
||||||
|
Class.forName(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run client in this thread.
|
||||||
|
*
|
||||||
|
* @throws just about anything, caller would be wise to catch Throwable
|
||||||
|
* @since 0.7.13
|
||||||
|
*/
|
||||||
|
public static void runClientInline(String className, String clientName, String args[], Log log) throws Exception {
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("Loading up the client application " + clientName + ": " + className + " " + Arrays.toString(args));
|
||||||
|
if (args == null)
|
||||||
|
args = new String[0];
|
||||||
|
Class cls = Class.forName(className);
|
||||||
|
Method method = cls.getMethod("main", new Class[] { String[].class });
|
||||||
|
method.invoke(cls, new Object[] { args });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run client in a new thread.
|
||||||
|
*/
|
||||||
public static void runClient(String className, String clientName, String args[], Log log) {
|
public static void runClient(String className, String clientName, String args[], Log log) {
|
||||||
if (log.shouldLog(Log.INFO))
|
if (log.shouldLog(Log.INFO))
|
||||||
log.info("Loading up the client application " + clientName + ": " + className + " " + Arrays.toString(args));
|
log.info("Loading up the client application " + clientName + ": " + className + " " + Arrays.toString(args));
|
||||||
|
Reference in New Issue
Block a user