forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p' (head 7e9829897ed454bcb4a8e64b029060f7e90cbbfa)
to branch 'i2p.i2p.zzz.jetty6' (head b9984717e63b03b3b5fcf3a9729d55411aa65e89)
This commit is contained in:
@ -21,7 +21,12 @@
|
||||
<pathelement location="../../../core/java/build/obj" />
|
||||
<pathelement location="../../../router/java/build/obj" />
|
||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-sslengine.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-java5-threadpool.jar" />
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
|
||||
<pathelement location="../../systray/java/build/obj" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
<pathelement location="../../desktopgui/build" />
|
||||
@ -54,7 +59,12 @@
|
||||
<pathelement location="../../../core/java/build/i2p.jar" />
|
||||
<pathelement location="../../../router/java/build/router.jar" />
|
||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-sslengine.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-java5-threadpool.jar" />
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
|
||||
<pathelement location="../../systray/java/build/systray.jar" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
|
||||
@ -236,7 +246,9 @@
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../jetty/jettylib/ant.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
|
||||
<pathelement location="../../systray/java/build/obj" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
|
||||
@ -269,6 +281,11 @@
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-util.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-sslengine.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-java5-threadpool.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
|
||||
<pathelement location="../../systray/java/build/obj" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
|
||||
|
@ -15,7 +15,7 @@ import net.i2p.router.client.ClientManagerFacadeImpl;
|
||||
import net.i2p.router.startup.ClientAppConfig;
|
||||
import net.i2p.router.startup.LoadClientAppsJob;
|
||||
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.handler.ContextHandlerCollection;
|
||||
|
||||
/**
|
||||
* Saves changes to clients.config or webapps.config
|
||||
@ -291,7 +291,7 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
* requested and add the .war to that one
|
||||
*/
|
||||
private void startWebApp(String app) {
|
||||
Server s = WebAppStarter.getConsoleServer();
|
||||
ContextHandlerCollection s = WebAppStarter.getConsoleServer();
|
||||
if (s != null) {
|
||||
try {
|
||||
File path = new File(_context.getBaseDir(), "webapps");
|
||||
|
@ -4,11 +4,13 @@ import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
import org.mortbay.http.HttpRequest;
|
||||
import org.mortbay.http.HttpResponse;
|
||||
import org.mortbay.jetty.servlet.WebApplicationHandler;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
|
||||
/**
|
||||
* Convert foo.jsp to foo_xx.jsp for language xx.
|
||||
@ -19,12 +21,12 @@ import org.mortbay.jetty.servlet.WebApplicationHandler;
|
||||
*
|
||||
* @author zzz
|
||||
*/
|
||||
public class LocaleWebAppHandler extends WebApplicationHandler
|
||||
public class LocaleWebAppHandler extends WebAppContext
|
||||
{
|
||||
private final I2PAppContext _context;
|
||||
|
||||
public LocaleWebAppHandler(I2PAppContext ctx) {
|
||||
super();
|
||||
public LocaleWebAppHandler(I2PAppContext ctx, String path, String warPath) {
|
||||
super(warPath, path);
|
||||
_context = ctx;
|
||||
}
|
||||
|
||||
@ -36,13 +38,13 @@ public class LocaleWebAppHandler extends WebApplicationHandler
|
||||
*/
|
||||
@Override
|
||||
public void handle(String pathInContext,
|
||||
String pathParams,
|
||||
HttpRequest httpRequest,
|
||||
HttpResponse httpResponse)
|
||||
throws IOException
|
||||
HttpServletRequest httpRequest,
|
||||
HttpServletResponse httpResponse,
|
||||
int dispatch)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
// Handle OPTIONS (nothing to override)
|
||||
if (HttpRequest.__OPTIONS.equals(httpRequest.getMethod()))
|
||||
if ("OPTIONS".equals(httpRequest.getMethod()))
|
||||
{
|
||||
handleOptions(httpRequest, httpResponse);
|
||||
return;
|
||||
@ -74,7 +76,7 @@ public class LocaleWebAppHandler extends WebApplicationHandler
|
||||
if (lang != null && lang.length() > 0 && !lang.equals("en")) {
|
||||
String testPath = pathInContext.substring(0, len - 4) + '_' + lang + ".jsp";
|
||||
// Do we have a servlet for the new path that isn't the catchall *.jsp?
|
||||
Map.Entry servlet = getHolderEntry(testPath);
|
||||
Map.Entry servlet = getServletHandler().getHolderEntry(testPath);
|
||||
if (servlet != null) {
|
||||
String servletPath = (String) servlet.getKey();
|
||||
if (servletPath != null && !servletPath.startsWith("*")) {
|
||||
@ -87,7 +89,7 @@ public class LocaleWebAppHandler extends WebApplicationHandler
|
||||
}
|
||||
}
|
||||
//System.err.println("New path: " + newPath);
|
||||
super.handle(newPath, pathParams, httpRequest, httpResponse);
|
||||
super.handle(newPath, httpRequest, httpResponse, dispatch);
|
||||
//System.err.println("Was handled? " + httpRequest.isHandled());
|
||||
}
|
||||
|
||||
@ -95,22 +97,24 @@ public class LocaleWebAppHandler extends WebApplicationHandler
|
||||
* Overrides method in ServletHandler
|
||||
* @since 0.8
|
||||
*/
|
||||
/**** not in Jetty 6
|
||||
@Override
|
||||
public void handleTrace(HttpRequest request,
|
||||
HttpResponse response)
|
||||
public void handleTrace(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws IOException
|
||||
{
|
||||
response.sendError(HttpResponse.__405_Method_Not_Allowed);
|
||||
response.sendError(405);
|
||||
}
|
||||
****/
|
||||
|
||||
/**
|
||||
* Not an override
|
||||
* @since 0.8
|
||||
*/
|
||||
public void handleOptions(HttpRequest request,
|
||||
HttpResponse response)
|
||||
public void handleOptions(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws IOException
|
||||
{
|
||||
response.sendError(HttpResponse.__405_Method_Not_Allowed);
|
||||
response.sendError(405);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import java.util.List;
|
||||
import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.VersionComparator;
|
||||
|
||||
import org.mortbay.http.Version;
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.tanukisoftware.wrapper.WrapperManager;
|
||||
|
||||
public class LogsHelper extends HelperBase {
|
||||
@ -15,19 +15,12 @@ public class LogsHelper extends HelperBase {
|
||||
|
||||
/** @since 0.8.12 */
|
||||
public String getJettyVersion() {
|
||||
return jettyVersion();
|
||||
return Server.getVersion();
|
||||
}
|
||||
|
||||
|
||||
/** @since 0.8.13 */
|
||||
static String jettyVersion() {
|
||||
try {
|
||||
String rv = Version.getImplVersion();
|
||||
if (rv.startsWith("Jetty/"))
|
||||
rv = rv.substring(6);
|
||||
return rv;
|
||||
} catch (Throwable t) {
|
||||
return "unknown";
|
||||
}
|
||||
return Server.getVersion();
|
||||
}
|
||||
|
||||
public String getLogs() {
|
||||
|
@ -32,7 +32,7 @@ import net.i2p.util.Log;
|
||||
import net.i2p.util.Translate;
|
||||
import net.i2p.util.VersionComparator;
|
||||
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.handler.ContextHandlerCollection;
|
||||
|
||||
|
||||
/**
|
||||
@ -254,7 +254,7 @@ public class PluginStarter implements Runnable {
|
||||
}
|
||||
|
||||
// start console webapps in console/webapps
|
||||
Server server = WebAppStarter.getConsoleServer();
|
||||
ContextHandlerCollection server = WebAppStarter.getConsoleServer();
|
||||
if (server != null) {
|
||||
File consoleDir = new File(pluginDir, "console");
|
||||
Properties wprops = RouterConsoleRunner.webAppProperties(consoleDir.getAbsolutePath());
|
||||
@ -354,8 +354,8 @@ public class PluginStarter implements Runnable {
|
||||
}
|
||||
|
||||
// stop console webapps in console/webapps
|
||||
Server server = WebAppStarter.getConsoleServer();
|
||||
if (server != null) {
|
||||
//ContextHandlerCollection server = WebAppStarter.getConsoleServer();
|
||||
//if (server != null) {
|
||||
/*
|
||||
File consoleDir = new File(pluginDir, "console");
|
||||
Properties props = RouterConsoleRunner.webAppProperties(consoleDir.getAbsolutePath());
|
||||
@ -375,11 +375,11 @@ public class PluginStarter implements Runnable {
|
||||
Iterator <String> wars = pluginWars.get(appName).iterator();
|
||||
while (wars.hasNext()) {
|
||||
String warName = wars.next();
|
||||
WebAppStarter.stopWebApp(server, warName);
|
||||
WebAppStarter.stopWebApp(warName);
|
||||
}
|
||||
pluginWars.get(appName).clear();
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
// remove summary bar link
|
||||
Properties props = pluginProperties(ctx, appName);
|
||||
|
@ -11,12 +11,18 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.apps.systray.SysTray;
|
||||
import net.i2p.data.Base32;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.desktopgui.Main;
|
||||
import net.i2p.jetty.I2PLogger;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
@ -26,25 +32,41 @@ import net.i2p.util.SecureFileOutputStream;
|
||||
import net.i2p.util.ShellCommand;
|
||||
import net.i2p.util.VersionComparator;
|
||||
|
||||
import org.mortbay.http.DigestAuthenticator;
|
||||
import org.mortbay.http.HashUserRealm;
|
||||
import org.mortbay.http.NCSARequestLog;
|
||||
import org.mortbay.http.SecurityConstraint;
|
||||
import org.mortbay.http.SocketListener;
|
||||
import org.mortbay.http.SslListener;
|
||||
import org.mortbay.http.handler.SecurityHandler;
|
||||
import org.mortbay.jetty.AbstractConnector;
|
||||
import org.mortbay.jetty.Connector;
|
||||
import org.mortbay.jetty.Handler;
|
||||
import org.mortbay.jetty.NCSARequestLog;
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.servlet.WebApplicationContext;
|
||||
import org.mortbay.jetty.servlet.WebApplicationHandler;
|
||||
import org.mortbay.util.InetAddrPort;
|
||||
import org.mortbay.jetty.handler.ContextHandlerCollection;
|
||||
import org.mortbay.jetty.handler.DefaultHandler;
|
||||
import org.mortbay.jetty.handler.HandlerCollection;
|
||||
import org.mortbay.jetty.handler.RequestLogHandler;
|
||||
import org.mortbay.jetty.nio.SelectChannelConnector;
|
||||
import org.mortbay.jetty.security.DigestAuthenticator;
|
||||
import org.mortbay.jetty.security.HashUserRealm;
|
||||
import org.mortbay.jetty.security.Constraint;
|
||||
import org.mortbay.jetty.security.ConstraintMapping;
|
||||
import org.mortbay.jetty.security.SecurityHandler;
|
||||
import org.mortbay.jetty.security.SslSelectChannelConnector;
|
||||
import org.mortbay.jetty.servlet.ServletHandler;
|
||||
import org.mortbay.jetty.servlet.ServletHolder;
|
||||
import org.mortbay.jetty.servlet.SessionHandler;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
import org.mortbay.log.Log;
|
||||
import org.mortbay.thread.QueuedThreadPool;
|
||||
import org.mortbay.thread.concurrent.ThreadPool;
|
||||
|
||||
/**
|
||||
* Start the router console.
|
||||
*/
|
||||
public class RouterConsoleRunner {
|
||||
private Server _server;
|
||||
private static Server _server;
|
||||
private String _listenPort;
|
||||
private String _listenHost;
|
||||
private String _sslListenPort;
|
||||
private String _sslListenHost;
|
||||
private String _webAppsDir;
|
||||
|
||||
private static final String PROP_WEBAPP_CONFIG_FILENAME = "router.webappsConfigFile";
|
||||
private static final String DEFAULT_WEBAPP_CONFIG_FILENAME = "webapps.config";
|
||||
private static final DigestAuthenticator authenticator = new DigestAuthenticator();
|
||||
@ -59,6 +81,11 @@ public class RouterConsoleRunner {
|
||||
private static final String DEFAULT_WEBAPPS_DIR = "./webapps/";
|
||||
private static final String USAGE = "Bad RouterConsoleRunner arguments, check clientApp.0.args in your clients.config file! " +
|
||||
"Usage: [[port host[,host]] [-s sslPort [host[,host]]] [webAppsDir]]";
|
||||
|
||||
private static final int MIN_THREADS = 1;
|
||||
private static final int MAX_THREADS = 24;
|
||||
private static final int MAX_IDLE_TIME = 90*1000;
|
||||
private static final String THREAD_NAME = "RouterConsole Jetty";
|
||||
|
||||
static {
|
||||
System.setProperty("org.mortbay.http.Version.paranoid", "true");
|
||||
@ -137,6 +164,15 @@ public class RouterConsoleRunner {
|
||||
runner.startConsole();
|
||||
}
|
||||
|
||||
/**
|
||||
* SInce _server is now static
|
||||
* @return may be null or stopped perhaps
|
||||
* @since Jetty 6 since it doesn't have Server.getServers()
|
||||
*/
|
||||
static Server getConsoleServer() {
|
||||
return _server;
|
||||
}
|
||||
|
||||
private static void startTrayApp() {
|
||||
try {
|
||||
//TODO: move away from routerconsole into a separate application.
|
||||
@ -160,6 +196,24 @@ public class RouterConsoleRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* http://irc.codehaus.org/display/JETTY/Porting+to+jetty6
|
||||
*
|
||||
*<pre>
|
||||
* Server
|
||||
* HandlerCollection
|
||||
* ContextHandlerCollection
|
||||
* WebAppContext (i.e. ContextHandler)
|
||||
* SessionHandler
|
||||
* SecurityHandler
|
||||
* ServletHandler
|
||||
* servlets...
|
||||
* WebAppContext
|
||||
* ...
|
||||
* DefaultHandler
|
||||
* RequestLogHandler (opt)
|
||||
*</pre>
|
||||
*/
|
||||
public void startConsole() {
|
||||
File workDir = new SecureDirectory(I2PAppContext.getGlobalContext().getTempDir(), "jetty-work");
|
||||
boolean workDirRemoved = FileUtil.rmdir(workDir, false);
|
||||
@ -169,9 +223,37 @@ public class RouterConsoleRunner {
|
||||
if (!workDirCreated)
|
||||
System.err.println("ERROR: Unable to create Jetty temporary work directory");
|
||||
|
||||
//try {
|
||||
// Log.setLog(new I2PLogger(I2PAppContext.getGlobalContext()));
|
||||
//} catch (Throwable t) {
|
||||
// System.err.println("INFO: I2P Jetty logging class not found, logging to wrapper log");
|
||||
//}
|
||||
// This way it doesn't try to load Slf4jLog first
|
||||
System.setProperty("org.mortbay.log.class", "net.i2p.jetty.I2PLogger");
|
||||
|
||||
// so Jetty can find WebAppConfiguration
|
||||
System.setProperty("jetty.class.path", I2PAppContext.getGlobalContext().getBaseDir() + "/lib/routerconsole.jar");
|
||||
_server = new Server();
|
||||
_server.setGracefulShutdown(1000);
|
||||
|
||||
try {
|
||||
ThreadPool ctp = new CustomThreadPoolExecutor();
|
||||
ctp.prestartAllCoreThreads();
|
||||
_server.setThreadPool(ctp);
|
||||
} catch (Throwable t) {
|
||||
// class not found...
|
||||
System.out.println("INFO: Jetty concurrent ThreadPool unavailable, using QueuedThreadPool");
|
||||
QueuedThreadPool qtp = new QueuedThreadPool(MAX_THREADS);
|
||||
qtp.setMinThreads(MIN_THREADS);
|
||||
qtp.setMaxIdleTimeMs(MAX_IDLE_TIME);
|
||||
_server.setThreadPool(qtp);
|
||||
}
|
||||
|
||||
HandlerCollection hColl = new HandlerCollection();
|
||||
ContextHandlerCollection chColl = new ContextHandlerCollection();
|
||||
_server.addHandler(hColl);
|
||||
hColl.addHandler(chColl);
|
||||
hColl.addHandler(new DefaultHandler());
|
||||
|
||||
String log = I2PAppContext.getGlobalContext().getProperty("routerconsole.log");
|
||||
if (log != null) {
|
||||
@ -179,8 +261,10 @@ public class RouterConsoleRunner {
|
||||
if (!logFile.isAbsolute())
|
||||
logFile = new File(I2PAppContext.getGlobalContext().getLogDir(), "logs/" + log);
|
||||
try {
|
||||
_server.setRequestLog(new NCSARequestLog(logFile.getAbsolutePath()));
|
||||
} catch (IOException ioe) {
|
||||
RequestLogHandler rhl = new RequestLogHandler();
|
||||
rhl.setRequestLog(new NCSARequestLog(logFile.getAbsolutePath()));
|
||||
hColl.addHandler(rhl);
|
||||
} catch (Exception ioe) {
|
||||
System.err.println("ERROR: Unable to create Jetty log: " + ioe);
|
||||
}
|
||||
}
|
||||
@ -203,8 +287,8 @@ public class RouterConsoleRunner {
|
||||
if (!_webAppsDir.endsWith("/"))
|
||||
_webAppsDir += '/';
|
||||
|
||||
List<String> notStarted = new ArrayList();
|
||||
WebApplicationHandler baseHandler = null;
|
||||
WebAppContext rootWebApp = null;
|
||||
ServletHandler rootServletHandler = null;
|
||||
try {
|
||||
int boundAddresses = 0;
|
||||
|
||||
@ -219,17 +303,17 @@ public class RouterConsoleRunner {
|
||||
// _server.addListener('[' + host + "]:" + _listenPort);
|
||||
//else
|
||||
// _server.addListener(host + ':' + _listenPort);
|
||||
InetAddrPort iap = new InetAddrPort(host, lport);
|
||||
SocketListener lsnr = new SocketListener(iap);
|
||||
lsnr.setMinThreads(1); // default 2
|
||||
lsnr.setMaxThreads(24); // default 256
|
||||
lsnr.setMaxIdleTimeMs(90*1000); // default 10 sec
|
||||
// Use AbstractConnector instead of Connector so we can do setName()
|
||||
AbstractConnector lsnr = new SelectChannelConnector();
|
||||
lsnr.setHost(host);
|
||||
lsnr.setPort(lport);
|
||||
lsnr.setMaxIdleTime(90*1000); // default 10 sec
|
||||
lsnr.setName("ConsoleSocket"); // all with same name will use the same thread pool
|
||||
_server.addListener(lsnr);
|
||||
_server.addConnector(lsnr);
|
||||
boundAddresses++;
|
||||
} catch (NumberFormatException nfe) {
|
||||
System.err.println("Unable to bind routerconsole to " + host + " port " + _listenPort + ' ' + nfe);
|
||||
} catch (IOException ioe) { // this doesn't seem to work, exceptions don't happen until start() below
|
||||
} catch (Exception ioe) { // this doesn't seem to work, exceptions don't happen until start() below
|
||||
System.err.println("Unable to bind routerconsole to " + host + " port " + _listenPort + ' ' + ioe);
|
||||
}
|
||||
}
|
||||
@ -254,19 +338,20 @@ public class RouterConsoleRunner {
|
||||
while (tok.hasMoreTokens()) {
|
||||
String host = tok.nextToken().trim();
|
||||
// doing it this way means we don't have to escape an IPv6 host with []
|
||||
InetAddrPort iap = new InetAddrPort(host, sslPort);
|
||||
try {
|
||||
SslListener ssll = new SslListener(iap);
|
||||
// TODO if class not found use SslChannelConnector
|
||||
// Sadly there's no common base class with the ssl methods in it
|
||||
SslSelectChannelConnector ssll = new SslSelectChannelConnector();
|
||||
ssll.setHost(host);
|
||||
ssll.setPort(sslPort);
|
||||
// the keystore path and password
|
||||
ssll.setKeystore(keyStore.getAbsolutePath());
|
||||
ssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD));
|
||||
// the X.509 cert password (if not present, verifyKeyStore() returned false)
|
||||
ssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork"));
|
||||
ssll.setMinThreads(1); // default 2
|
||||
ssll.setMaxThreads(24); // default 256
|
||||
ssll.setMaxIdleTimeMs(90*1000); // default 10 sec
|
||||
ssll.setMaxIdleTime(90*1000); // default 10 sec
|
||||
ssll.setName("ConsoleSocket"); // all with same name will use the same thread pool
|
||||
_server.addListener(ssll);
|
||||
_server.addConnector(ssll);
|
||||
boundAddresses++;
|
||||
} catch (Exception e) { // probably no exceptions at this point
|
||||
System.err.println("Unable to bind routerconsole to " + host + " port " + sslPort + " for SSL: " + e);
|
||||
@ -282,47 +367,25 @@ public class RouterConsoleRunner {
|
||||
System.err.println("Unable to bind routerconsole to any address on port " + _listenPort + (sslPort > 0 ? (" or SSL port " + sslPort) : ""));
|
||||
return;
|
||||
}
|
||||
_server.setRootWebApp(ROUTERCONSOLE);
|
||||
WebApplicationContext wac = _server.addWebApplication("/", _webAppsDir + ROUTERCONSOLE + ".war");
|
||||
|
||||
rootWebApp = new LocaleWebAppHandler(I2PAppContext.getGlobalContext(),
|
||||
"/", _webAppsDir + ROUTERCONSOLE + ".war");
|
||||
File tmpdir = new SecureDirectory(workDir, ROUTERCONSOLE + "-" +
|
||||
(_listenPort != null ? _listenPort : _sslListenPort));
|
||||
tmpdir.mkdir();
|
||||
wac.setTempDirectory(tmpdir);
|
||||
baseHandler = new LocaleWebAppHandler(I2PAppContext.getGlobalContext());
|
||||
wac.addHandler(0, baseHandler);
|
||||
initialize(wac);
|
||||
File dir = new File(_webAppsDir);
|
||||
String fileNames[] = dir.list(WarFilenameFilter.instance());
|
||||
if (fileNames != null) {
|
||||
for (int i = 0; i < fileNames.length; i++) {
|
||||
try {
|
||||
String appName = fileNames[i].substring(0, fileNames[i].lastIndexOf(".war"));
|
||||
String enabled = props.getProperty(PREFIX + appName + ENABLED);
|
||||
if (! "false".equals(enabled)) {
|
||||
String path = new File(dir, fileNames[i]).getCanonicalPath();
|
||||
tmpdir = new SecureDirectory(workDir, appName + "-" +
|
||||
(_listenPort != null ? _listenPort : _sslListenPort));
|
||||
WebAppStarter.addWebApp(I2PAppContext.getGlobalContext(), _server, appName, path, tmpdir);
|
||||
rootWebApp.setTempDirectory(tmpdir);
|
||||
rootWebApp.setSessionHandler(new SessionHandler());
|
||||
rootServletHandler = new ServletHandler();
|
||||
rootWebApp.setServletHandler(rootServletHandler);
|
||||
initialize(rootWebApp);
|
||||
chColl.addHandler(rootWebApp);
|
||||
|
||||
if (enabled == null) {
|
||||
// do this so configclients.jsp knows about all apps from reading the config
|
||||
props.setProperty(PREFIX + appName + ENABLED, "true");
|
||||
rewrite = true;
|
||||
}
|
||||
} else {
|
||||
notStarted.add(appName);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("Error resolving '" + fileNames[i] + "' in '" + dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
} catch (Exception ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
if (rewrite)
|
||||
storeWebAppProperties(props);
|
||||
|
||||
try {
|
||||
// start does a mapContexts()
|
||||
_server.start();
|
||||
} catch (Throwable me) {
|
||||
// NoClassFoundDefError from a webapp is a throwable, not an exception
|
||||
@ -335,14 +398,61 @@ public class RouterConsoleRunner {
|
||||
me.printStackTrace();
|
||||
}
|
||||
|
||||
if (baseHandler != null) {
|
||||
// Start all the other webapps after the server is up,
|
||||
// so things start faster.
|
||||
// Jetty 6 starts the connector before the router console is ready
|
||||
// This also prevents one webapp from breaking the whole thing
|
||||
List<String> notStarted = new ArrayList();
|
||||
if (_server.isRunning()) {
|
||||
File dir = new File(_webAppsDir);
|
||||
String fileNames[] = dir.list(WarFilenameFilter.instance());
|
||||
if (fileNames != null) {
|
||||
for (int i = 0; i < fileNames.length; i++) {
|
||||
String appName = fileNames[i].substring(0, fileNames[i].lastIndexOf(".war"));
|
||||
String enabled = props.getProperty(PREFIX + appName + ENABLED);
|
||||
if (! "false".equals(enabled)) {
|
||||
try {
|
||||
String path = new File(dir, fileNames[i]).getCanonicalPath();
|
||||
WebAppStarter.startWebApp(I2PAppContext.getGlobalContext(), chColl, appName, path);
|
||||
if (enabled == null) {
|
||||
// do this so configclients.jsp knows about all apps from reading the config
|
||||
props.setProperty(PREFIX + appName + ENABLED, "true");
|
||||
rewrite = true;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
System.err.println("ERROR: Failed to start " + appName + ' ' + t);
|
||||
t.printStackTrace();
|
||||
notStarted.add(appName);
|
||||
}
|
||||
} else {
|
||||
notStarted.add(appName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.err.println("ERROR: Router console did not start, not starting webapps");
|
||||
}
|
||||
|
||||
if (rewrite)
|
||||
storeWebAppProperties(props);
|
||||
|
||||
if (rootServletHandler != null && notStarted.size() > 0) {
|
||||
// map each not-started webapp to the error page
|
||||
ServletHolder noWebApp = rootServletHandler.getServlet("net.i2p.router.web.jsp.nowebapp_jsp");
|
||||
for (int i = 0; i < notStarted.size(); i++) {
|
||||
// we want a new handler for each one since if the webapp is started we remove the handler???
|
||||
try {
|
||||
baseHandler.mapPathToServlet('/' + notStarted.get(i) + "/*",
|
||||
"net.i2p.router.web.jsp.nowebapp_jsp");
|
||||
if (noWebApp != null) {
|
||||
String path = '/' + notStarted.get(i);
|
||||
// LocaleWebAppsHandler adds a .jsp
|
||||
rootServletHandler.addServletWithMapping(noWebApp, path + ".jsp");
|
||||
rootServletHandler.addServletWithMapping(noWebApp, path + "/*");
|
||||
} else {
|
||||
System.err.println("Can't find nowebapp.jsp?");
|
||||
}
|
||||
} catch (Throwable me) {
|
||||
System.err.println(me);
|
||||
me.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -458,18 +568,22 @@ public class RouterConsoleRunner {
|
||||
return success;
|
||||
}
|
||||
|
||||
static void initialize(WebApplicationContext context) {
|
||||
static void initialize(WebAppContext context) {
|
||||
SecurityHandler sec = new SecurityHandler();
|
||||
List<ConstraintMapping> constraints = new ArrayList(4);
|
||||
String password = getPassword();
|
||||
if (password != null) {
|
||||
HashUserRealm realm = new HashUserRealm("i2prouter");
|
||||
realm.put("admin", password);
|
||||
realm.addUserToRole("admin", "routerAdmin");
|
||||
context.setRealm(realm);
|
||||
context.setAuthenticator(authenticator);
|
||||
context.addHandler(0, new SecurityHandler());
|
||||
SecurityConstraint constraint = new SecurityConstraint("admin", "routerAdmin");
|
||||
sec.setUserRealm(realm);
|
||||
sec.setAuthenticator(authenticator);
|
||||
Constraint constraint = new Constraint("admin", "routerAdmin");
|
||||
constraint.setAuthenticate(true);
|
||||
context.addSecurityConstraint("/", constraint);
|
||||
ConstraintMapping cm = new ConstraintMapping();
|
||||
cm.setConstraint(constraint);
|
||||
cm.setPathSpec("/");
|
||||
constraints.add(cm);
|
||||
}
|
||||
|
||||
// This forces a '403 Forbidden' response for TRACE and OPTIONS unless the
|
||||
@ -481,12 +595,27 @@ public class RouterConsoleRunner {
|
||||
// The other strange methods - PUT, DELETE, MOVE - are disabled by default
|
||||
// See also:
|
||||
// http://old.nabble.com/Disable-HTTP-TRACE-in-Jetty-5.x-td12412607.html
|
||||
SecurityConstraint sc = new SecurityConstraint();
|
||||
sc.setName("No trace or options");
|
||||
sc.addMethod("TRACE");
|
||||
sc.addMethod("OPTIONS");
|
||||
sc.setAuthenticate(true);
|
||||
context.addSecurityConstraint("/*", sc) ;
|
||||
|
||||
Constraint sc = new Constraint();
|
||||
sc.setName("No trace");
|
||||
ConstraintMapping cm = new ConstraintMapping();
|
||||
cm.setMethod("TRACE");
|
||||
cm.setConstraint(sc);
|
||||
cm.setPathSpec("/");
|
||||
constraints.add(cm);
|
||||
|
||||
sc = new Constraint();
|
||||
sc.setName("No options");
|
||||
cm = new ConstraintMapping();
|
||||
cm.setMethod("OPTIONS");
|
||||
cm.setConstraint(sc);
|
||||
cm.setPathSpec("/");
|
||||
constraints.add(cm);
|
||||
|
||||
ConstraintMapping cmarr[] = constraints.toArray(new ConstraintMapping[constraints.size()]);
|
||||
sec.setConstraintMappings(cmarr);
|
||||
|
||||
context.setSecurityHandler(sec);
|
||||
}
|
||||
|
||||
static String getPassword() {
|
||||
@ -511,11 +640,11 @@ public class RouterConsoleRunner {
|
||||
}
|
||||
|
||||
/** @since 0.8.8 */
|
||||
private class ServerShutdown implements Runnable {
|
||||
private static class ServerShutdown implements Runnable {
|
||||
public void run() {
|
||||
try {
|
||||
_server.stop();
|
||||
} catch (InterruptedException ie) {}
|
||||
} catch (Exception ie) {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -574,4 +703,31 @@ public class RouterConsoleRunner {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Just to set the name and set Daemon
|
||||
* @since Jetty 6
|
||||
*/
|
||||
private static class CustomThreadPoolExecutor extends ThreadPool {
|
||||
public CustomThreadPoolExecutor() {
|
||||
super(MIN_THREADS, MAX_THREADS, MAX_IDLE_TIME, TimeUnit.MILLISECONDS,
|
||||
new SynchronousQueue(), new CustomThreadFactory(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Just to set the name and set Daemon
|
||||
* @since Jetty 6
|
||||
*/
|
||||
private static class CustomThreadFactory implements ThreadFactory {
|
||||
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread rv = Executors.defaultThreadFactory().newThread(r);
|
||||
rv.setName(THREAD_NAME);
|
||||
rv.setDaemon(true);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
import org.mortbay.jetty.servlet.WebApplicationContext;
|
||||
import org.mortbay.jetty.webapp.Configuration;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
|
||||
|
||||
/**
|
||||
@ -31,16 +32,16 @@ import org.mortbay.jetty.servlet.WebApplicationContext;
|
||||
* @since 0.7.12
|
||||
* @author zzz
|
||||
*/
|
||||
public class WebAppConfiguration implements WebApplicationContext.Configuration {
|
||||
private WebApplicationContext _wac;
|
||||
public class WebAppConfiguration implements Configuration {
|
||||
private WebAppContext _wac;
|
||||
|
||||
private static final String CLASSPATH = ".classpath";
|
||||
|
||||
public void setWebApplicationContext(WebApplicationContext context) {
|
||||
public void setWebAppContext(WebAppContext context) {
|
||||
_wac = context;
|
||||
}
|
||||
|
||||
public WebApplicationContext getWebApplicationContext() {
|
||||
public WebAppContext getWebAppContext() {
|
||||
return _wac;
|
||||
}
|
||||
|
||||
@ -87,10 +88,16 @@ public class WebAppConfiguration implements WebApplicationContext.Configuration
|
||||
else
|
||||
path = dir.getAbsolutePath() + '/' + elem;
|
||||
System.err.println("Adding " + path + " to classpath for " + appName);
|
||||
_wac.addClassPath(path);
|
||||
_wac.setExtraClasspath(path);
|
||||
}
|
||||
}
|
||||
|
||||
public void configureDefaults() {}
|
||||
public void configureWebApp() {}
|
||||
|
||||
/** @since Jetty 6 */
|
||||
public void deconfigureWebApp() {}
|
||||
|
||||
/** @since Jetty 6 */
|
||||
public void configureClassLoader() {}
|
||||
}
|
||||
|
@ -14,10 +14,12 @@ import net.i2p.util.Log;
|
||||
import net.i2p.util.SecureDirectory;
|
||||
import net.i2p.util.PortMapper;
|
||||
|
||||
import org.mortbay.http.HttpContext;
|
||||
import org.mortbay.http.HttpListener;
|
||||
import org.mortbay.jetty.Connector;
|
||||
import org.mortbay.jetty.Handler;
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.servlet.WebApplicationContext;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
import org.mortbay.jetty.handler.ContextHandler;
|
||||
import org.mortbay.jetty.handler.ContextHandlerCollection;
|
||||
|
||||
|
||||
/**
|
||||
@ -49,9 +51,10 @@ public class WebAppStarter {
|
||||
* adds and starts
|
||||
* @throws just about anything, caller would be wise to catch Throwable
|
||||
*/
|
||||
static void startWebApp(I2PAppContext ctx, Server server, String appName, String warPath) throws Exception {
|
||||
static void startWebApp(I2PAppContext ctx, ContextHandlerCollection server,
|
||||
String appName, String warPath) throws Exception {
|
||||
File tmpdir = new SecureDirectory(ctx.getTempDir(), "jetty-work-" + appName + ctx.random().nextInt());
|
||||
WebApplicationContext wac = addWebApp(ctx, server, appName, warPath, tmpdir);
|
||||
WebAppContext wac = addWebApp(ctx, server, appName, warPath, tmpdir);
|
||||
_log.debug("Loading war from: " + warPath);
|
||||
wac.start();
|
||||
}
|
||||
@ -61,12 +64,13 @@ public class WebAppStarter {
|
||||
* This is used only by RouterConsoleRunner, which adds all the webapps first
|
||||
* and then starts all at once.
|
||||
*/
|
||||
static WebApplicationContext addWebApp(I2PAppContext ctx, Server server, String appName, String warPath, File tmpdir) throws IOException {
|
||||
static WebAppContext addWebApp(I2PAppContext ctx, ContextHandlerCollection server,
|
||||
String appName, String warPath, File tmpdir) throws IOException {
|
||||
|
||||
// Jetty will happily load one context on top of another without stopping
|
||||
// the first one, so we remove any previous one here
|
||||
try {
|
||||
stopWebApp(server, appName);
|
||||
stopWebApp(appName);
|
||||
} catch (Throwable t) {}
|
||||
|
||||
// To avoid ZipErrors from JarURLConnetion caching,
|
||||
@ -91,7 +95,7 @@ public class WebAppStarter {
|
||||
warPath = tmpPath;
|
||||
}
|
||||
|
||||
WebApplicationContext wac = server.addWebApplication("/"+ appName, warPath);
|
||||
WebAppContext wac = new WebAppContext(warPath, "/"+ appName);
|
||||
tmpdir.mkdir();
|
||||
wac.setTempDirectory(tmpdir);
|
||||
|
||||
@ -101,12 +105,14 @@ public class WebAppStarter {
|
||||
|
||||
|
||||
// see WebAppConfiguration for info
|
||||
String[] classNames = server.getWebApplicationConfigurationClassNames();
|
||||
String[] classNames = wac.getConfigurationClasses();
|
||||
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);
|
||||
wac.setConfigurationClasses(newClassNames);
|
||||
server.addHandler(wac);
|
||||
server.mapContexts();
|
||||
return wac;
|
||||
}
|
||||
|
||||
@ -114,42 +120,55 @@ public class WebAppStarter {
|
||||
* stop it and remove the context
|
||||
* @throws just about anything, caller would be wise to catch Throwable
|
||||
*/
|
||||
static void stopWebApp(Server server, String appName) {
|
||||
// this will return a new context if one does not exist
|
||||
HttpContext wac = server.getContext('/' + appName);
|
||||
static void stopWebApp(String appName) {
|
||||
ContextHandler wac = getWebApp(appName);
|
||||
if (wac == null)
|
||||
return;
|
||||
try {
|
||||
// false -> not graceful
|
||||
wac.stop(false);
|
||||
} catch (InterruptedException ie) {}
|
||||
// not graceful is default in Jetty 6?
|
||||
wac.stop();
|
||||
} catch (Exception ie) {}
|
||||
ContextHandlerCollection server = getConsoleServer();
|
||||
if (server == null)
|
||||
return;
|
||||
try {
|
||||
server.removeContext(wac);
|
||||
server.removeHandler(wac);
|
||||
server.mapContexts();
|
||||
} catch (IllegalStateException ise) {}
|
||||
}
|
||||
|
||||
static boolean isWebAppRunning(String appName) {
|
||||
Server server = WebAppStarter.getConsoleServer();
|
||||
if (server == null)
|
||||
ContextHandler wac = getWebApp(appName);
|
||||
if (wac == null)
|
||||
return false;
|
||||
// this will return a new context if one does not exist
|
||||
HttpContext wac = server.getContext('/' + appName);
|
||||
return wac.isStarted();
|
||||
}
|
||||
|
||||
/** see comments in ConfigClientsHandler */
|
||||
static Server getConsoleServer() {
|
||||
PortMapper pm = I2PAppContext.getGlobalContext().portMapper();
|
||||
int p1 = pm.getPort(PortMapper.SVC_CONSOLE);
|
||||
int p2 = pm.getPort(PortMapper.SVC_HTTPS_CONSOLE);
|
||||
Collection c = Server.getHttpServers();
|
||||
for (int i = 0; i < c.size(); i++) {
|
||||
Server s = (Server) c.toArray()[i];
|
||||
HttpListener[] hl = s.getListeners();
|
||||
for (int j = 0; j < hl.length; j++) {
|
||||
int port = hl[j].getPort();
|
||||
if (port == p1 || port == p2)
|
||||
return s;
|
||||
}
|
||||
/** @since Jetty 6 */
|
||||
static ContextHandler getWebApp(String appName) {
|
||||
ContextHandlerCollection server = getConsoleServer();
|
||||
if (server == null)
|
||||
return null;
|
||||
Handler handlers[] = server.getHandlers();
|
||||
if (handlers == null)
|
||||
return null;
|
||||
String path = '/'+ appName;
|
||||
for (int i = 0; i < handlers.length; i++) {
|
||||
ContextHandler ch = (ContextHandler) handlers[i];
|
||||
if (path.equals(ch.getContextPath()))
|
||||
return ch;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** see comments in ConfigClientsHandler */
|
||||
static ContextHandlerCollection getConsoleServer() {
|
||||
Server s = RouterConsoleRunner.getConsoleServer();
|
||||
if (s == null)
|
||||
return null;
|
||||
Handler h = s.getChildHandlerByClass(ContextHandlerCollection.class);
|
||||
if (h == null)
|
||||
return null;
|
||||
return (ContextHandlerCollection) h;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user