* Plugins:

- Fix classpath setting for webapps
      - Implement uninstall args in clients.config
This commit is contained in:
zzz
2010-02-11 19:18:26 +00:00
parent cada9fae44
commit 62308f26bc
5 changed files with 57 additions and 24 deletions

View File

@ -1,6 +1,7 @@
package net.i2p.router.web; package net.i2p.router.web;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -69,9 +70,11 @@ public class ConfigClientsHandler extends FormHandler {
} else { } else {
try { try {
PluginStarter.stopPlugin(_context, app); PluginStarter.stopPlugin(_context, app);
} catch (Exception e) {} PluginStarter.deletePlugin(_context, app);
PluginStarter.deletePlugin(_context, app); addFormNotice(_("Deleted plugin {0}", app));
addFormNotice(_("Deleted plugin {0}", app)); } catch (IOException e) {
addFormError(_("Error deleting plugin {0}", app) + ": " + e);
}
} }
return; return;
} }
@ -81,7 +84,7 @@ public class ConfigClientsHandler extends FormHandler {
String app = _action.substring(5); String app = _action.substring(5);
try { try {
PluginStarter.stopPlugin(_context, app); PluginStarter.stopPlugin(_context, app);
} catch (Exception e) {} } catch (IOException e) {}
addFormNotice(_("Stopped plugin {0}", app)); addFormNotice(_("Stopped plugin {0}", app));
return; return;
} }

View File

@ -77,6 +77,7 @@ public class PluginStarter implements Runnable {
log.error("Cannot start nonexistent plugin: " + appName); log.error("Cannot start nonexistent plugin: " + appName);
return false; return false;
} }
//log.error("Starting plugin: " + appName);
// load and start things in clients.config // load and start things in clients.config
File clientConfig = new File(pluginDir, "clients.config"); File clientConfig = new File(pluginDir, "clients.config");
@ -84,7 +85,7 @@ public class PluginStarter implements Runnable {
Properties props = new Properties(); Properties props = new Properties();
DataHelper.loadProps(props, clientConfig); DataHelper.loadProps(props, clientConfig);
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(clientConfig); List<ClientAppConfig> clients = ClientAppConfig.getClientApps(clientConfig);
runClientApps(ctx, pluginDir, clients, true); runClientApps(ctx, pluginDir, clients, "start");
} }
// start console webapps in console/webapps // start console webapps in console/webapps
@ -98,6 +99,7 @@ public class PluginStarter implements Runnable {
for (int i = 0; i < fileNames.length; i++) { for (int i = 0; i < fileNames.length; i++) {
try { try {
String warName = fileNames[i].substring(0, fileNames[i].lastIndexOf(".war")); String warName = fileNames[i].substring(0, fileNames[i].lastIndexOf(".war"));
//log.error("Found webapp: " + warName);
// check for duplicates in $I2P // check for duplicates in $I2P
// easy way for now... // easy way for now...
if (warName.equals("i2psnark") || warName.equals("susidns") || warName.equals("i2ptunnel") || if (warName.equals("i2psnark") || warName.equals("susidns") || warName.equals("i2ptunnel") ||
@ -107,6 +109,7 @@ public class PluginStarter implements Runnable {
} }
String enabled = props.getProperty(PREFIX + warName + ENABLED); String enabled = props.getProperty(PREFIX + warName + ENABLED);
if (! "false".equals(enabled)) { if (! "false".equals(enabled)) {
//log.error("Starting webapp: " + warName);
String path = new File(webappDir, fileNames[i]).getCanonicalPath(); String path = new File(webappDir, fileNames[i]).getCanonicalPath();
WebAppStarter.startWebApp(ctx, server, warName, path); WebAppStarter.startWebApp(ctx, server, warName, path);
} }
@ -157,7 +160,7 @@ public class PluginStarter implements Runnable {
} }
/** @return true on success */ /** @return true on success */
static boolean stopPlugin(RouterContext ctx, String appName) throws Exception { static boolean stopPlugin(RouterContext ctx, String appName) throws IOException {
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())) {
@ -171,7 +174,7 @@ public class PluginStarter implements Runnable {
Properties props = new Properties(); Properties props = new Properties();
DataHelper.loadProps(props, clientConfig); DataHelper.loadProps(props, clientConfig);
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(clientConfig); List<ClientAppConfig> clients = ClientAppConfig.getClientApps(clientConfig);
runClientApps(ctx, pluginDir, clients, false); runClientApps(ctx, pluginDir, clients, "stop");
} }
// stop console webapps in console/webapps // stop console webapps in console/webapps
@ -201,17 +204,26 @@ public class PluginStarter implements Runnable {
if (name != null && name.length() > 0) if (name != null && name.length() > 0)
NavHelper.unregisterApp(name); NavHelper.unregisterApp(name);
log.error("Stopping plugin: " + appName);
return true; return true;
} }
/** @return true on success - call stopPlugin() first */ /** @return true on success - call stopPlugin() first */
static boolean deletePlugin(RouterContext ctx, String appName) { static boolean deletePlugin(RouterContext ctx, String appName) throws IOException {
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())) {
log.error("Cannot stop nonexistent plugin: " + appName); log.error("Cannot stop nonexistent plugin: " + appName);
return false; return false;
} }
// uninstall things in clients.config
File clientConfig = new File(pluginDir, "clients.config");
if (clientConfig.exists()) {
Properties props = new Properties();
DataHelper.loadProps(props, clientConfig);
List<ClientAppConfig> clients = ClientAppConfig.getClientApps(clientConfig);
runClientApps(ctx, pluginDir, clients, "uninstall");
}
FileUtil.rmdir(pluginDir, false); FileUtil.rmdir(pluginDir, false);
Properties props = pluginProperties(); Properties props = pluginProperties();
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) { for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
@ -313,20 +325,28 @@ public class PluginStarter implements Runnable {
return null; return null;
} }
/** @param start true=start, false=stop */ /** @param action "start" or "stop" or "uninstall" */
private static void runClientApps(RouterContext ctx, File pluginDir, List<ClientAppConfig> apps, boolean start) { private static void runClientApps(RouterContext ctx, File pluginDir, List<ClientAppConfig> apps, String action) {
Log log = ctx.logManager().getLog(PluginStarter.class); Log log = ctx.logManager().getLog(PluginStarter.class);
for(ClientAppConfig app : apps) { for(ClientAppConfig app : apps) {
if (start && app.disabled) if (action.equals("start") && app.disabled)
continue; continue;
String argVal[]; String argVal[];
if (start) { if (action.equals("start")) {
// start
argVal = LoadClientAppsJob.parseArgs(app.args); argVal = LoadClientAppsJob.parseArgs(app.args);
} else { } else {
// stopargs must be present String args;
if (app.stopargs == null || app.stopargs.length() <= 0) if (action.equals("stop"))
args = app.stopargs;
else if (action.equals("uninstall"))
args = app.uninstallargs;
else
throw new IllegalArgumentException("bad action");
// args must be present
if (args == null || args.length() <= 0)
continue; continue;
argVal = LoadClientAppsJob.parseArgs(app.stopargs); argVal = LoadClientAppsJob.parseArgs(args);
} }
// do this after parsing so we don't need to worry about quoting // do this after parsing so we don't need to worry about quoting
for (int i = 0; i < argVal.length; i++) { for (int i = 0; i < argVal.length; i++) {
@ -345,7 +365,7 @@ public class PluginStarter implements Runnable {
} }
addToClasspath(cp, app.clientName, log); addToClasspath(cp, app.clientName, log);
} }
if (app.delay == 0 || !start) { if (app.delay == 0 || !action.equals("start")) {
// 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 {

View File

@ -308,7 +308,7 @@ public class PluginUpdateHandler extends UpdateHandler {
if (!PluginStarter.stopPlugin(_context, appName)) { if (!PluginStarter.stopPlugin(_context, appName)) {
// failed, ignore // failed, ignore
} }
} catch (Exception e) {} // ignore } catch (IOException e) {} // ignore
} else { } else {
if (Boolean.valueOf(props.getProperty("update-only")).booleanValue()) { if (Boolean.valueOf(props.getProperty("update-only")).booleanValue()) {

View File

@ -53,8 +53,10 @@ public class WebAppConfiguration implements WebApplicationContext.Configuration
I2PAppContext i2pContext = I2PAppContext.getGlobalContext(); I2PAppContext i2pContext = I2PAppContext.getGlobalContext();
File libDir = new File(i2pContext.getBaseDir(), "lib"); File libDir = new File(i2pContext.getBaseDir(), "lib");
File pluginLibDir = new File(i2pContext.getAppDir(), // FIXME this only works if war is the same name as the plugin
PluginUpdateHandler.PLUGIN_DIR + ctxPath + '/' + "lib"); File pluginDir = new File(i2pContext.getAppDir(),
PluginUpdateHandler.PLUGIN_DIR + ctxPath);
File dir = libDir; File dir = libDir;
String cp; String cp;
if (ctxPath.equals("/susidns")) { if (ctxPath.equals("/susidns")) {
@ -63,10 +65,11 @@ public class WebAppConfiguration implements WebApplicationContext.Configuration
} else if (ctxPath.equals("/i2psnark")) { } else if (ctxPath.equals("/i2psnark")) {
// duplicate classes removed from the .war in 0.7.12 // duplicate classes removed from the .war in 0.7.12
cp = "i2psnark.jar"; cp = "i2psnark.jar";
} else if (pluginLibDir.exists()) { } else if (pluginDir.exists()) {
Properties props = RouterConsoleRunner.webAppProperties(pluginLibDir.getAbsolutePath()); File consoleDir = new File(pluginDir, "console");
Properties props = RouterConsoleRunner.webAppProperties(consoleDir.getAbsolutePath());
cp = props.getProperty(RouterConsoleRunner.PREFIX + appName + CLASSPATH); cp = props.getProperty(RouterConsoleRunner.PREFIX + appName + CLASSPATH);
dir = pluginLibDir; dir = pluginDir;
} else { } else {
Properties props = RouterConsoleRunner.webAppProperties(); Properties props = RouterConsoleRunner.webAppProperties();
cp = props.getProperty(RouterConsoleRunner.PREFIX + appName + CLASSPATH); cp = props.getProperty(RouterConsoleRunner.PREFIX + appName + CLASSPATH);
@ -79,6 +82,8 @@ public class WebAppConfiguration implements WebApplicationContext.Configuration
String path; String path;
if (elem.startsWith("$I2P")) if (elem.startsWith("$I2P"))
path = i2pContext.getBaseDir().getAbsolutePath() + '/' + elem.substring(4); path = i2pContext.getBaseDir().getAbsolutePath() + '/' + elem.substring(4);
else if (elem.startsWith("$PLUGIN"))
path = dir.getAbsolutePath() + '/' + elem.substring(7);
else else
path = dir.getAbsolutePath() + '/' + elem; path = dir.getAbsolutePath() + '/' + elem;
System.err.println("Adding " + path + " to classpath for " + appName); System.err.println("Adding " + path + " to classpath for " + appName);

View File

@ -37,6 +37,8 @@ public class ClientAppConfig {
public String classpath; public String classpath;
/** @since 0.7.12 */ /** @since 0.7.12 */
public String stopargs; public String stopargs;
/** @since 0.7.12 */
public String uninstallargs;
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;
@ -47,10 +49,11 @@ public class ClientAppConfig {
} }
/** @since 0.7.12 */ /** @since 0.7.12 */
public ClientAppConfig(String cl, String client, String a, long d, boolean dis, String cp, String sa) { public ClientAppConfig(String cl, String client, String a, long d, boolean dis, String cp, String sa, String ua) {
this(cl, client, a, d, dis); this(cl, client, a, d, dis);
classpath = cp; classpath = cp;
stopargs = sa; stopargs = sa;
uninstallargs = ua;
} }
public static File configFile(I2PAppContext ctx) { public static File configFile(I2PAppContext ctx) {
@ -118,6 +121,7 @@ public class ClientAppConfig {
String disabled = clientApps.getProperty(PREFIX + i + ".startOnLoad"); String disabled = clientApps.getProperty(PREFIX + i + ".startOnLoad");
String classpath = clientApps.getProperty(PREFIX + i + ".classpath"); String classpath = clientApps.getProperty(PREFIX + i + ".classpath");
String stopargs = clientApps.getProperty(PREFIX + i + ".stopargs"); String stopargs = clientApps.getProperty(PREFIX + i + ".stopargs");
String uninstallargs = clientApps.getProperty(PREFIX + i + ".uninstallargs");
i++; i++;
boolean dis = disabled != null && "false".equals(disabled); boolean dis = disabled != null && "false".equals(disabled);
@ -129,7 +133,8 @@ 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, classpath, stopargs)); rv.add(new ClientAppConfig(className, clientName, args, delay, dis,
classpath, stopargs, uninstallargs));
} }
return rv; return rv;
} }