diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java index bcd1f3cbd..31d854aea 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java @@ -69,6 +69,8 @@ public class RouterConsoleRunner { if (!workDirCreated) System.err.println("ERROR: Unable to create Jetty temporary work directory"); + // so Jetty can find WebAppConfiguration + System.setProperty("jetty.class.path", I2PAppContext.getGlobalContext().getBaseDir() + "/lib/routerconsole.jar"); _server = new Server(); boolean rewrite = false; Properties props = webAppProperties(); @@ -127,11 +129,9 @@ public class RouterConsoleRunner { String enabled = props.getProperty(PREFIX + appName + ENABLED); if (! "false".equals(enabled)) { String path = new File(dir, fileNames[i]).getCanonicalPath(); - wac = _server.addWebApplication("/"+ appName, path); tmpdir = new File(workDir, appName + "-" + _listenPort); - tmpdir.mkdir(); - wac.setTempDirectory(tmpdir); - initialize(wac); + WebAppStarter.addWebApp(I2PAppContext.getGlobalContext(), _server, appName, path, tmpdir); + if (enabled == null) { // do this so configclients.jsp knows about all apps from reading the config props.setProperty(PREFIX + appName + ENABLED, "true"); @@ -190,7 +190,7 @@ public class RouterConsoleRunner { st.start(); } - private void initialize(WebApplicationContext context) { + static void initialize(WebApplicationContext context) { String password = getPassword(); if (password != null) { HashUserRealm realm = new HashUserRealm("i2prouter"); @@ -205,7 +205,7 @@ public class RouterConsoleRunner { } } - private String getPassword() { + static String getPassword() { List contexts = RouterContext.listContexts(); if (contexts != null) { for (int i = 0; i < contexts.size(); i++) { @@ -237,10 +237,14 @@ public class RouterConsoleRunner { ********/ public static Properties webAppProperties() { + return webAppProperties(I2PAppContext.getGlobalContext().getConfigDir().getAbsolutePath()); + } + + public static Properties webAppProperties(String dir) { Properties rv = new Properties(); // String webappConfigFile = ctx.getProperty(PROP_WEBAPP_CONFIG_FILENAME, DEFAULT_WEBAPP_CONFIG_FILENAME); String webappConfigFile = DEFAULT_WEBAPP_CONFIG_FILENAME; - File cfgFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), webappConfigFile); + File cfgFile = new File(dir, webappConfigFile); try { DataHelper.loadProps(rv, cfgFile); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java new file mode 100644 index 000000000..d903d83ca --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java @@ -0,0 +1,91 @@ +package net.i2p.router.web; + +import java.io.File; +import java.util.Properties; +import java.util.StringTokenizer; + +import net.i2p.I2PAppContext; + +import org.mortbay.jetty.servlet.WebApplicationContext; + + +/** + * Add to the webapp classpath as specified in webapps.config. + * This allows us to reference classes that are not in the classpath + * specified in wrapper.config, since old installations have + * individual jars and not lib/*.jar specified in wrapper.config. + * + * A sample line in webapps.config is: + * webapps.appname.path=foo.jar,$I2P/lib/bar.jar + * Unless $I2P is specified the path will be relative to $I2P/lib for + * webapps in the installation and appDir/plugins/appname/lib for plugins. + * + * Sadly, setting Class-Path in MANIFEST.MF doesn't work for jetty wars. + * We could look there ourselves, or look for another properties file in the war, + * but let's just do it in webapps.config. + * + * No, wac.addClassPath() does not work. For more info see: + * + * http://servlets.com/archive/servlet/ReadMsg?msgId=511113&listName=jetty-support + * + * @since 0.7.12 + * @author zzz + */ +public class WebAppConfiguration implements WebApplicationContext.Configuration { + private WebApplicationContext _wac; + + private static final String CLASSPATH = ".classpath"; + + public void setWebApplicationContext(WebApplicationContext context) { + _wac = context; + } + + public WebApplicationContext getWebApplicationContext() { + return _wac; + } + + public void configureClassPath() throws Exception { + String ctxPath = _wac.getContextPath(); + //System.err.println("Configure Class Path " + ctxPath); + if (ctxPath.equals("/")) + return; + String appName = ctxPath.substring(1); + + I2PAppContext i2pContext = I2PAppContext.getGlobalContext(); + File libDir = new File(i2pContext.getBaseDir(), "lib"); + File pluginLibDir = new File(i2pContext.getAppDir(), + PluginUpdateHandler.PLUGIN_DIR + ctxPath + '/' + "lib"); + File dir = libDir; + String cp; + if (ctxPath.equals("/susidns")) { + // jars moved from the .war to lib/ in 0.7.12 + cp = "jstl.jar,standard.jar"; + } else if (ctxPath.equals("/i2psnark")) { + // duplicate classes removed from the .war in 0.7.12 + cp = "i2psnark.jar"; + } else if (pluginLibDir.exists()) { + Properties props = RouterConsoleRunner.webAppProperties(pluginLibDir.getAbsolutePath()); + cp = props.getProperty(RouterConsoleRunner.PREFIX + appName + CLASSPATH); + dir = pluginLibDir; + } else { + Properties props = RouterConsoleRunner.webAppProperties(); + cp = props.getProperty(RouterConsoleRunner.PREFIX + appName + CLASSPATH); + } + if (cp == null) + return; + StringTokenizer tok = new StringTokenizer(cp, " ,"); + while (tok.hasMoreTokens()) { + String elem = tok.nextToken().trim(); + String path; + if (elem.startsWith("$I2P")) + path = i2pContext.getBaseDir().getAbsolutePath() + '/' + elem.substring(4); + else + path = dir.getAbsolutePath() + '/' + elem; + System.err.println("Adding " + path + " to classpath for " + appName); + _wac.addClassPath(path); + } + } + + public void configureDefaults() {} + public void configureWebApp() {} +} diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java new file mode 100644 index 000000000..dafc1c10a --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java @@ -0,0 +1,60 @@ +package net.i2p.router.web; + +import java.io.File; +import java.io.IOException; +import java.util.Properties; +import java.util.StringTokenizer; + +import net.i2p.I2PAppContext; + +import org.mortbay.jetty.Server; +import org.mortbay.jetty.servlet.WebApplicationContext; + + +/** + * Start a webappapp classpath as specified in webapps.config. + * + * Sadly, setting Class-Path in MANIFEST.MF doesn't work for jetty wars. + * We could look there ourselves, or look for another properties file in the war, + * but let's just do it in webapps.config. + * + * No, wac.addClassPath() does not work. + * + * http://servlets.com/archive/servlet/ReadMsg?msgId=511113&listName=jetty-support + * + * @since 0.7.12 + * @author zzz + */ +public class WebAppStarter { + + /** + * adds and starts + */ + static void startWebApp(I2PAppContext ctx, Server server, String appName, String warPath) throws Exception { + File tmpdir = new File(ctx.getTempDir(), "jetty-work-" + appName + ctx.random().nextInt()); + WebApplicationContext wac = addWebApp(ctx, server, appName, warPath, tmpdir); + wac.start(); + } + + /** + * add but don't start + */ + static WebApplicationContext addWebApp(I2PAppContext ctx, Server server, String appName, String warPath, File tmpdir) throws IOException { + + WebApplicationContext wac = server.addWebApplication("/"+ appName, warPath); + tmpdir.mkdir(); + wac.setTempDirectory(tmpdir); + + // this does the passwords... + RouterConsoleRunner.initialize(wac); + + // see WebAppConfiguration for info + String[] classNames = server.getWebApplicationConfigurationClassNames(); + String[] newClassNames = new String[classNames.length + 1]; + for (int j = 0; j < classNames.length; j++) + newClassNames[j] = classNames[j]; + newClassNames[classNames.length] = WebAppConfiguration.class.getName(); + wac.setConfigurationClassNames(newClassNames); + return wac; + } +}