2004-05-02 05:02:10 +00:00
|
|
|
package net.i2p.router.startup;
|
|
|
|
|
|
|
|
import java.lang.reflect.Method;
|
2010-03-02 22:51:53 +00:00
|
|
|
import java.util.Arrays;
|
2004-05-02 05:02:10 +00:00
|
|
|
import java.util.ArrayList;
|
2004-05-17 03:38:53 +00:00
|
|
|
import java.util.List;
|
2010-04-16 03:58:48 +00:00
|
|
|
import java.util.concurrent.CountDownLatch;
|
2004-05-17 03:38:53 +00:00
|
|
|
|
|
|
|
import net.i2p.router.JobImpl;
|
|
|
|
import net.i2p.router.RouterContext;
|
|
|
|
import net.i2p.util.I2PThread;
|
|
|
|
import net.i2p.util.Log;
|
2004-05-02 05:02:10 +00:00
|
|
|
|
|
|
|
/**
|
2010-03-15 16:19:19 +00:00
|
|
|
* Run any client applications specified in clients.config. If any clientApp
|
2004-05-02 05:02:10 +00:00
|
|
|
* contains the config property ".onBoot=true" it'll be launched immediately, otherwise
|
|
|
|
* it'll get queued up for starting 2 minutes later.
|
|
|
|
*
|
|
|
|
*/
|
2008-06-20 20:20:50 +00:00
|
|
|
public class LoadClientAppsJob extends JobImpl {
|
2004-05-02 05:02:10 +00:00
|
|
|
private Log _log;
|
2004-09-06 05:20:40 +00:00
|
|
|
private static boolean _loaded = false;
|
2004-08-19 17:42:47 +00:00
|
|
|
|
2004-05-02 05:02:10 +00:00
|
|
|
public LoadClientAppsJob(RouterContext ctx) {
|
|
|
|
super(ctx);
|
|
|
|
_log = ctx.logManager().getLog(LoadClientAppsJob.class);
|
|
|
|
}
|
|
|
|
public void runJob() {
|
2004-09-06 05:20:40 +00:00
|
|
|
synchronized (LoadClientAppsJob.class) {
|
|
|
|
if (_loaded) return;
|
|
|
|
_loaded = true;
|
|
|
|
}
|
2008-06-16 12:19:55 +00:00
|
|
|
List apps = ClientAppConfig.getClientApps(getContext());
|
2009-07-04 16:35:36 +00:00
|
|
|
if (apps.size() <= 0) {
|
|
|
|
_log.error("Warning - No client apps or router console configured - we are just a router");
|
|
|
|
System.err.println("Warning - No client apps or router console configured - we are just a router");
|
|
|
|
return;
|
|
|
|
}
|
2008-06-16 12:19:55 +00:00
|
|
|
for(int i = 0; i < apps.size(); i++) {
|
|
|
|
ClientAppConfig app = (ClientAppConfig) apps.get(i);
|
|
|
|
if (app.disabled)
|
2008-06-01 20:16:17 +00:00
|
|
|
continue;
|
2008-06-16 12:19:55 +00:00
|
|
|
String argVal[] = parseArgs(app.args);
|
2010-03-15 16:19:19 +00:00
|
|
|
if (app.delay <= 0) {
|
2004-05-02 05:02:10 +00:00
|
|
|
// run this guy now
|
2008-06-20 20:20:50 +00:00
|
|
|
runClient(app.className, app.clientName, argVal, _log);
|
2004-05-02 05:02:10 +00:00
|
|
|
} else {
|
2004-11-25 21:57:19 +00:00
|
|
|
// wait before firing it up
|
2008-06-16 12:19:55 +00:00
|
|
|
getContext().jobQueue().addJob(new DelayedRunClient(getContext(), app.className, app.clientName, argVal, app.delay));
|
2004-05-02 05:02:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-02-07 13:32:49 +00:00
|
|
|
|
|
|
|
public static class DelayedRunClient extends JobImpl {
|
2004-05-02 05:02:10 +00:00
|
|
|
private String _className;
|
|
|
|
private String _clientName;
|
|
|
|
private String _args[];
|
2010-02-07 13:32:49 +00:00
|
|
|
private Log _log;
|
2010-04-16 03:58:48 +00:00
|
|
|
private ThreadGroup _threadGroup;
|
2010-02-07 13:32:49 +00:00
|
|
|
|
2005-01-26 06:29:17 +00:00
|
|
|
public DelayedRunClient(RouterContext enclosingContext, String className, String clientName, String args[], long delay) {
|
2010-04-16 03:58:48 +00:00
|
|
|
this(enclosingContext, className, clientName, args, delay, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public DelayedRunClient(RouterContext enclosingContext, String className, String clientName, String args[], long delay, ThreadGroup threadGroup) {
|
2005-01-26 06:29:17 +00:00
|
|
|
super(enclosingContext);
|
2004-05-02 05:02:10 +00:00
|
|
|
_className = className;
|
|
|
|
_clientName = clientName;
|
|
|
|
_args = args;
|
2010-02-07 13:32:49 +00:00
|
|
|
_log = enclosingContext.logManager().getLog(LoadClientAppsJob.class);
|
2010-04-16 03:58:48 +00:00
|
|
|
_threadGroup = threadGroup;
|
2010-02-07 13:32:49 +00:00
|
|
|
getTiming().setStartAfter(getContext().clock().now() + delay);
|
2004-05-02 05:02:10 +00:00
|
|
|
}
|
|
|
|
public String getName() { return "Delayed client job"; }
|
|
|
|
public void runJob() {
|
2010-04-16 03:58:48 +00:00
|
|
|
runClient(_className, _clientName, _args, _log, _threadGroup);
|
2004-05-02 05:02:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-20 20:20:50 +00:00
|
|
|
public static String[] parseArgs(String args) {
|
2004-05-02 05:02:10 +00:00
|
|
|
List argList = new ArrayList(4);
|
|
|
|
if (args != null) {
|
|
|
|
char data[] = args.toCharArray();
|
2009-07-01 16:00:43 +00:00
|
|
|
StringBuilder buf = new StringBuilder(32);
|
2004-05-02 05:02:10 +00:00
|
|
|
boolean isQuoted = false;
|
|
|
|
for (int i = 0; i < data.length; i++) {
|
|
|
|
switch (data[i]) {
|
|
|
|
case '\'':
|
|
|
|
case '\"':
|
|
|
|
if (isQuoted) {
|
|
|
|
String str = buf.toString().trim();
|
|
|
|
if (str.length() > 0)
|
|
|
|
argList.add(str);
|
2009-07-01 16:00:43 +00:00
|
|
|
buf = new StringBuilder(32);
|
2004-05-02 05:02:10 +00:00
|
|
|
}
|
2010-03-02 22:51:53 +00:00
|
|
|
isQuoted = !isQuoted;
|
2004-05-02 05:02:10 +00:00
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
// whitespace - if we're in a quoted section, keep this as part of the quote,
|
|
|
|
// otherwise use it as a delim
|
|
|
|
if (isQuoted) {
|
|
|
|
buf.append(data[i]);
|
|
|
|
} else {
|
|
|
|
String str = buf.toString().trim();
|
|
|
|
if (str.length() > 0)
|
|
|
|
argList.add(str);
|
2009-07-01 16:00:43 +00:00
|
|
|
buf = new StringBuilder(32);
|
2004-05-02 05:02:10 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
buf.append(data[i]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (buf.length() > 0) {
|
|
|
|
String str = buf.toString().trim();
|
|
|
|
if (str.length() > 0)
|
|
|
|
argList.add(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
String rv[] = new String[argList.size()];
|
|
|
|
for (int i = 0; i < argList.size(); i++)
|
|
|
|
rv[i] = (String)argList.get(i);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2010-03-15 16:19:19 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2008-06-20 20:20:50 +00:00
|
|
|
public static void runClient(String className, String clientName, String args[], Log log) {
|
2010-04-16 03:58:48 +00:00
|
|
|
runClient(className, clientName, args, log, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Run client in a new thread.
|
|
|
|
*/
|
|
|
|
public static void runClient(String className, String clientName, String args[], Log log, ThreadGroup threadGroup) {
|
2010-03-02 22:51:53 +00:00
|
|
|
if (log.shouldLog(Log.INFO))
|
|
|
|
log.info("Loading up the client application " + clientName + ": " + className + " " + Arrays.toString(args));
|
2010-04-16 03:58:48 +00:00
|
|
|
I2PThread t;
|
|
|
|
if (threadGroup != null)
|
|
|
|
t = new I2PThread(threadGroup, new RunApp(className, clientName, args, log));
|
|
|
|
else
|
|
|
|
t = new I2PThread(new RunApp(className, clientName, args, log));
|
2004-06-20 00:40:16 +00:00
|
|
|
if (clientName == null)
|
|
|
|
clientName = className + " client";
|
2004-05-02 05:02:10 +00:00
|
|
|
t.setName(clientName);
|
|
|
|
t.setDaemon(true);
|
|
|
|
t.start();
|
|
|
|
}
|
|
|
|
|
2008-06-20 20:20:50 +00:00
|
|
|
private final static class RunApp implements Runnable {
|
2004-05-02 05:02:10 +00:00
|
|
|
private String _className;
|
|
|
|
private String _appName;
|
|
|
|
private String _args[];
|
2008-06-20 20:20:50 +00:00
|
|
|
private Log _log;
|
|
|
|
public RunApp(String className, String appName, String args[], Log log) {
|
2004-05-02 05:02:10 +00:00
|
|
|
_className = className;
|
|
|
|
_appName = appName;
|
|
|
|
if (args == null)
|
|
|
|
_args = new String[0];
|
|
|
|
else
|
|
|
|
_args = args;
|
2008-06-20 20:20:50 +00:00
|
|
|
_log = log;
|
2004-05-02 05:02:10 +00:00
|
|
|
}
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
Class cls = Class.forName(_className);
|
|
|
|
Method method = cls.getMethod("main", new Class[] { String[].class });
|
|
|
|
method.invoke(cls, new Object[] { _args });
|
|
|
|
} catch (Throwable t) {
|
|
|
|
_log.log(Log.CRIT, "Error starting up the client class " + _className, t);
|
|
|
|
}
|
2010-03-02 22:51:53 +00:00
|
|
|
if (_log.shouldLog(Log.INFO))
|
|
|
|
_log.info("Done running client application " + _appName);
|
2004-05-02 05:02:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getName() { return "Load up any client applications"; }
|
|
|
|
|
|
|
|
public static void main(String args[]) {
|
|
|
|
test(null);
|
|
|
|
test("hi how are you?");
|
|
|
|
test("hi how are you? ");
|
|
|
|
test(" hi how are you? ");
|
|
|
|
test(" hi how are \"y\"ou? ");
|
|
|
|
test("-nogui -e \"config localhost 17654\" -e \"httpclient 4544\"");
|
|
|
|
test("-nogui -e 'config localhost 17654' -e 'httpclient 4544'");
|
|
|
|
}
|
|
|
|
private static void test(String args) {
|
|
|
|
String parsed[] = parseArgs(args);
|
|
|
|
System.out.print("Parsed [" + args + "] into " + parsed.length + " elements: ");
|
|
|
|
for (int i = 0; i < parsed.length; i++)
|
|
|
|
System.out.print("[" + parsed[i] + "] ");
|
|
|
|
System.out.println();
|
|
|
|
}
|
|
|
|
}
|