diff --git a/LICENSE.txt b/LICENSE.txt
index 4d6494366af2f3923bc57413ebd420170064c715..db99aa5fc27d54c118c1c615be131e3750418dc9 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -172,8 +172,9 @@ Applications:
    By welterde.
    See licenses/LICENSE-GPLv2.txt
 
-   Jetty 5.1.15:
-   Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
+   Jetty 6.1.26:
+   Copyright 1995-2009 Mort Bay Consulting Pty Ltd
+   See licenses/LICENSE-Jetty.txt
    See licenses/LICENSE-Apache2.0.txt
    See licenses/NOTICE-Commons-Logging.txt
 
@@ -215,8 +216,10 @@ Applications:
    Copyright (C) 2005 <susi23@mail.i2p>
    GPLv2 (or any later version)
    See licenses/LICENSE-GPLv2.txt
-       Uses Apache Jakarta Standard Tag Library 1.1.2:
-       See licenses/LICENSE-Apache2.0.txt
+       Uses Glassfish Standard Tag Library (JSTL) 1.2:
+       Common Development and Distribution License (CDDL) version 1.0 + GNU General Public License (GPL) version 2
+       See https://glassfish.dev.java.net/public/CDDL+GPL.html
+       See licenses/LICENSE-GPLv2.txt
 
    SusiMail:
    Copyright (C) 2004-2005  <susi23@mail.i2p>
@@ -228,6 +231,10 @@ Applications:
       Bundles systray4j-2.4.1:
       See licenses/LICENSE-LGPLv2.1.txt
 
+   Tomcat 6.0.35:
+   Copyright 1999-2011 The Apache Software Foundation
+   See licenses/LICENSE-Apache2.0.txt
+   See licenses/NOTICE-Tomcat.txt
 
 
 Other Applications and Libraries
diff --git a/apps/addressbook/java/src/net/i2p/addressbook/Servlet.java b/apps/addressbook/java/src/net/i2p/addressbook/Servlet.java
index beb225ca0d6d60fcea8b69585b24abcbf91240d8..9b386b423abd0f076d33a8974a0d09e8be65916c 100644
--- a/apps/addressbook/java/src/net/i2p/addressbook/Servlet.java
+++ b/apps/addressbook/java/src/net/i2p/addressbook/Servlet.java
@@ -84,7 +84,7 @@ public class Servlet extends HttpServlet {
         this.thread.setDaemon(true);
         this.thread.setName("Addressbook");
         this.thread.start();
-        System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
+        //System.out.println("INFO: Starting Addressbook " + Daemon.VERSION);
         //System.out.println("INFO: config root under " + args[0]);
     }
 
diff --git a/apps/i2psnark/java/build.xml b/apps/i2psnark/java/build.xml
index c5a3b106fd7fd5e3d44efcb0184818a04652c005..fa7c03147ff7085743597991adf14bdeff2953dc 100644
--- a/apps/i2psnark/java/build.xml
+++ b/apps/i2psnark/java/build.xml
@@ -19,6 +19,7 @@
                 <pathelement location="../../ministreaming/java/build/obj" />
                 <pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
                 <pathelement location="../../jetty/jettylib/javax.servlet.jar" />
+                <pathelement location="../../jetty/jettylib/jetty-util.jar" />
             </classpath>
         </depend>
     </target>
@@ -34,7 +35,7 @@
             debug="true" deprecation="on" source="1.5" target="1.5" 
             destdir="./build/obj" 
             includeAntRuntime="false"
-            classpath="../../../core/java/build/i2p.jar:../../jetty/jettylib/org.mortbay.jetty.jar:../../jetty/jettylib/javax.servlet.jar:../../ministreaming/java/build/mstreaming.jar" >
+            classpath="../../../core/java/build/i2p.jar:../../jetty/jettylib/org.mortbay.jetty.jar:../../jetty/jettylib/javax.servlet.jar:../../jetty/jettylib/jetty-util.jar:../../ministreaming/java/build/mstreaming.jar" >
             <compilerarg line="${javac.compilerargs}" />
         </javac>
     </target>
diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
index 7f3839ec943472a227612fe6bed573977a329500..7126bf687215877945c37f07239768c09b4be003 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
@@ -43,17 +43,16 @@ import org.klomp.snark.SnarkManager;
 import org.klomp.snark.Storage;
 import org.klomp.snark.TrackerClient;
 
-import org.mortbay.http.HttpResponse;
-import org.mortbay.jetty.servlet.Default;
-import org.mortbay.util.Resource;
-import org.mortbay.util.URI;
+import org.mortbay.jetty.servlet.DefaultServlet;
+import org.mortbay.resource.Resource;
+import org.mortbay.util.URIUtil;
 
 /**
  *  We extend Default instead of HTTPServlet so we can handle
  *  i2psnark/ file requests with http:// instead of the flaky and
  *  often-blocked-by-the-browser file://
  */
-public class I2PSnarkServlet extends Default {
+public class I2PSnarkServlet extends DefaultServlet {
     private I2PAppContext _context;
     private Log _log;
     private SnarkManager _manager;
@@ -99,13 +98,17 @@ public class I2PSnarkServlet extends Default {
      *  and we can't get any resources (like icons) out of the .war
      */
     @Override
-    protected Resource getResource(String pathInContext) throws IOException
+    public Resource getResource(String pathInContext)
     {
         if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") ||
             pathInContext.equals("/index.html") || pathInContext.startsWith("/_icons/"))
             return super.getResource(pathInContext);
         // files in the i2psnark/ directory
-        return _resourceBase.addPath(pathInContext);
+        try {
+            return _resourceBase.addPath(pathInContext);
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
     }
 
     /**
@@ -113,10 +116,11 @@ public class I2PSnarkServlet extends Default {
      *  @since 0.8.3
      */
     @Override
-    public void handleGet(HttpServletRequest request, HttpServletResponse response, String pathInContext, Resource resource, boolean endsWithSlash) throws ServletException, IOException {
-        if (resource.getName().startsWith("jar:file:"))
-            response.setHeader("Cache-Control", "max-age=86400");  // cache for a day
-        super.handleGet(request, response, pathInContext, resource, endsWithSlash);
+    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+////////////////////////////////////
+        //if (resource.getName().startsWith("jar:file:"))
+        //    response.setHeader("Cache-Control", "max-age=86400");  // cache for a day
+        super.doGet(request, response);
     }
 
     /**
@@ -144,7 +148,7 @@ public class I2PSnarkServlet extends Default {
         // since we are not overriding handle*(), do this here
         String method = req.getMethod();
         if (!(method.equals("GET") || method.equals("HEAD") || method.equals("POST"))) {
-            resp.sendError(HttpResponse.__405_Method_Not_Allowed);
+            resp.sendError(405);
             return;
         }
         _themePath = "/themes/snark/" + _manager.getTheme() + '/';
@@ -157,20 +161,20 @@ public class I2PSnarkServlet extends Default {
             if (path.endsWith("/")) {
                 // bypass the horrid Resource.getListHTML()
                 String pathInfo = req.getPathInfo();
-                String pathInContext = URI.addPaths(path, pathInfo);
+                String pathInContext = URIUtil.addPaths(path, pathInfo);
                 req.setCharacterEncoding("UTF-8");
                 resp.setCharacterEncoding("UTF-8");
                 resp.setContentType("text/html; charset=UTF-8");
                 Resource resource = getResource(pathInContext);
                 if (resource == null || (!resource.exists())) {
-                    resp.sendError(HttpResponse.__404_Not_Found);
+                    resp.sendError(404);
                 } else {
-                    String base = URI.addPaths(req.getRequestURI(), "/");
+                    String base = URIUtil.addPaths(req.getRequestURI(), "/");
                     String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null);
                     if (listing != null)
                         resp.getWriter().write(listing);
                     else // shouldn't happen
-                        resp.sendError(HttpResponse.__404_Not_Found);
+                        resp.sendError(404);
                 }
             } else {
                 super.service(req, resp);
@@ -1686,7 +1690,7 @@ public class I2PSnarkServlet extends Default {
         
         StringBuilder buf=new StringBuilder(4096);
         buf.append(DOCTYPE + "<HTML><HEAD><TITLE>");
-        String title = URI.decodePath(base);
+        String title = URIUtil.decodePath(base);
         if (title.startsWith("/i2psnark/"))
             title = title.substring("/i2psnark/".length());
 
@@ -1795,7 +1799,7 @@ public class I2PSnarkServlet extends Default {
             .append(_("Priority")).append("</th>");
         buf.append("</tr></thead>\n");
         buf.append("<tr><td colspan=\"" + (showPriority ? '4' : '3') + "\" class=\"ParentDir\"><A HREF=\"");
-        buf.append(URI.addPaths(base,"../"));
+        buf.append(URIUtil.addPaths(base,"../"));
         buf.append("\"><img alt=\"\" border=\"0\" src=\"" + _imgPath + "up.png\"> ")
             .append(_("Up to higher level directory")).append("</A></td></tr>\n");
 
@@ -1805,7 +1809,7 @@ public class I2PSnarkServlet extends Default {
         boolean showSaveButton = false;
         for (int i=0 ; i< ls.length ; i++)
         {   
-            String encoded=URI.encodePath(ls[i]);
+            String encoded=URIUtil.encodePath(ls[i]);
             // bugfix for I2P - Backport from Jetty 6 (zero file lengths and last-modified times)
             // http://jira.codehaus.org/browse/JETTY-361?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel#issue-tabs
             // See resource.diff attachment
@@ -1861,9 +1865,9 @@ public class I2PSnarkServlet extends Default {
                 }
             }
 
-            String path=URI.addPaths(base,encoded);
+            String path=URIUtil.addPaths(base,encoded);
             if (item.isDirectory() && !path.endsWith("/"))
-                path=URI.addPaths(path,"/");
+                path=URIUtil.addPaths(path,"/");
             String icon = toIcon(item);
 
             if (complete) {
diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/RunStandalone.java b/apps/i2psnark/java/src/org/klomp/snark/web/RunStandalone.java
index 2880676a2520f398483e300e6e9484cdfdf1b637..2bf912410113277db59bf9a0287db99111386ae3 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/RunStandalone.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/RunStandalone.java
@@ -31,6 +31,8 @@ public class RunStandalone {
         if (!workDirCreated)
             System.err.println("ERROR: Unable to create Jetty temporary work directory");
         
+        throw new RuntimeException("unsupported");
+/****
         try {
             _server = new Server("jetty-i2psnark.xml");
             // just blow up NPE if we don't have a context
@@ -39,13 +41,17 @@ public class RunStandalone {
         } catch (Exception e) {
             e.printStackTrace();
         }
+****/
     }
     
     public void stop() {
+        throw new RuntimeException("unsupported");
+/****
         try {
             _server.stop();
         } catch (InterruptedException ie) {
             ie.printStackTrace();
         }
+****/
     }
 }
diff --git a/apps/i2ptunnel/java/build.xml b/apps/i2ptunnel/java/build.xml
index 1b62279145de25669f48b9c6356ee25069488ba1..63885b85ed2730bbbeb9ab1ffea9a34fb76cad4d 100644
--- a/apps/i2ptunnel/java/build.xml
+++ b/apps/i2ptunnel/java/build.xml
@@ -52,13 +52,11 @@
     </target>
 
 
-    <!-- TODO: Move the web classes from the jar to the war - they are not part of the API
-      -  This will require sponge to rewrite some seedless stuff that uses it.
-     -->
+    <!-- The web classes are now in the war not the jar - they are not part of the API -->
     <target name="jar" depends="builddep, compile, jarUpToDate, listChangedFiles" unless="jar.uptodate" >
         <!-- set if unset -->
         <property name="workspace.changes.j.tr" value="" />
-        <jar destfile="./build/i2ptunnel.jar" basedir="./build/obj" includes="**/*.class">
+        <jar destfile="./build/i2ptunnel.jar" basedir="./build/obj" includes="**/*.class" excludes="**/EditBean.class **/IndexBean.class" >
             <manifest>
                 <attribute name="Main-Class" value="net.i2p.i2ptunnel.I2PTunnel" />
                 <attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
@@ -68,6 +66,7 @@
                 <attribute name="Workspace-Changes" value="${workspace.changes.j.tr}" />
             </manifest>
         </jar>
+        <jar destfile="./build/temp-beans.jar" basedir="./build/obj" includes="**/EditBean.class **/IndexBean.class" />
     </target>
 
     <target name="jarUpToDate">
@@ -129,9 +128,12 @@
         </exec>
     </target>
 
+    <!-- The web classes are now in the war not the jar - they are not part of the API -->
     <target name="war" depends="precompilejsp, bundle, warUpToDate, listChangedFiles2" unless="war.uptodate" > 
         <!-- set if unset -->
         <property name="workspace.changes.w.tr" value="" />
+        <copy file="build/obj/net/i2p/i2ptunnel/web/EditBean.class" todir="../jsp/WEB-INF/classes/net/i2p/i2ptunnel/web" />
+        <copy file="build/obj/net/i2p/i2ptunnel/web/IndexBean.class" todir="../jsp/WEB-INF/classes/net/i2p/i2ptunnel/web" />
         <war destfile="build/i2ptunnel.war" webxml="../jsp/web-out.xml"
              basedir="../jsp/" excludes="web.xml, web-fragment.xml, web-out.xml, **/*.java, *.jsp">
             <manifest>
@@ -171,11 +173,14 @@
                 <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/ant.jar" />
+                <pathelement location="../../jetty/jettylib/jsp-api.jar" />
+                <pathelement location="${ant.home}/lib/ant.jar" />
                 <pathelement location="build/i2ptunnel.jar" />
+                <pathelement location="build/temp-beans.jar" />
             </classpath>
             <arg value="-d" />
             <arg value="../jsp/WEB-INF/classes" />
+            <arg value="-v" />
             <arg value="-p" />
             <arg value="net.i2p.i2ptunnel.jsp" />
             <arg value="-webinc" />
@@ -192,7 +197,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="build/i2ptunnel.jar" />
+                <pathelement location="build/temp-beans.jar" />
             </classpath>
         </javac>
         <copy file="../jsp/web.xml" tofile="../jsp/web-out.xml" />
diff --git a/apps/i2ptunnel/jsp/edit.jsp b/apps/i2ptunnel/jsp/edit.jsp
index e35f23c0fb2cd1909c9334f4d16325766de912d3..236e600f0b8dc6dea569616eeebc8c0265740b57 100644
--- a/apps/i2ptunnel/jsp/edit.jsp
+++ b/apps/i2ptunnel/jsp/edit.jsp
@@ -2,6 +2,7 @@
     // NOTE: Do the header carefully so there is no whitespace before the <?xml... line
 
 %><%@page pageEncoding="UTF-8"
+%><%@page trimDirectiveWhitespaces="true"
 %><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
 %><% 
 String tun = request.getParameter("tunnel");
diff --git a/apps/i2ptunnel/jsp/editClient.jsp b/apps/i2ptunnel/jsp/editClient.jsp
index ad2d14aa2ccb7d52a5c63f9d4ec7f9035b20d930..fd279fdc351dbb2ba66292c028eb28f8f4f4a6d1 100644
--- a/apps/i2ptunnel/jsp/editClient.jsp
+++ b/apps/i2ptunnel/jsp/editClient.jsp
@@ -1,4 +1,6 @@
-<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"%><?xml version="1.0" encoding="UTF-8"?>
+<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
+%><%@page trimDirectiveWhitespaces="true"
+%><?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
 <jsp:useBean class="net.i2p.i2ptunnel.web.Messages" id="intl" scope="request" />
diff --git a/apps/i2ptunnel/jsp/editServer.jsp b/apps/i2ptunnel/jsp/editServer.jsp
index 45e96f73d0000fdc7fa638124ab6a93325bd2e2d..3f6560c16b40aca0767735afc715b853d7a9fe8b 100644
--- a/apps/i2ptunnel/jsp/editServer.jsp
+++ b/apps/i2ptunnel/jsp/editServer.jsp
@@ -1,4 +1,6 @@
-<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"%><?xml version="1.0" encoding="UTF-8"?>
+<%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
+%><%@page trimDirectiveWhitespaces="true"
+%><?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <jsp:useBean class="net.i2p.i2ptunnel.web.EditBean" id="editBean" scope="request" />
 <jsp:useBean class="net.i2p.i2ptunnel.web.Messages" id="intl" scope="request" />
diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp
index 4f790b940acca08538f482ec2d3d233d1d3be8aa..3f31bdd05b94a282b79e2ec6e622dec4e3f93d2e 100644
--- a/apps/i2ptunnel/jsp/index.jsp
+++ b/apps/i2ptunnel/jsp/index.jsp
@@ -6,6 +6,7 @@
         request.setCharacterEncoding("UTF-8");
 
 %><%@page pageEncoding="UTF-8"
+%><%@page trimDirectiveWhitespaces="true"
 %><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.IndexBean"
 %><?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
diff --git a/apps/jetty/apache-tomcat-deployer/NOTICE b/apps/jetty/apache-tomcat-deployer/NOTICE
new file mode 100644
index 0000000000000000000000000000000000000000..c44c35de8848e6dbe18ff5477c67694b74b19042
--- /dev/null
+++ b/apps/jetty/apache-tomcat-deployer/NOTICE
@@ -0,0 +1,16 @@
+Apache Tomcat
+Copyright 1999-2011 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+The Windows Installer is built with the Nullsoft
+Scriptable Install Sysem (NSIS), which is
+open source software.  The original software and
+related information is available at
+http://nsis.sourceforge.net.
+
+Java compilation software for JSP pages is provided by Eclipse, 
+which is open source software.  The original software and 
+related information is available at
+http://www.eclipse.org.
diff --git a/apps/jetty/apache-tomcat-deployer/README-i2p.txt b/apps/jetty/apache-tomcat-deployer/README-i2p.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dd398113861368996037f52c137ce55db6445a44
--- /dev/null
+++ b/apps/jetty/apache-tomcat-deployer/README-i2p.txt
@@ -0,0 +1,14 @@
+This is Apache Tomcat 6.x, supporting Servlet 2.5 and JSP 2.1.
+The Glassfish JSP 2.1 bundled in Jetty 6 is way too old.
+
+Retrieved from the file
+	apache-tomcat-6.0.35-deployer.tar.gz
+
+minus the following files and directores:
+
+build.xml
+deployer-howto.html
+images/*
+lib/catalina*
+LICENSE (see ../../../licenses/LICENSE-Apache2.0.txt, it's also inside every jar)
+RELEASE-NOTES
diff --git a/apps/jetty/apache-tomcat-deployer/lib/el-api.jar b/apps/jetty/apache-tomcat-deployer/lib/el-api.jar
new file mode 100644
index 0000000000000000000000000000000000000000..3518f7d76b3b83fc0ae8f660079439d7c68a27e0
Binary files /dev/null and b/apps/jetty/apache-tomcat-deployer/lib/el-api.jar differ
diff --git a/apps/jetty/apache-tomcat-deployer/lib/jasper-el.jar b/apps/jetty/apache-tomcat-deployer/lib/jasper-el.jar
new file mode 100644
index 0000000000000000000000000000000000000000..23876732eeb471c2d620ab485745086e5b9e1269
Binary files /dev/null and b/apps/jetty/apache-tomcat-deployer/lib/jasper-el.jar differ
diff --git a/apps/jetty/apache-tomcat-deployer/lib/jasper.jar b/apps/jetty/apache-tomcat-deployer/lib/jasper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..e64284f4f625353e50e1f2956261e1fb515de529
Binary files /dev/null and b/apps/jetty/apache-tomcat-deployer/lib/jasper.jar differ
diff --git a/apps/jetty/apache-tomcat-deployer/lib/jsp-api.jar b/apps/jetty/apache-tomcat-deployer/lib/jsp-api.jar
new file mode 100644
index 0000000000000000000000000000000000000000..6ef6574cea37f17321800b1921f18e6ab63d47fd
Binary files /dev/null and b/apps/jetty/apache-tomcat-deployer/lib/jsp-api.jar differ
diff --git a/apps/jetty/apache-tomcat-deployer/lib/servlet-api.jar b/apps/jetty/apache-tomcat-deployer/lib/servlet-api.jar
new file mode 100644
index 0000000000000000000000000000000000000000..1bf50af6e504fff15c5a3ad31b773b12aedee16d
Binary files /dev/null and b/apps/jetty/apache-tomcat-deployer/lib/servlet-api.jar differ
diff --git a/apps/jetty/apache-tomcat-deployer/lib/tomcat-juli.jar b/apps/jetty/apache-tomcat-deployer/lib/tomcat-juli.jar
new file mode 100644
index 0000000000000000000000000000000000000000..07571768cafb3948f98eb0b1d3ac5fa01393875d
Binary files /dev/null and b/apps/jetty/apache-tomcat-deployer/lib/tomcat-juli.jar differ
diff --git a/apps/jetty/build.xml b/apps/jetty/build.xml
index e686e364a73c17db730bbcf1959f1bc4f5f3ca05..7d4c824cf55f67736028b37961a2a3fd74f7c34b 100644
--- a/apps/jetty/build.xml
+++ b/apps/jetty/build.xml
@@ -1,12 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project basedir="." default="all" name="jetty">
 
-    <property name="jetty.base" value="jetty-5.1.15" />
-    <property name="jetty.sha1" value="3a7a3de50f86f0cdb23c33aec632ea7f44132c5e" />
-    <property name="jetty.filename" value="${jetty.base}.tgz" />
-    <property name="jetty.url" value="http://dist.codehaus.org/jetty/jetty-5.1.x/${jetty.filename}" />
+    <property name="jetty.ver" value="6.1.26" />
+    <property name="jetty.base" value="jetty-${jetty.ver}" />
+    <property name="jetty.sha1" value="9485913f1a1945a849a90f1a34853d22350bc524" />
+    <property name="jetty.filename" value="${jetty.base}.zip" />
+    <property name="jetty.url" value="http://dist.codehaus.org/jetty/${jetty.base}/${jetty.filename}" />
     <property name="verified.filename" value="verified.txt" />
     <property name="javac.compilerargs" value="" />
+    <property name="tomcat.lib" value="apache-tomcat-deployer/lib" />
 
     <target name="all" depends="build" />
 
@@ -64,26 +66,75 @@
     </target>
 
     <target name="extractJettylib" unless="jetty.zip.extracted" >
+      <!-- for .tgz -->
+      <!--
         <gunzip src="${jetty.filename}" dest="jetty.tar" />
         <untar src="jetty.tar" dest="." />
+      -->
+      <!-- for .zip -->
+        <unzip src="${jetty.filename}" dest="." />
         <mkdir dir="jettylib" />
-        <copy todir="jettylib" preservelastmodified="true" >
-            <fileset dir="${jetty.base}/lib">
-                <include name="*.jar" />
-            </fileset>
-            <fileset dir="${jetty.base}/ext">
-                <include name="ant.jar" />
-                <include name="commons-el.jar" />
-                <include name="commons-logging.jar" />
-                <include name="jasper-compiler.jar" />
-                <include name="jasper-runtime.jar" />
-            </fileset>
-        </copy>
+      <!-- We copy everything to names without the version numbers so we
+           can update them later. Where there was something similar in Jetty 5,
+           we use the same names so they will overwrite the Jetty 5 jar on upgrade.
+           Otherwise we use the same name as the symlink in Ubuntu /usr/share/java.
+           Reasons for inclusion:
+              start.jar: Needed for clients.config startup of eepsites
+              jetty-util-xxx.jar: LifeCycle (base class for stuff), URIUtil (used in i2psnark)
+              jetty-sslengine-xxx.jar: SSL NIO Connector for console
+              jetty-java5-threadpool-xxx.jar: Concurrent thread pool for eepsite
+              glassfish 2.1: Not used, too old, see Tomcat below.
+              jetty-rewrite-handler: Not used by I2P, but only 20KB and could be useful for eepsites
+              jetty-management: Not used by I2P, but only 34KB and could be useful for eepsites, and we bundled it with Jetty 5
+              All of these are available in the Ubuntu packages libjetty-java and libjetty-extra-java
+        -->
+        <copy preservelastmodified="true" file="${jetty.base}/start.jar" tofile="jettylib/jetty-start.jar" />
+        <copy file="${jetty.base}/lib/${jetty.base}.jar" tofile="jettylib/org.mortbay.jetty.jar" />
+        <copy preservelastmodified="true" file="${jetty.base}/lib/jetty-util-${jetty.ver}.jar" tofile="jettylib/jetty-util.jar" />
+        <copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-java5-threadpool-${jetty.ver}.jar" tofile="jettylib/jetty-java5-threadpool.jar" />
+        <copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-rewrite-handler-${jetty.ver}.jar" tofile="jettylib/jetty-rewrite-handler.jar" />
+        <copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-sslengine-${jetty.ver}.jar" tofile="jettylib/jetty-sslengine.jar" />
+        <copy preservelastmodified="true" file="${jetty.base}/lib/management/jetty-management-${jetty.ver}.jar" tofile="jettylib/org.mortbay.jmx.jar" />
         <delete file="jetty.tar" />
         <delete dir="${jetty.base}" />
+        <!-- commons-logging.jar not in Jetty 6 but we have it in launch4j so copy it over, we need it
+             for org.apache.jasper.JspC compiler
+          -->
+        <copy preservelastmodified="true" file="../../installer/lib/launch4j/lib/commons-logging.jar" todir="jettylib/" />
+        <ant target="copyTomcatLib" />
+    </target>
+
+    <!-- Tomcat.
+         The glassfish jars bundled in Jetty 6 are way too old.
+         For compatibility with very old I2P installations where the classpath
+         was set individually in wrapper.config, we rename and combine the jars as follows:
+         jasper.jar : jasper-runtime.jar
+         jasper-el.jar + el-api.jar : commons-el.jar
+         servlet-api.jar + jsp-api.jar : javax.servlet.jar
+         tomcat-juli.jar : commons-logging.jar
+         empty jar : jasper-compiler.jar
+         Also, take NOTICE and LICENSE out of each one, we bundle those separately.
+     -->
+    <target name="copyTomcatLib" >
+        <jar destfile="jettylib/jasper-runtime.jar" >
+            <zipfileset excludes="META-INF/LICENSE META-INF/NOTICE" src="${tomcat.lib}/jasper.jar" />
+        </jar>
+        <jar destfile="jettylib/commons-el.jar" duplicate="preserve" >
+            <zipfileset excludes="META-INF/LICENSE META-INF/NOTICE" src="${tomcat.lib}/jasper-el.jar" />
+            <zipfileset excludes="META-INF/**/*" src="${tomcat.lib}/el-api.jar" />
+        </jar>
+        <jar destfile="jettylib/javax.servlet.jar" duplicate="preserve" >
+            <zipfileset excludes="META-INF/LICENSE META-INF/NOTICE" src="${tomcat.lib}/servlet-api.jar" />
+            <zipfileset excludes="META-INF/**/*" src="${tomcat.lib}/jsp-api.jar" />
+        </jar>
+        <jar destfile="jettylib/commons-logging.jar" >
+            <zipfileset excludes="META-INF/LICENSE META-INF/NOTICE" src="${tomcat.lib}/tomcat-juli.jar" />
+        </jar>
+        <jar destfile="jettylib/jasper-compiler.jar" />
     </target>
 
     <target name="build" depends="jar" />
+
     <target name="builddep" />
     <target name="compile" depends="builddep, ensureJettylib" >
         <mkdir dir="./build" />
@@ -93,7 +144,7 @@
             debug="true" source="1.5" target="1.5" 
             destdir="./build/obj" 
             includeAntRuntime="false"
-            classpath="./jettylib/commons-logging.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar" >
+            classpath="../../core/java/build/i2p.jar:./jettylib/commons-logging.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar:./jettylib/jetty-util.jar" >
             <compilerarg line="${javac.compilerargs}" />
         </javac>
     </target>
@@ -112,10 +163,14 @@
         </exec>
     </target>
 
+    <!-- With Jetty 5 we replaced classes in the jar, but with Jetty 6 we
+         put our stuff in its own jar so we can work with standard Jetty 6 packages
+      -->
     <target name="jar" depends="compile, jarUpToDate, listChangedFiles" unless="jar.uptodate" >
         <!-- set if unset -->
         <property name="workspace.changes.tr" value="" />
-        <jar destfile="./jettylib/org.mortbay.jetty.jar" basedir="./build/obj" includes="**/*.class" update="true" >
+        <copy todir="build/obj" file="resources/log4j.properties" />
+        <jar destfile="./jettylib/jetty-i2p.jar" basedir="./build/obj" includes="**/*.class log4j.properties" >
             <manifest>
                 <attribute name="Build-Date" value="${build.timestamp}" />
                 <attribute name="Base-Revision" value="${workspace.version}" />
@@ -125,7 +180,7 @@
     </target>    
 
     <target name="jarUpToDate">
-        <uptodate property="jar.uptodate" targetfile="jettylib/org.mortbay.jetty.jar" >
+        <uptodate property="jar.uptodate" targetfile="jettylib/jetty-i2p.jar" >
             <srcfiles dir= "build/obj" includes="**/*.class" />
         </uptodate>
         <condition property="shouldListChanges" >
diff --git a/apps/jetty/java/src/net/i2p/jetty/I2PLogger.java b/apps/jetty/java/src/net/i2p/jetty/I2PLogger.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e5fe91d2cef7d12dee1f171f91c60d6c87a612b
--- /dev/null
+++ b/apps/jetty/java/src/net/i2p/jetty/I2PLogger.java
@@ -0,0 +1,175 @@
+// ========================================================================
+// Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at 
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================================================================
+
+package net.i2p.jetty;
+
+import net.i2p.I2PAppContext;
+import net.i2p.util.Log;
+
+import org.mortbay.jetty.Server;
+import org.mortbay.log.Logger;
+
+/**
+ * Modified from Jetty 6.1.26 StdErrLog.java and Slf4jLog.java
+ *
+ * Usage: org.mortbay.log.Log.setLog(new I2PLogger(ctx));
+ *
+ * @since Jetty 6
+ */
+public class I2PLogger implements Logger
+{    
+    private final Log _log;
+    
+    StringBuilder _buffer = new StringBuilder();
+    
+    public I2PLogger()
+    {
+        this(I2PAppContext.getGlobalContext());
+    }
+    
+    public I2PLogger(I2PAppContext ctx)
+    {
+        _log = ctx.logManager().getLog(Server.class);
+        if (System.getProperty("DEBUG") != null)
+            setDebugEnabled(true);
+    }
+    
+    public boolean isDebugEnabled()
+    {
+        return _log.shouldLog(Log.DEBUG);
+    }
+    
+    public void setDebugEnabled(boolean enabled)
+    {
+        if (enabled)
+            _log.setMinimumPriority(Log.DEBUG);
+        else
+            // LogManager.getDefaultLimit() returns a String, not worth it
+            _log.setMinimumPriority(Log.ERROR);
+    }
+    
+    public void info(String msg,Object arg0, Object arg1)
+    {
+        if (arg0 == null && arg1 == null) {
+            _log.info(msg);
+        } else if (_log.shouldLog(Log.INFO)) {
+            synchronized(_buffer) {
+                format(msg,arg0,arg1);
+                _log.info(_buffer.toString());
+            }
+        }
+    }
+    
+    public void debug(String msg,Throwable th)
+    {
+        _log.debug(msg,th);
+    }
+    
+    public void debug(String msg,Object arg0, Object arg1)
+    {
+        if (arg0 == null && arg1 == null) {
+            _log.debug(msg);
+        } else if (_log.shouldLog(Log.DEBUG)) {
+            synchronized(_buffer) {
+                format(msg,arg0,arg1);
+                _log.debug(_buffer.toString());
+            }
+        }
+    }
+    
+    public void warn(String msg,Object arg0, Object arg1)
+    {
+        if (arg0 == null && arg1 == null) {
+            _log.warn(msg);
+        } else if (_log.shouldLog(Log.WARN)) {
+            synchronized(_buffer) {
+                format(msg,arg0,arg1);
+                _log.warn(_buffer.toString());
+            }
+        }
+    }
+    
+    public void warn(String msg, Throwable th)
+    {
+        // This doesn't cover ClassNotFoundException, etc.
+        //if (th instanceof RuntimeException || th instanceof Error)
+            _log.error(msg, th);
+        //else
+        //    _log.warn(msg,th);
+    }
+    
+    private void format(String msg, Object arg0, Object arg1)
+    {
+        _buffer.setLength(0);
+        int i0=msg==null?-1:msg.indexOf("{}");
+        int i1=i0<0?-1:msg.indexOf("{}",i0+2);
+        
+        if (i0>=0)
+        {
+            format(msg.substring(0,i0));
+            format(String.valueOf(arg0==null?"null":arg0));
+            
+            if (i1>=0)
+            {
+                format(msg.substring(i0+2,i1));
+                format(String.valueOf(arg1==null?"null":arg1));
+                format(msg.substring(i1+2));
+            }
+            else
+            {
+                format(msg.substring(i0+2));
+                if (arg1!=null)
+                {
+                    _buffer.append(' ');
+                    format(String.valueOf(arg1));
+                }
+            }
+        }
+        else
+        {
+            format(msg);
+            if (arg0!=null)
+            {
+                _buffer.append(' ');
+                format(String.valueOf(arg0));
+            }
+            if (arg1!=null)
+            {
+                _buffer.append(' ');
+                format(String.valueOf(arg1));
+            }
+        }
+    }
+    
+    private void format(String msg)
+    {
+        if (msg == null)
+            _buffer.append("null");
+        else
+            _buffer.append(msg);
+    }
+
+    public Logger getLogger(String name)
+    {
+            return this;
+    }
+    
+    @Override
+    public String toString()
+    {
+        return "I2PLogger";
+    }
+    
+
+}
diff --git a/apps/jetty/java/src/net/i2p/jetty/I2PRequestLog.java b/apps/jetty/java/src/net/i2p/jetty/I2PRequestLog.java
new file mode 100644
index 0000000000000000000000000000000000000000..6aa001146f75ed2d543166396870907775ffb702
--- /dev/null
+++ b/apps/jetty/java/src/net/i2p/jetty/I2PRequestLog.java
@@ -0,0 +1,513 @@
+//========================================================================
+//Copyright 1997-2006 Mort Bay Consulting Pty. Ltd.
+//------------------------------------------------------------------------
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//http://www.apache.org/licenses/LICENSE-2.0
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+//========================================================================
+
+package net.i2p.jetty; 
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import javax.servlet.http.Cookie;
+
+import org.mortbay.component.AbstractLifeCycle;
+import org.mortbay.jetty.HttpHeaders;
+import org.mortbay.jetty.Request;
+import org.mortbay.jetty.RequestLog;
+import org.mortbay.jetty.Response;
+import org.mortbay.jetty.servlet.PathMap;
+import org.mortbay.log.Log;
+import org.mortbay.util.DateCache;
+import org.mortbay.util.RolloverFileOutputStream;
+import org.mortbay.util.StringUtil;
+import org.mortbay.util.TypeUtil;
+import org.mortbay.util.Utf8StringBuffer;
+
+/** 
+ * This {@link RequestLog} implementation outputs logs in the pseudo-standard NCSA common log format.
+ * Configuration options allow a choice between the standard Common Log Format (as used in the 3 log format)
+ * and the Combined Log Format (single log format).
+ * This log format can be output by most web servers, and almost all web log analysis software can understand
+ *  these formats.
+ *
+ * ** I2P Mods **
+ *
+ * For Jetty 5, this extended NCSARequestLog to
+ * override log() to put in the requestor's destination hash,
+ * instead of 127.0.0.1,
+ * which is placed in the X-I2P-DestHash field in the request headers
+ * by I2PTunnelHTTPServer.
+ * But we also had to modify NCSARequestLog to do so, to change private
+ * fields to protected.
+ *
+ * So that we will work with system Jetty 6 packages, we just copy the whole thing
+ * and modify log() as required.
+ * We leave the package as org.mortbay.http for compatibility with old
+ * jetty.xml files.
+ *
+ * @author Greg Wilkins
+ * @author Nigel Canonizado
+ * 
+ */
+public class I2PRequestLog extends AbstractLifeCycle implements RequestLog
+{
+    private String _filename;
+    private boolean _extended;
+    private boolean _append;
+    private int _retainDays;
+    private boolean _closeOut;
+    private boolean _preferProxiedForAddress;
+    private String _logDateFormat="dd/MMM/yyyy:HH:mm:ss Z";
+    private String _filenameDateFormat = null;
+    private Locale _logLocale = Locale.getDefault();
+    private String _logTimeZone = "GMT";
+    private String[] _ignorePaths;
+    private boolean _logLatency = false;
+    private boolean _logCookies = false;
+    private boolean _logServer = false;
+    
+    private transient OutputStream _out;
+    private transient OutputStream _fileOut;
+    private transient DateCache _logDateCache;
+    private transient PathMap _ignorePathMap;
+    private transient Writer _writer;
+    private transient ArrayList _buffers;
+    private transient char[] _copy;
+
+    
+    public I2PRequestLog()
+    {
+        _extended = true;
+        _append = true;
+        _retainDays = 31;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @param filename The filename for the request log. This may be in the format expected by {@link RolloverFileOutputStream}
+     */
+    public I2PRequestLog(String filename)
+    {
+        _extended = true;
+        _append = true;
+        _retainDays = 31;
+        setFilename(filename);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @param filename The filename for the request log. This may be in the format expected by {@link RolloverFileOutputStream}
+     */
+    public void setFilename(String filename)
+    {
+        if (filename != null) 
+        {
+            filename = filename.trim();
+            if (filename.length() == 0)
+                filename = null;
+        }    
+        _filename = filename;
+    }
+    
+    public String getFilename() 
+    {
+        return _filename;
+    }
+    
+    public String getDatedFilename()
+    {
+        if (_fileOut instanceof RolloverFileOutputStream)
+            return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
+        return null;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @param format Format for the timestamps in the log file.  If not set,
+     * the pre-formated request timestamp is used.
+     */
+    public void setLogDateFormat(String format)
+    {
+        _logDateFormat = format;
+    }
+    
+    public String getLogDateFormat() 
+    {
+        return _logDateFormat;
+    }
+    
+    public void setLogLocale(Locale logLocale)
+    {
+        _logLocale = logLocale;
+    }
+    
+    public Locale getLogLocale()
+    {
+        return _logLocale;
+    }
+    
+    public void setLogTimeZone(String tz) 
+    {
+        _logTimeZone = tz;
+    }
+    
+    public String getLogTimeZone()
+    {
+        return _logTimeZone;
+    }
+    
+    public void setRetainDays(int retainDays)
+    {
+        _retainDays = retainDays;
+    }
+    
+    public int getRetainDays()
+    {
+        return _retainDays;
+    }
+    
+    public void setExtended(boolean extended)
+    {
+        _extended = extended;
+    }
+    
+    public boolean isExtended() 
+    {
+        return _extended;
+    }
+    
+    public void setAppend(boolean append)
+    {
+        _append = append;
+    }
+    
+    public boolean isAppend()
+    {
+        return _append;
+    }
+    
+    public void setIgnorePaths(String[] ignorePaths) 
+    {
+        _ignorePaths = ignorePaths;
+    }
+    
+    public String[] getIgnorePaths()
+    {
+        return _ignorePaths;
+    }
+    
+    public void setLogCookies(boolean logCookies) 
+    {
+        _logCookies = logCookies;
+    }
+    
+    public boolean getLogCookies()
+    {
+        return _logCookies;
+    }
+
+    public boolean getLogServer()
+    {
+        return _logServer;
+    }
+
+    public void setLogServer(boolean logServer)
+    {
+        _logServer=logServer;
+    }
+    
+    public void setLogLatency(boolean logLatency) 
+    {
+        _logLatency = logLatency;
+    }
+    
+    public boolean getLogLatency()
+    {
+        return _logLatency;
+    }
+    
+    public void setPreferProxiedForAddress(boolean preferProxiedForAddress)
+    {
+        _preferProxiedForAddress = preferProxiedForAddress;
+    }
+
+    /* ------------------------------------------------------------ */
+    public void log(Request request, Response response)
+    {
+        if (!isStarted()) 
+            return;
+        
+        try 
+        {
+            if (_ignorePathMap != null && _ignorePathMap.getMatch(request.getRequestURI()) != null)
+                return;
+            
+            if (_fileOut == null)
+                return;
+
+            Utf8StringBuffer u8buf;
+            StringBuffer buf;
+            synchronized(_writer)
+            {
+                int size=_buffers.size();
+                u8buf = size==0?new Utf8StringBuffer(160):(Utf8StringBuffer)_buffers.remove(size-1);
+                buf = u8buf.getStringBuffer();
+            }
+            
+            synchronized(buf) // for efficiency until we can use StringBuilder
+            {
+                if (_logServer)
+                {
+                    buf.append(request.getServerName());
+                    buf.append(' ');
+                }
+
+                String addr = null;
+                if (_preferProxiedForAddress) 
+                {
+                    addr = request.getHeader(HttpHeaders.X_FORWARDED_FOR);
+                }
+
+                if (addr == null) {
+                    // TODO offer B32 option
+                    addr = request.getHeader("X-I2P-DestHash");
+                    if(addr != null)
+                        addr += ".i2p";
+                    else
+                        addr = request.getRemoteAddr();
+                }
+
+                buf.append(addr);
+                buf.append(" - ");
+                String user = request.getRemoteUser();
+                buf.append((user == null)? " - " : user);
+                buf.append(" [");
+                if (_logDateCache!=null)
+                    buf.append(_logDateCache.format(request.getTimeStamp()));
+                else
+                    buf.append(request.getTimeStampBuffer().toString());
+                    
+                buf.append("] \"");
+                buf.append(request.getMethod());
+                buf.append(' ');
+                
+                request.getUri().writeTo(u8buf);
+                
+                buf.append(' ');
+                buf.append(request.getProtocol());
+                buf.append("\" ");
+                int status = response.getStatus();
+                if (status<=0)
+                    status=404;
+                buf.append((char)('0'+((status/100)%10)));
+                buf.append((char)('0'+((status/10)%10)));
+                buf.append((char)('0'+(status%10)));
+
+
+                long responseLength=response.getContentCount();
+                if (responseLength >=0)
+                {
+                    buf.append(' ');
+                    if (responseLength > 99999)
+                        buf.append(Long.toString(responseLength));
+                    else 
+                    {
+                        if (responseLength > 9999)
+                            buf.append((char)('0' + ((responseLength / 10000)%10)));
+                        if (responseLength > 999)
+                            buf.append((char)('0' + ((responseLength /1000)%10)));
+                        if (responseLength > 99)
+                            buf.append((char)('0' + ((responseLength / 100)%10)));
+                        if (responseLength > 9)
+                            buf.append((char)('0' + ((responseLength / 10)%10)));
+                        buf.append((char)('0' + (responseLength)%10));
+                    }
+                    buf.append(' ');
+                }
+                else 
+                    buf.append(" - ");
+
+            }
+
+            if (!_extended && !_logCookies && !_logLatency)
+            {
+                synchronized(_writer)
+                {
+                    buf.append(StringUtil.__LINE_SEPARATOR);
+                    int l=buf.length();
+                    if (l>_copy.length)
+                        l=_copy.length;  
+                    buf.getChars(0,l,_copy,0); 
+                    _writer.write(_copy,0,l);
+                    _writer.flush();
+                    u8buf.reset();
+                    _buffers.add(u8buf); 
+                }
+            }
+            else
+            {
+                synchronized(_writer)
+                {
+                    int l=buf.length();
+                    if (l>_copy.length)
+                        l=_copy.length;  
+                    buf.getChars(0,l,_copy,0); 
+                    _writer.write(_copy,0,l);
+                    u8buf.reset();
+                    _buffers.add(u8buf); 
+
+                    // TODO do outside synchronized scope
+                    if (_extended)
+                        logExtended(request, response, _writer);
+
+                    // TODO do outside synchronized scope
+                    if (_logCookies)
+                    {
+                        Cookie[] cookies = request.getCookies(); 
+                        if (cookies == null || cookies.length == 0)
+                            _writer.write(" -");
+                        else
+                        {
+                            _writer.write(" \"");
+                            for (int i = 0; i < cookies.length; i++) 
+                            {
+                                if (i != 0)
+                                    _writer.write(';');
+                                _writer.write(cookies[i].getName());
+                                _writer.write('=');
+                                _writer.write(cookies[i].getValue());
+                            }
+                            _writer.write('\"');
+                        }
+                    }
+
+                    if (_logLatency)
+                    {
+                        _writer.write(' ');
+                        _writer.write(TypeUtil.toString(System.currentTimeMillis() - request.getTimeStamp()));
+                    }
+
+                    _writer.write(StringUtil.__LINE_SEPARATOR);
+                    _writer.flush();
+                }
+            }
+        } 
+        catch (IOException e) 
+        {
+            Log.warn(e);
+        }
+        
+    }
+
+    /* ------------------------------------------------------------ */
+    protected void logExtended(Request request, 
+                               Response response, 
+                               Writer writer) throws IOException 
+    {
+        String referer = request.getHeader(HttpHeaders.REFERER);
+        if (referer == null) 
+            writer.write("\"-\" ");
+        else 
+        {
+            writer.write('"');
+            writer.write(referer);
+            writer.write("\" ");
+        }
+        
+        String agent = request.getHeader(HttpHeaders.USER_AGENT);
+        if (agent == null)
+            writer.write("\"-\" ");
+        else
+        {
+            writer.write('"');
+            writer.write(agent);
+            writer.write('"');
+        }          
+    }
+
+    /* ------------------------------------------------------------ */
+    protected void doStart() throws Exception
+    {
+        if (_logDateFormat!=null)
+        {       
+            _logDateCache = new DateCache(_logDateFormat, _logLocale);
+            _logDateCache.setTimeZoneID(_logTimeZone);
+        }
+        
+        if (_filename != null) 
+        {
+            _fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(_logTimeZone),_filenameDateFormat,null);
+            _closeOut = true;
+            Log.info("Opened "+getDatedFilename());
+        }
+        else 
+            _fileOut = System.err;
+        
+        _out = _fileOut;
+        
+        if (_ignorePaths != null && _ignorePaths.length > 0)
+        {
+            _ignorePathMap = new PathMap();
+            for (int i = 0; i < _ignorePaths.length; i++) 
+                _ignorePathMap.put(_ignorePaths[i], _ignorePaths[i]);
+        }
+        else 
+            _ignorePathMap = null;
+        
+        _writer = new OutputStreamWriter(_out);
+        _buffers = new ArrayList();
+        _copy = new char[1024];
+        super.doStart();
+    }
+
+    /* ------------------------------------------------------------ */
+    protected void doStop() throws Exception
+    {
+        super.doStop();
+        try {if (_writer != null) _writer.flush();} catch (IOException e) {Log.ignore(e);}
+        if (_out != null && _closeOut) 
+            try {_out.close();} catch (IOException e) {Log.ignore(e);}
+            
+        _out = null;
+        _fileOut = null;
+        _closeOut = false;
+        _logDateCache = null;
+        _writer = null;
+        _buffers = null;
+        _copy = null;
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
+     * @return the log File Date Format
+     */
+    public String getFilenameDateFormat()
+    {
+        return _filenameDateFormat;
+    }
+
+    /* ------------------------------------------------------------ */
+    /** Set the log file date format.
+     * see RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)
+     * @param logFileDateFormat the logFileDateFormat to pass to RolloverFileOutputStream
+     */
+    public void setFilenameDateFormat(String logFileDateFormat)
+    {
+        _filenameDateFormat=logFileDateFormat;
+    }
+
+}
diff --git a/apps/jetty/java/src/org/mortbay/http/HttpContext.java b/apps/jetty/java/src/org/mortbay/http/HttpContext.java
deleted file mode 100644
index 1ae1a08b6ef6748736519fd16afab4819b43e9f5..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/http/HttpContext.java
+++ /dev/null
@@ -1,2198 +0,0 @@
-// ========================================================================
-// $Id: HttpContext.java,v 1.136 2006/02/21 09:47:43 gregwilkins Exp $
-// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-
-package org.mortbay.http;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Serializable;
-import java.net.InetAddress;
-import java.net.MalformedURLException;
-import java.net.Socket;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.UnknownHostException;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.Permissions;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import org.apache.commons.logging.Log;
-import org.mortbay.log.LogFactory;
-import org.mortbay.http.ResourceCache.ResourceMetaData;
-import org.mortbay.http.handler.ErrorPageHandler;
-import org.mortbay.util.Container;
-import org.mortbay.util.EventProvider;
-import org.mortbay.util.IO;
-import org.mortbay.util.LazyList;
-import org.mortbay.util.LifeCycle;
-import org.mortbay.util.LogSupport;
-import org.mortbay.util.MultiException;
-import org.mortbay.util.Resource;
-import org.mortbay.util.URI;
-
-
-/* ------------------------------------------------------------ */
-/** Context for a collection of HttpHandlers.
- * HTTP Context provides an ordered container for HttpHandlers
- * that share the same path prefix, filebase, resourcebase and/or
- * classpath.
- * <p>
- * A HttpContext is analagous to a ServletContext in the
- * Servlet API, except that it may contain other types of handler
- * other than servlets.
- * <p>
- * A ClassLoader is created for the context and it uses
- * Thread.currentThread().getContextClassLoader(); as it's parent loader.
- * The class loader is initialized during start(), when a derived
- * context calls initClassLoader() or on the first call to loadClass()
- * <p>
- *
- * <B>Note. that order is important when configuring a HttpContext.
- * For example, if resource serving is enabled before servlets, then resources
- * take priority.</B>
- *
- * @see HttpServer
- * @see HttpHandler
- * @see org.mortbay.jetty.servlet.ServletHttpContext
- * @version $Id: HttpContext.java,v 1.136 2006/02/21 09:47:43 gregwilkins Exp $
- * @author Greg Wilkins (gregw)
- */
-public class HttpContext extends Container
-                         implements LifeCycle,
-                                    HttpHandler,
-                                    EventProvider,
-                                    Serializable
-{
-    private static Log log = LogFactory.getLog(HttpContext.class);
-
-    /* ------------------------------------------------------------ */
-    /** File class path attribute.
-     * If this name is set as a context init parameter, then the attribute
-     * name given will be used to set the file classpath for the context as a
-     * context attribute.
-     */
-    public final static String __fileClassPathAttr=
-        "org.mortbay.http.HttpContext.FileClassPathAttribute";
-
-    public final static String __ErrorHandler=
-        "org.mortbay.http.ErrorHandler";
-
-
-    /* ------------------------------------------------------------ */
-    /* ------------------------------------------------------------ */
-    // These attributes are serialized by WebApplicationContext, which needs
-    // to be updated if you add to these
-    private String _contextPath;
-    private List _vhosts=new ArrayList(2);
-    private List _hosts=new ArrayList(2);
-    private List _handlers=new ArrayList(3);
-    private Map _attributes = new HashMap(3);
-    private boolean _redirectNullPath=true;
-    private boolean _statsOn=false;
-    private PermissionCollection _permissions;
-    private boolean _classLoaderJava2Compliant=true;
-    private ResourceCache _resources;
-    private String[] _systemClasses=new String [] {"java.","javax.servlet.","javax.xml.","org.mortbay.","org.xml.","org.w3c.","org.apache.commons.logging."};
-    private String[] _serverClasses = new String[] {"-org.mortbay.http.PathMap","-org.mortbay.jetty.servlet.Invoker","-org.mortbay.jetty.servlet.JSR154Filter","-org.mortbay.jetty.servlet.Default","org.mortbay.jetty.Server","org.mortbay.http.","org.mortbay.start.","org.mortbay.stop."};
-  
-    /* ------------------------------------------------------------ */
-    private String _contextName;
-    private String _classPath;
-    private Map _initParams = new HashMap(11);
-    private UserRealm _userRealm;
-    private String _realmName;
-    private PathMap _constraintMap=new PathMap();
-    private Authenticator _authenticator;
-    private RequestLog _requestLog;
-
-
-    private String[] _welcomes=
-    {
-        "welcome.html",
-        "index.html",
-        "index.htm",
-        "index.jsp"
-    };
-
-
-    /* ------------------------------------------------------------ */
-    private transient boolean _gracefulStop;
-    private transient ClassLoader _parent;
-    private transient ClassLoader _loader;
-    private transient HttpServer _httpServer;
-    private transient File _tmpDir;
-    private transient HttpHandler[] _handlersArray;
-    private transient String[] _vhostsArray;
-
-
-    /* ------------------------------------------------------------ */
-    transient Object _statsLock=new Object[0];
-    transient long _statsStartedAt;
-    transient int _requests;
-    transient int _requestsActive;
-    transient int _requestsActiveMax;
-    transient int _responses1xx; // Informal
-    transient int _responses2xx; // Success
-    transient int _responses3xx; // Redirection
-    transient int _responses4xx; // Client Error
-    transient int _responses5xx; // Server Error
-
-
-    /* ------------------------------------------------------------ */
-    /** Constructor.
-     */
-    public HttpContext()
-    {
-        setAttribute(__ErrorHandler,  new ErrorPageHandler()); 
-        _resources=new ResourceCache();
-        addComponent(_resources);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Constructor.
-     * @param httpServer
-     * @param contextPathSpec
-     */
-    public HttpContext(HttpServer httpServer,String contextPathSpec)
-    {
-        this();
-        setHttpServer(httpServer);
-        setContextPath(contextPathSpec);
-    }
-
-    /* ------------------------------------------------------------ */
-    private void readObject(java.io.ObjectInputStream in)
-        throws IOException, ClassNotFoundException
-    {
-        in.defaultReadObject();
-        _statsLock=new Object[0];
-        getHandlers();
-        for (int i=0;i<_handlersArray.length;i++)
-            _handlersArray[i].initialize(this);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the ThreadLocal HttpConnection.
-     * Get the HttpConnection for current thread, if any.  This method is
-     * not static in order to control access.
-     * @return HttpConnection for this thread.
-     */
-    public HttpConnection getHttpConnection()
-    {
-        return HttpConnection.getHttpConnection();
-    }
-
-    /* ------------------------------------------------------------ */
-    void setHttpServer(HttpServer httpServer)
-    {
-        _httpServer=httpServer;
-        _contextName=null;
-      
-    }
-
-    /* ------------------------------------------------------------ */
-    public HttpServer getHttpServer()
-    {
-        return _httpServer;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void setStopGracefully(boolean graceful)
-    {
-	_gracefulStop=graceful;
-    }
-
-    /* ------------------------------------------------------------ */
-    public boolean getStopGracefully()
-    {
-	return _gracefulStop;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    public static String canonicalContextPathSpec(String contextPathSpec)
-    {
-        // check context path
-        if (contextPathSpec==null ||
-            contextPathSpec.indexOf(',')>=0 ||
-            contextPathSpec.startsWith("*"))
-            throw new IllegalArgumentException ("Illegal context spec:"+contextPathSpec);
-
-        if(!contextPathSpec.startsWith("/"))
-	    contextPathSpec='/'+contextPathSpec;
-
-        if (contextPathSpec.length()>1)
-        {
-            if (contextPathSpec.endsWith("/"))
-                contextPathSpec+="*";
-            else if (!contextPathSpec.endsWith("/*"))
-                contextPathSpec+="/*";
-        }
-
-        return contextPathSpec;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void setContextPath(String contextPathSpec)
-    {
-        if (_httpServer!=null)
-            _httpServer.removeMappings(this);
-
-        contextPathSpec=canonicalContextPathSpec(contextPathSpec);
-
-        if (contextPathSpec.length()>1)
-            _contextPath=contextPathSpec.substring(0,contextPathSpec.length()-2);
-        else
-            _contextPath="/";
-
-        _contextName=null;
-
-        if (_httpServer!=null)
-            _httpServer.addMappings(this);
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return The context prefix
-     */
-    public String getContextPath()
-    {
-        return _contextPath;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Add a virtual host alias to this context.
-     * @see #setVirtualHosts
-     * @param hostname A hostname. A null host name means any hostname is
-     * acceptable. Host names may String representation of IP addresses.
-     */
-    public void addVirtualHost(String hostname)
-    {
-        // Note that null hosts are also added.
-        if (!_vhosts.contains(hostname))
-        {
-            _vhosts.add(hostname);
-            _contextName=null;
-
-            if (_httpServer!=null)
-            {
-                if (_vhosts.size()==1)
-                    _httpServer.removeMapping(null,this);
-                _httpServer.addMapping(hostname,this);
-            }
-            _vhostsArray=null;
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    /** remove a virtual host alias to this context.
-     * @see #setVirtualHosts
-     * @param hostname A hostname. A null host name means any hostname is
-     * acceptable. Host names may String representation of IP addresses.
-     */
-    public void removeVirtualHost(String hostname)
-    {
-        // Note that null hosts are also added.
-        if (_vhosts.remove(hostname))
-        {
-            _contextName=null;
-            if (_httpServer!=null)
-            {
-                _httpServer.removeMapping(hostname,this);
-                if (_vhosts.size()==0)
-                    _httpServer.addMapping(null,this);
-            }
-            _vhostsArray=null;
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set the virtual hosts for the context.
-     * Only requests that have a matching host header or fully qualified
-     * URL will be passed to that context with a virtual host name.
-     * A context with no virtual host names or a null virtual host name is
-     * available to all requests that are not served by a context with a
-     * matching virtual host name.
-     * @param hosts Array of virtual hosts that this context responds to. A
-     * null host name or null/empty array means any hostname is acceptable.
-     * Host names may String representation of IP addresses.
-     */
-    public void setVirtualHosts(String[] hosts)
-    {
-        List old = new ArrayList(_vhosts);
-
-        if (hosts!=null)
-	{
-	    for (int i=0;i<hosts.length;i++)
-	    {
-		boolean existing=old.remove(hosts[i]);
-		if (!existing)
-		    addVirtualHost(hosts[i]);
-	    }
-	}
-
-        for (int i=0;i<old.size();i++)
-            removeVirtualHost((String)old.get(i));
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the virtual hosts for the context.
-     * Only requests that have a matching host header or fully qualified
-     * URL will be passed to that context with a virtual host name.
-     * A context with no virtual host names or a null virtual host name is
-     * available to all requests that are not served by a context with a
-     * matching virtual host name.
-     * @return Array of virtual hosts that this context responds to. A
-     * null host name or empty array means any hostname is acceptable.
-     * Host names may be String representation of IP addresses.
-     */
-    public String[] getVirtualHosts()
-    {
-        if (_vhostsArray!=null)
-            return _vhostsArray;
-        if (_vhosts==null)
-            _vhostsArray=new String[0];
-        else
-        {
-            _vhostsArray=new String[_vhosts.size()];
-            _vhostsArray=(String[])_vhosts.toArray(_vhostsArray);
-        }
-        return _vhostsArray;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Set the hosts for the context.
-     * Set the real hosts that this context will accept requests for.
-     * If not null or empty, then only requests from HttpListeners for hosts
-     * in this array are accepted by this context. 
-     * Unlike virutal hosts, this value is not used by HttpServer for
-     * matching a request to a context.
-     */
-    public void setHosts(String[] hosts)
-        throws UnknownHostException
-    {
-        if (hosts==null || hosts.length==0)
-            _hosts=null;
-        else
-        {
-            _hosts=new ArrayList();
-            for (int i=0;i<hosts.length;i++)
-                if (hosts[i]!=null)
-                    _hosts.add(InetAddress.getByName(hosts[i]));
-        }
-        
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the hosts for the context.
-     */
-    public String[] getHosts()
-    {
-        if (_hosts==null || _hosts.size()==0)
-            return null;
-        String[] hosts=new String[_hosts.size()];
-        for (int i=0;i<hosts.length;i++)
-        {
-            InetAddress a = (InetAddress)_hosts.get(i);
-            if (a!=null)
-                hosts[i]=a.getHostName();
-        }
-        return hosts;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Set system classes.
-     * System classes cannot be overriden by context classloaders.
-     * @param classes array of classname Strings.  Names ending with '.' are treated as package names. Names starting with '-' are treated as
-     * negative matches and must be listed before any enclosing packages.
-     */
-    public void setSystemClasses(String[] classes)
-    {
-        _systemClasses=classes;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get system classes.
-     * System classes cannot be overriden by context classloaders.
-     * @return array of classname Strings.  Names ending with '.' are treated as package names. Names starting with '-' are treated as
-     * negative matches and must be listed before any enclosing packages. Null if not set.
-     */
-    public String[] getSystemClasses()
-    {
-        return _systemClasses;
-    }
-    
-
-    /* ------------------------------------------------------------ */
-    /** Set system classes.
-     * Servers classes cannot be seen by context classloaders.
-     * @param classes array of classname Strings.  Names ending with '.' are treated as package names. Names starting with '-' are treated as
-     * negative matches and must be listed before any enclosing packages.
-     */
-    public void setServerClasses(String[] classes)
-    {
-        _serverClasses=classes;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get system classes.
-     * System classes cannot be seen by context classloaders.
-     * @return array of classname Strings.  Names ending with '.' are treated as package names. Names starting with '-' are treated as
-     * negative matches and must be listed before any enclosing packages. Null if not set.
-     */
-    public String[] getServerClasses()
-    {
-        return _serverClasses;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    public void setHandlers(HttpHandler[] handlers)
-    {
-        List old = new ArrayList(_handlers);
-
-	if (handlers!=null)
-	{
-	    for (int i=0;i<handlers.length;i++)
-	    {
-		boolean existing=old.remove(handlers[i]);
-		if (!existing)
-		    addHandler(handlers[i]);
-	    }
-	}
-
-        for (int i=0;i<old.size();i++)
-            removeHandler((HttpHandler)old.get(i));
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get all handlers.
-     * @return List of all HttpHandlers
-     */
-    public HttpHandler[] getHandlers()
-    {
-        if (_handlersArray!=null)
-            return _handlersArray;
-        if (_handlers==null)
-            _handlersArray=new HttpHandler[0];
-        else
-        {
-            _handlersArray=new HttpHandler[_handlers.size()];
-            _handlersArray=(HttpHandler[])_handlers.toArray(_handlersArray);
-        }
-        return _handlersArray;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Add a handler.
-     * @param i The position in the handler list
-     * @param handler The handler.
-     */
-    public synchronized void addHandler(int i,HttpHandler handler)
-    {
-        _handlers.add(i,handler);
-        _handlersArray=null;
-
-        HttpContext context = handler.getHttpContext();
-        if (context==null)
-            handler.initialize(this);
-        else if (context!=this)
-            throw new IllegalArgumentException("Handler in another HttpContext");
-        addComponent(handler);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Add a HttpHandler to the context.
-     * @param handler
-     */
-    public synchronized void addHandler(HttpHandler handler)
-    {
-        addHandler(_handlers.size(),handler);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get handler index.
-     * @param handler instance
-     * @return Index of handler in context or -1 if not found.
-     */
-    public int getHandlerIndex(HttpHandler handler)
-    {
-        for (int h=0;h<_handlers.size();h++)
-        {
-            if ( handler == _handlers.get(h))
-                return h;
-        }
-        return -1;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get a handler by class.
-     * @param handlerClass
-     * @return The first handler that is an instance of the handlerClass
-     */
-    public synchronized HttpHandler getHandler(Class handlerClass)
-    {
-        for (int h=0;h<_handlers.size();h++)
-        {
-            HttpHandler handler = (HttpHandler)_handlers.get(h);
-            if (handlerClass.isInstance(handler))
-                return handler;
-        }
-        return null;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Remove a handler.
-     * The handler must be stopped before being removed.
-     * @param i index of handler
-     */
-    public synchronized HttpHandler removeHandler(int i)
-    {
-        HttpHandler handler = _handlersArray[i];
-        if (handler.isStarted())
-            try{handler.stop();} catch (InterruptedException e){log.warn(LogSupport.EXCEPTION,e);}
-        _handlers.remove(i);
-        _handlersArray=null;
-        removeComponent(handler);
-        return handler;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Remove a handler.
-     * The handler must be stopped before being removed.
-     */
-    public synchronized void removeHandler(HttpHandler handler)
-    {
-        if (handler.isStarted())
-            try{handler.stop();} catch (InterruptedException e){log.warn(LogSupport.EXCEPTION,e);}
-        _handlers.remove(handler);
-        removeComponent(handler);
-        _handlersArray=null;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Set context init parameter.
-     * Init Parameters differ from attributes as they can only
-     * have string values, servlets cannot set them and they do
-     * not have a package scoped name space.
-     * @param param param name
-     * @param value param value or null
-     */
-    public void setInitParameter(String param, String value)
-    {
-        _initParams.put(param,value);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get context init parameter.
-     * @param param param name
-     * @return param value or null
-     */
-    public String getInitParameter(String param)
-    {
-        return (String)_initParams.get(param);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get context init parameter.
-     * @return Enumeration of names
-     */
-    public Enumeration getInitParameterNames()
-    {
-        return Collections.enumeration(_initParams.keySet());
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set a context attribute.
-     * @param name attribute name
-     * @param value attribute value
-     */
-    public synchronized void setAttribute(String name, Object value)
-    {
-        _attributes.put(name,value);
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @param name attribute name
-     * @return attribute value or null
-     */
-    public Object getAttribute(String name)
-    {
-        return _attributes.get(name);
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     */
-    public Map getAttributes()
-    {
-        return _attributes;
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     */
-    public void setAttributes(Map attributes)
-    {
-        _attributes=attributes;
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return enumaration of names.
-     */
-    public Enumeration getAttributeNames()
-    {
-        return Collections.enumeration(_attributes.keySet());
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @param name attribute name
-     */
-    public synchronized void removeAttribute(String name)
-    {
-        _attributes.remove(name);
-    }
-
-
-    /* ------------------------------------------------------------ */
-    public void flushCache()
-    {
-        _resources.flushCache();
-    }
-
-    /* ------------------------------------------------------------ */
-    public String[] getWelcomeFiles()
-    {
-        return _welcomes;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void setWelcomeFiles(String[] welcomes)
-    {
-        if (welcomes==null)
-            _welcomes=new String[0];
-        else
-            _welcomes=welcomes;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void addWelcomeFile(String welcomeFile)
-    {
-        if (welcomeFile.startsWith("/") ||
-            welcomeFile.startsWith(java.io.File.separator) ||
-            welcomeFile.endsWith("/") ||
-            welcomeFile.endsWith(java.io.File.separator))
-            log.warn("Invalid welcome file: "+welcomeFile);
-        List list = new ArrayList(Arrays.asList(_welcomes));
-        list.add(welcomeFile);
-        _welcomes=(String[])list.toArray(_welcomes);
-    }
-
-    /* ------------------------------------------------------------ */
-    public void removeWelcomeFile(String welcomeFile)
-    {
-        List list = new ArrayList(Arrays.asList(_welcomes));
-        list.remove(welcomeFile);
-        _welcomes=(String[])list.toArray(_welcomes);
-    }
-
-    /* ------------------------------------------------------------ */
-    public String getWelcomeFile(Resource resource)
-        throws IOException
-    {
-        if (!resource.isDirectory())
-            return null;
-
-        for (int i=0;i<_welcomes.length;i++)
-        {
-            Resource welcome=resource.addPath(_welcomes[i]);
-            if (welcome.exists())
-                return _welcomes[i];
-        }
-
-        return null;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Get the context classpath.
-     * This method only returns the paths that have been set for this
-     * context and does not include any paths from a parent or the
-     * system classloader.
-     * Note that this may not be a legal javac classpath.
-     * @return a comma or ';' separated list of class
-     * resources. These may be jar files, directories or URLs to jars
-     * or directories.
-     * @see #getFileClassPath()
-     */
-    public String getClassPath()
-    {
-        return _classPath;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the file classpath of the context.
-     * This method makes a best effort to return a complete file
-     * classpath for the context.
-     * It is obtained by walking the classloader hierarchy and looking for
-     * URLClassLoaders.  The system property java.class.path is also checked for
-     * file elements not already found in the loader hierarchy.
-     * @return Path of files and directories for loading classes.
-     * @exception IllegalStateException HttpContext.initClassLoader
-     * has not been called.
-     */
-    public String getFileClassPath()
-        throws IllegalStateException
-    {
-	
-        ClassLoader loader = getClassLoader();
-        if (loader==null)
-            throw new IllegalStateException("Context classloader not initialized");
-            
-        LinkedList paths =new LinkedList();
-        LinkedList loaders=new LinkedList();
-        
-        // Walk the loader hierarchy
-       	while (loader !=null)
-       	{
-            loaders.add(0,loader);
-            loader = loader.getParent();
-       	}
-       	
-       	// Try to handle java2compliant modes
-       	loader=getClassLoader();
-       	if (loader instanceof ContextLoader && !((ContextLoader)loader).isJava2Compliant())
-       	{
-            loaders.remove(loader);
-            loaders.add(0,loader);
-       	}
-        
-        for (int i=0;i<loaders.size();i++)
-        {
-            loader=(ClassLoader)loaders.get(i);
-            
-            if (log.isDebugEnabled()) log.debug("extract paths from "+loader);
-            if (loader instanceof URLClassLoader)
-            {
-                URL[] urls = ((URLClassLoader)loader).getURLs();
-                for (int j=0;urls!=null && j<urls.length;j++)
-                {
-                    try
-                    {
-                        Resource path = Resource.newResource(urls[j]);
-                        if (log.isTraceEnabled()) log.trace("path "+path);
-                        File file = path.getFile();
-                        if (file!=null)
-                            paths.add(file.getAbsolutePath());
-                    }
-                    catch(Exception e)
-                    {
-                        LogSupport.ignore(log,e);
-                    }
-                }	
-            }	
-       	}
-       	
-        // Add the system classpath elements from property.
-        String jcp=System.getProperty("java.class.path");
-        if (jcp!=null)
-        {
-            StringTokenizer tok=new StringTokenizer(jcp,File.pathSeparator);
-            while (tok.hasMoreTokens())
-            {
-                String path=tok.nextToken();
-                if (!paths.contains(path))
-                {
-                    if(log.isTraceEnabled())log.trace("PATH="+path);
-                    paths.add(path);
-                }
-                else
-                    if(log.isTraceEnabled())log.trace("done="+path);			
-            }
-        }
-        
-        StringBuffer buf = new StringBuffer();
-        Iterator iter = paths.iterator();
-        while(iter.hasNext())
-        {
-            if (buf.length()>0)
-                buf.append(File.pathSeparator);
-            buf.append(iter.next().toString());
-        }
-        
-        if (log.isDebugEnabled()) log.debug("fileClassPath="+buf);
-        return buf.toString();
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Sets the class path for the context.
-     * A class path is only required for a context if it uses classes
-     * that are not in the system class path.
-     * @param classPath a comma or ';' separated list of class
-     * resources. These may be jar files, directories or URLs to jars
-     * or directories.
-     */
-    public void setClassPath(String classPath)
-    {
-        _classPath=classPath;
-        if (isStarted())
-            log.warn("classpath set while started");
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Add the class path element  to the context.
-     * A class path is only required for a context if it uses classes
-     * that are not in the system class path.
-     * @param classPath a comma or ';' separated list of class
-     * resources. These may be jar files, directories or URLs to jars
-     * or directories.
-     */
-    public void addClassPath(String classPath)
-    {
-        if (_classPath==null || _classPath.length()==0)
-            _classPath=classPath;
-        else
-            _classPath+=","+classPath;
-
-        if (isStarted())
-            log.warn("classpath set while started");
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Add elements to the class path for the context from the jar and zip files found
-     *  in the specified resource.
-     * @param lib the resource that contains the jar and/or zip files.
-     * @param append true if the classpath entries are to be appended to any
-     * existing classpath, or false if they replace the existing classpath.
-     * @see #setClassPath(String)
-     */
-    public void addClassPaths(Resource lib)
-    {
-        if (isStarted())
-            log.warn("classpaths set while started");
-
-        if (lib.exists() && lib.isDirectory())
-        {
-            String[] files=lib.list();
-            for (int f=0;files!=null && f<files.length;f++)
-            {
-                try {
-                    Resource fn=lib.addPath(files[f]);
-                    String fnlc=fn.getName().toLowerCase();
-                    if (fnlc.endsWith(".jar") || fnlc.endsWith(".zip"))
-                    {
-                        addClassPath(fn.toString());
-                    }
-                }
-                catch (Exception ex)
-                {
-                    log.warn(LogSupport.EXCEPTION,ex);
-                }
-            }
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get Java2 compliant classloading.
-     * @return If true, the class loader will conform to the java 2
-     * specification and delegate all loads to the parent classloader. If
-     * false, the context classloader only delegate loads for system classes
-     * or classes that it can't find itself.
-     */
-    public boolean isClassLoaderJava2Compliant()
-    {
-        return _classLoaderJava2Compliant;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set Java2 compliant classloading.
-     * @param compliant If true, the class loader will conform to the java 2
-     * specification and delegate all loads to the parent classloader. If
-     * false, the context classloader only delegate loads for system classes
-     * or classes that it can't find itself.
-     */
-    public void setClassLoaderJava2Compliant(boolean compliant)
-    {
-        _classLoaderJava2Compliant = compliant;
-        if (_loader!=null && (_loader instanceof ContextLoader))
-            ((ContextLoader)_loader).setJava2Compliant(compliant);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set temporary directory for context.
-     * The javax.servlet.context.tempdir attribute is also set.
-     * @param dir Writable temporary directory.
-     */
-    public void setTempDirectory(File dir)
-    {
-        if (isStarted())
-            throw new IllegalStateException("Started");
-
-        if (dir!=null)
-        {
-            try{dir=new File(dir.getCanonicalPath());}
-            catch (IOException e){log.warn(LogSupport.EXCEPTION,e);}
-        }
-
-        if (dir!=null && !dir.exists())
-        {
-            dir.mkdir();
-            dir.deleteOnExit();
-        }
-
-        if (dir!=null && ( !dir.exists() || !dir.isDirectory() || !dir.canWrite()))
-            throw new IllegalArgumentException("Bad temp directory: "+dir);
-
-        _tmpDir=dir;
-        setAttribute("javax.servlet.context.tempdir",_tmpDir);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get Context temporary directory.
-     * A tempory directory is generated if it has not been set.  The
-     * "javax.servlet.context.tempdir" attribute is consulted and if
-     * not set, the host, port and context are used to generate a
-     * directory within the JVMs temporary directory.
-     *
-     * Patched for IPV6 support in I2P to replace ':' in the dir name which
-     * Windows can't handle.
-     *
-     * @return Temporary directory as a File.
-     */
-    public File getTempDirectory()
-    {
-        if (_tmpDir!=null)
-            return _tmpDir;
-
-        // Initialize temporary directory
-        //
-        // I'm afraid that this is very much black magic.
-        // but if you can think of better....
-        Object t = getAttribute("javax.servlet.context.tempdir");
-
-        if (t!=null && (t instanceof File))
-        {
-            _tmpDir=(File)t;
-            if (_tmpDir.isDirectory() && _tmpDir.canWrite())
-                return _tmpDir;
-        }
-
-        if (t!=null && (t instanceof String))
-        {
-            try
-            {
-                _tmpDir=new File((String)t);
-
-                if (_tmpDir.isDirectory() && _tmpDir.canWrite())
-                {
-                    if(log.isDebugEnabled())log.debug("Converted to File "+_tmpDir+" for "+this);
-                    setAttribute("javax.servlet.context.tempdir",_tmpDir);
-                    return _tmpDir;
-                }
-            }
-            catch(Exception e)
-            {
-                log.warn(LogSupport.EXCEPTION,e);
-            }
-        }
-
-        // No tempdir so look for a WEB-INF/work directory to use as tempDir base
-        File work=null;
-        try
-        {
-            work=new File(System.getProperty("jetty.home"),"work");
-            if (!work.exists() || !work.canWrite() || !work.isDirectory())
-                work=null;
-        }
-        catch(Exception e)
-        {
-            LogSupport.ignore(log,e);
-        }
-
-        // No tempdir set so make one!
-        try
-        {
-            HttpListener httpListener=_httpServer.getListeners()[0];
-
-            String vhost = null;
-            for (int h=0;vhost==null && _vhosts!=null && h<_vhosts.size();h++)
-                vhost=(String)_vhosts.get(h);
-            String host=httpListener.getHost();
-            String temp="Jetty_"+
-                (host==null?"":host)+
-                "_"+
-                httpListener.getPort()+
-                "_"+
-                (vhost==null?"":vhost)+
-                getContextPath();
-
-            temp=temp.replace('/','_');
-            temp=temp.replace('.','_');
-            temp=temp.replace('\\','_');
-            temp=temp.replace(':','_');
-
-            
-            if (work!=null)
-                _tmpDir=new File(work,temp);
-            else
-            {
-                _tmpDir=new File(System.getProperty("java.io.tmpdir"),temp);
-                
-                if (_tmpDir.exists())
-                {
-                    if(log.isDebugEnabled())log.debug("Delete existing temp dir "+_tmpDir+" for "+this);
-                    if (!IO.delete(_tmpDir))
-                    {
-                        if(log.isDebugEnabled())log.debug("Failed to delete temp dir "+_tmpDir);
-                    }
-                
-                    if (_tmpDir.exists())
-                    {
-                        String old=_tmpDir.toString();
-                        _tmpDir=File.createTempFile(temp+"_","");
-                        if (_tmpDir.exists())
-                            _tmpDir.delete();
-                        log.warn("Can't reuse "+old+", using "+_tmpDir);
-                    }
-                }
-            }
-
-            if (!_tmpDir.exists())
-                _tmpDir.mkdir();
-            if (work==null)
-                _tmpDir.deleteOnExit();
-            if(log.isDebugEnabled())log.debug("Created temp dir "+_tmpDir+" for "+this);
-        }
-        catch(Exception e)
-        {
-            _tmpDir=null;
-            LogSupport.ignore(log,e);
-        }
-
-        if (_tmpDir==null)
-        {
-            try{
-                // that didn't work, so try something simpler (ish)
-                _tmpDir=File.createTempFile("JettyContext","");
-                if (_tmpDir.exists())
-                    _tmpDir.delete();
-                _tmpDir.mkdir();
-                _tmpDir.deleteOnExit();
-                if(log.isDebugEnabled())log.debug("Created temp dir "+_tmpDir+" for "+this);
-            }
-            catch(IOException e)
-            {
-                log.fatal(e); System.exit(1);
-            }
-        }
-
-        setAttribute("javax.servlet.context.tempdir",_tmpDir);
-        return _tmpDir;
-    }
-
-
-
-    /* ------------------------------------------------------------ */
-    /** Set ClassLoader.
-     * @param loader The loader to be used by this context.
-     */
-    public synchronized void setClassLoader(ClassLoader loader)
-    {
-        if (isStarted())
-            throw new IllegalStateException("Started");
-        _loader=loader;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Get the classloader.
-     * If no classloader has been set and the context has been loaded
-     * normally, then null is returned.
-     * If no classloader has been set and the context was loaded from
-     * a classloader, that loader is returned.
-     * If a classloader has been set and no classpath has been set then
-     * the set classloader is returned.
-     * If a classloader and a classpath has been set, then a new
-     * URLClassloader initialized on the classpath with the set loader as a
-     * partent is return.
-     * @return Classloader or null.
-     */
-    public synchronized ClassLoader getClassLoader()
-    {
-        return _loader;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set Parent ClassLoader.
-     * By default the parent loader is the thread context classloader
-     * of the thread that calls initClassLoader.  If setClassLoader is
-     * called, then the parent is ignored.
-     * @param loader The class loader to use for the parent loader of
-     * the context classloader.
-     */
-    public synchronized void setParentClassLoader(ClassLoader loader)
-    {
-        if (isStarted())
-            throw new IllegalStateException("Started");
-        _parent=loader;
-    }
-
-    /* ------------------------------------------------------------ */
-    public ClassLoader getParentClassLoader()
-    {
-        return _parent;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Initialize the context classloader.
-     * Initialize the context classloader with the current parameters.
-     * Any attempts to change the classpath after this call will
-     * result in a IllegalStateException
-     * @param forceContextLoader If true, a ContextLoader is always if
-     * no loader has been set.
-     */
-    protected void initClassLoader(boolean forceContextLoader)
-        throws MalformedURLException, IOException
-    {
-        ClassLoader parent=_parent;
-        if (_loader==null)
-        {
-            // If no parent, then try this threads classes loader as parent
-            if (parent==null)
-                parent=Thread.currentThread().getContextClassLoader();
-
-            // If no parent, then try this classes loader as parent
-            if (parent==null)
-                parent=this.getClass().getClassLoader();
-
-            if(log.isDebugEnabled())log.debug("Init classloader from "+_classPath+
-                       ", "+parent+" for "+this);
-
-            if (forceContextLoader || _classPath!=null || _permissions!=null)
-            {
-                ContextLoader loader=new ContextLoader(this,_classPath,parent,_permissions);
-                loader.setJava2Compliant(_classLoaderJava2Compliant);
-                _loader=loader;
-            }
-            else
-                _loader=parent;
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    public synchronized Class loadClass(String className)
-        throws ClassNotFoundException
-    {
-        if (_loader==null)
-        {
-            try{initClassLoader(false);}
-            catch(Exception e)
-            {
-                log.warn(LogSupport.EXCEPTION,e);
-                return null;
-            }
-        }
-
-        if (className==null)
-            return null;
-
-        if (_loader == null) 
-            return Class.forName(className); 
-        return _loader.loadClass(className);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set the realm name.
-     * @param realmName The name to use to retrieve the actual realm
-     * from the HttpServer
-     */
-    public void setRealmName(String realmName)
-    {
-        _realmName=realmName;
-    }
-
-    /* ------------------------------------------------------------ */
-    public String getRealmName()
-    {
-        return _realmName;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set the  realm.
-     */
-    public void setRealm(UserRealm realm)
-    {
-        _userRealm=realm;
-    }
-
-    /* ------------------------------------------------------------ */
-    public UserRealm getRealm()
-    {
-        return _userRealm;
-    }
-
-    /* ------------------------------------------------------------ */
-    public Authenticator getAuthenticator()
-    {
-        return _authenticator;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void setAuthenticator(Authenticator authenticator)
-    {
-        _authenticator=authenticator;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void addSecurityConstraint(String pathSpec, SecurityConstraint sc)
-    {
-        Object scs = _constraintMap.get(pathSpec);
-        scs = LazyList.add(scs,sc);
-        _constraintMap.put(pathSpec,scs);
-        
-        if(log.isDebugEnabled())log.debug("added "+sc+" at "+pathSpec);
-    }
-
-    /* ------------------------------------------------------------ */
-    public void clearSecurityConstraints()
-    {
-        _constraintMap.clear();
-    }
-
-    /* ------------------------------------------------------------ */
-    public boolean checkSecurityConstraints(
-        String pathInContext,
-        HttpRequest request,
-        HttpResponse response)
-        throws HttpException, IOException
-    {
-        UserRealm realm= getRealm();
-
-        List scss= _constraintMap.getMatches(pathInContext);
-        String pattern=null;
-        if (scss != null && !scss.isEmpty())
-        {
-            Object constraints= null;
-
-            // for each path match
-            // Add only constraints that have the correct method
-            // break if the matching pattern changes.  This allows only
-            // constraints with matching pattern and method to be combined.
-            loop:
-            for (int m= 0; m < scss.size(); m++)
-            {
-                Map.Entry entry= (Map.Entry)scss.get(m);
-                Object scs= entry.getValue();
-                String p=(String)entry.getKey();
-                for (int c=0;c<LazyList.size(scs);c++)
-                {
-                	SecurityConstraint sc=(SecurityConstraint)LazyList.get(scs,c);
-					if (!sc.forMethod(request.getMethod()))
-						continue;
-						
-					if (pattern!=null && !pattern.equals(p))
-						break loop;
-					pattern=p;	
-	                constraints= LazyList.add(constraints, sc);
-                }
-            }
-            
-            return SecurityConstraint.check(
-                LazyList.getList(constraints),
-                _authenticator,
-                realm,
-                pathInContext,
-                request,
-                response);
-        }
-        request.setUserPrincipal(HttpRequest.__NOT_CHECKED);
-        return true;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set null path redirection.
-     * @param b if true a /context request will be redirected to
-     * /context/ if there is not path in the context.
-     */
-    public void setRedirectNullPath(boolean b)
-    {
-        _redirectNullPath=b;
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return True if a /context request is redirected to /context/ if
-     * there is not path in the context.
-     */
-    public boolean isRedirectNullPath()
-    {
-        return _redirectNullPath;
-    }
-
-
-
-    /* ------------------------------------------------------------ */
-    /** Set the permissions to be used for this context.
-     * The collection of permissions set here are used for all classes
-     * loaded by this context.  This is simpler that creating a
-     * security policy file, as not all code sources may be statically
-     * known.
-     * @param permissions
-     */
-    public void setPermissions(PermissionCollection permissions)
-    {
-        _permissions=permissions;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the permissions to be used for this context.
-     */
-    public PermissionCollection getPermissions()
-    {
-        return _permissions;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Add a permission to this context.
-     * The collection of permissions set here are used for all classes
-     * loaded by this context.  This is simpler that creating a
-     * security policy file, as not all code sources may be statically
-     * known.
-     * @param permission
-     */
-    public void addPermission(Permission permission)
-    {
-        if (_permissions==null)
-            _permissions=new Permissions();
-        _permissions.add(permission);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Handler request.
-     * Determine the path within the context and then call
-     * handle(pathInContext,request,response).
-     * @param request
-     * @param response
-     * @return True if the request has been handled.
-     * @exception HttpException
-     * @exception IOException
-     */
-    public void handle(HttpRequest request,
-                       HttpResponse response)
-        throws HttpException, IOException
-    {
-        if (!isStarted() || _gracefulStop)
-            return;
-
-        // reject requests by real host
-        if (_hosts!=null && _hosts.size()>0)
-        {
-            Object o = request.getHttpConnection().getConnection();
-            if (o instanceof Socket)
-            {
-                Socket s=(Socket)o;
-                if (!_hosts.contains(s.getLocalAddress()))
-                {
-                    if(log.isDebugEnabled())log.debug(s.getLocalAddress()+" not in "+_hosts);
-                    return;
-                }
-            }
-        }
-        
-        // handle stats
-        if (_statsOn)
-        {
-            synchronized(_statsLock)
-            {
-                _requests++;
-                _requestsActive++;
-                if (_requestsActive>_requestsActiveMax)
-                    _requestsActiveMax=_requestsActive;
-            }
-        }
-
-        String pathInContext = URI.canonicalPath(request.getPath());
-        if (pathInContext==null)
-        {
-            // Must be a bad request.
-            throw new HttpException(HttpResponse.__400_Bad_Request);
-        }
-
-        if (_contextPath.length()>1)
-            pathInContext=pathInContext.substring(_contextPath.length());
-
-        if (_redirectNullPath && (pathInContext==null ||
-                                  pathInContext.length()==0))
-        {
-            StringBuffer buf=request.getRequestURL();
-            buf.append("/");
-            String q=request.getQuery();
-            if (q!=null&&q.length()!=0)
-                buf.append("?"+q);
-                
-            response.sendRedirect(buf.toString());
-            if (log.isDebugEnabled())
-                log.debug(this+" consumed all of path "+
-                             request.getPath()+
-                             ", redirect to "+buf.toString());
-            return;
-        }
-
-        String pathParams=null;
-        int semi = pathInContext.lastIndexOf(';');
-        if (semi>=0)
-        {
-            int pl = pathInContext.length()-semi;
-            String ep=request.getEncodedPath();
-            if(';'==ep.charAt(ep.length()-pl))
-            {
-                pathParams=pathInContext.substring(semi+1);
-                pathInContext=pathInContext.substring(0,semi);
-            }
-        }
-
-        try
-        {
-            handle(pathInContext,pathParams,request,response);
-        }
-        finally
-        {
-            if (_userRealm!=null && request.hasUserPrincipal())
-                _userRealm.disassociate(request.getUserPrincipal());
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Handler request.
-     * Call each HttpHandler until request is handled.
-     * @param pathInContext Path in context
-     * @param pathParams Path parameters such as encoded Session ID
-     * @param request
-     * @param response
-     * @return True if the request has been handled.
-     * @exception HttpException
-     * @exception IOException
-     */
-    public void handle(String pathInContext,
-                       String pathParams,
-                       HttpRequest request,
-                       HttpResponse response)
-        throws HttpException, IOException
-    {
-        Object old_scope= null;
-        try
-        {
-            old_scope= enterContextScope(request,response);
-            HttpHandler[] handlers= getHandlers();
-            for (int k= 0; k < handlers.length; k++)
-            {
-                HttpHandler handler= handlers[k];
-                if (handler == null)
-                {
-                    handlers= getHandlers();
-                    k= -1;
-                    continue;
-                }
-                if (!handler.isStarted())
-                {
-                    if (log.isDebugEnabled())
-                        log.debug(handler + " not started in " + this);
-                    continue;
-                }
-                if (log.isDebugEnabled())
-                    log.debug("Handler " + handler);
-                handler.handle(pathInContext, pathParams, request, response);
-                if (request.isHandled())
-                {
-                    if (log.isDebugEnabled())
-                        log.debug("Handled by " + handler);
-                    return;
-                }
-            }
-            return;
-        }
-        finally
-        {
-            leaveContextScope(request, response, old_scope);
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Enter the context scope.
-     * This method is called (by handle or servlet dispatchers) to indicate that
-     * request handling is entering the scope of this context.  The opaque scope object
-     * returned, should be passed to the leaveContextScope method.
-     */
-    public Object enterContextScope(HttpRequest request, HttpResponse response)
-    {
-        // Save the thread context loader
-        Thread thread = Thread.currentThread();
-        ClassLoader cl=thread.getContextClassLoader();
-        HttpContext c=response.getHttpContext();
-
-        Scope scope=null;
-        if (cl!=HttpContext.class.getClassLoader() || c!=null)
-        {
-            scope=new Scope();
-            scope._classLoader=cl;
-            scope._httpContext=c;
-        }
-        
-        if (_loader!=null)
-            thread.setContextClassLoader(_loader);
-        response.setHttpContext(this);
-            
-        return scope;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Leave the context scope.
-     * This method is called (by handle or servlet dispatchers) to indicate that
-     * request handling is leaveing the scope of this context.  The opaque scope object
-     * returned by enterContextScope should be passed in.
-     */
-    public void leaveContextScope(HttpRequest request, HttpResponse response,Object oldScope)
-    {
-        if (oldScope==null)
-        {
-            Thread.currentThread()
-                .setContextClassLoader(HttpContext.class.getClassLoader());
-            response.setHttpContext(null);
-        }
-        else
-        {
-            Scope old = (Scope)oldScope;
-            Thread.currentThread().setContextClassLoader(old._classLoader);
-            response.setHttpContext(old._httpContext);
-        }
-    }
-    
-
-    /* ------------------------------------------------------------ */
-    public String getHttpContextName()
-    {
-        if (_contextName==null)
-            _contextName = (_vhosts.size()>1?(_vhosts.toString()+":"):"")+_contextPath;
-        return _contextName;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void setHttpContextName(String s)
-    {
-        _contextName=s;
-    }
-    
-    /* ------------------------------------------------------------ */
-    public String toString()
-    {
-        return "HttpContext["+getContextPath()+","+getHttpContextName()+"]";
-    }
-
-    /* ------------------------------------------------------------ */
-    public String toString(boolean detail)
-    {
-        return "HttpContext["+getContextPath()+","+getHttpContextName()+"]" +
-            (detail?("="+_handlers):"");
-    }
-
-    
-    /* ------------------------------------------------------------ */
-    protected synchronized void doStart()
-        throws Exception
-    {
-        if (isStarted())
-            return;
-
-        if (_httpServer.getServerClasses()!=null)
-            _serverClasses=_httpServer.getServerClasses();
-        if (_httpServer.getSystemClasses()!=null)
-            _systemClasses=_httpServer.getSystemClasses();
-        
-        _resources.start();
-        
-        statsReset();
-
-        if (_httpServer==null)
-            throw new IllegalStateException("No server for "+this);
-
-        // start the context itself
-        _resources.getMimeMap();
-        _resources.getEncodingMap();
-
-        // Setup realm
-        if (_userRealm==null && _authenticator!=null)
-        {
-            _userRealm=_httpServer.getRealm(_realmName);
-            if (_userRealm==null)
-                log.warn("No Realm: "+_realmName);
-        }
-
-        // setup the context loader
-        initClassLoader(false);
-
-        // Set attribute if needed
-        String attr = getInitParameter(__fileClassPathAttr);
-        if (attr!=null && attr.length()>0)
-            setAttribute(attr,getFileClassPath());
-
-        // Start the handlers
-        Thread thread = Thread.currentThread();
-        ClassLoader lastContextLoader=thread.getContextClassLoader();
-        try
-        {
-            if (_loader!=null)
-                thread.setContextClassLoader(_loader);
-
-            if (_requestLog!=null)
-                _requestLog.start();
-            
-            startHandlers();
-        }
-        finally
-        {
-            thread.setContextClassLoader(lastContextLoader);
-            getHandlers();
-        }
-
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Start the handlers.
-     * This is called by start after the classloader has been
-     * initialized and set as the thread context loader.
-     * It may be specialized to provide custom handling
-     * before any handlers are started.
-     * @exception Exception
-     */
-    protected void startHandlers()
-        throws Exception
-    {
-        // Prepare a multi exception
-        MultiException mx = new MultiException();
-
-        Iterator handlers = _handlers.iterator();
-        while(handlers.hasNext())
-        {
-            HttpHandler handler=(HttpHandler)handlers.next();
-            if (!handler.isStarted())
-                try{handler.start();}catch(Exception e){mx.add(e);}
-        }
-        mx.ifExceptionThrow();
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Stop the context.
-     * @param graceful If true and statistics are on, then this method will wait
-     * for requestsActive to go to zero before calling stop()
-     */
-    public void stop(boolean graceful)
-        throws InterruptedException
-    {
-        boolean gs=_gracefulStop;
-        try
-        {
-            _gracefulStop=true;
-            
-            // wait for all requests to complete.
-            while (graceful && _statsOn && _requestsActive>0 && _httpServer!=null)
-                try {Thread.sleep(100);}
-            catch (InterruptedException e){throw e;}
-            catch (Exception e){LogSupport.ignore(log,e);}
-            
-            stop();
-        }
-        finally
-        {
-            _gracefulStop=gs;
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Stop the context.
-     */
-    protected void doStop()
-        throws Exception
-    {
-        if (_httpServer==null)
-            throw new InterruptedException("Destroy called");
-
-        synchronized(this)
-        {
-            // Notify the container for the stop
-            Thread thread = Thread.currentThread();
-            ClassLoader lastContextLoader=thread.getContextClassLoader();
-            try
-            {
-                if (_loader!=null)
-                    thread.setContextClassLoader(_loader);
-                Iterator handlers = _handlers.iterator();
-                while(handlers.hasNext())
-                {
-                    HttpHandler handler=(HttpHandler)handlers.next();
-                    if (handler.isStarted())
-                    {
-                        try{handler.stop();}
-                        catch(Exception e){log.warn(LogSupport.EXCEPTION,e);}
-                    }
-                }
-                
-                if (_requestLog!=null)
-                    _requestLog.stop();
-            }
-            finally
-            {
-                thread.setContextClassLoader(lastContextLoader);
-            }
-            
-            // TODO this is a poor test
-            if (_loader instanceof ContextLoader)
-            {
-                ((ContextLoader)_loader).destroy();
-                LogFactory.release(_loader);
-            }
-            
-            _loader=null;
-        }
-        _resources.flushCache();
-        _resources.stop();
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Destroy a context.
-     * Destroy a context and remove it from the HttpServer. The
-     * HttpContext must be stopped before it can be destroyed.
-     */
-    public void destroy()
-    {
-        if (isStarted())
-            throw new IllegalStateException("Started");
-
-        if (_httpServer!=null)
-            _httpServer.removeContext(this);
-
-        _httpServer=null;
-        
-        if (_handlers!=null)
-            _handlers.clear();
-        
-        _handlers=null;
-        _parent=null;
-        _loader=null;
-        if (_attributes!=null)
-            _attributes.clear();
-        _attributes=null;
-        if (_initParams!=null)
-            _initParams.clear();
-        _initParams=null;
-        if (_vhosts!=null)
-            _vhosts.clear();
-        _vhosts=null;
-        _hosts=null;
-        _tmpDir=null;
-
-        _permissions=null;
-        
-        removeComponent(_resources);
-        if (_resources!=null)
-        {
-            _resources.flushCache();
-            if (_resources.isStarted())
-                try{_resources.stop();}catch(Exception e){LogSupport.ignore(log,e);}
-                _resources.destroy();
-        }
-        _resources=null;
-        
-        super.destroy();
-        
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Set the request log.
-     * @param log RequestLog to use.
-     */
-    public void setRequestLog(RequestLog log)
-    {
-        _requestLog=log;
-    }
-
-    /* ------------------------------------------------------------ */
-    public RequestLog getRequestLog()
-    {
-        return _requestLog;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Send an error response.
-     * This method may be specialized to provide alternative error handling for
-     * errors generated by the container.  The default implemenation calls HttpResponse.sendError
-     * @param response the response to send
-     * @param code The error code
-     * @param msg The message for the error or null for the default
-     * @throws IOException Problem sending response.
-     */
-    public void sendError(HttpResponse response,int code,String msg)
-    	throws IOException
-    {
-        response.sendError(code,msg);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Send an error response.
-     * This method obtains the responses context and call sendError for context specific
-     * error handling.
-     * @param response the response to send
-     * @param code The error code
-     * @param msg The message for the error or null for the default
-     * @throws IOException Problem sending response.
-     */
-    public static void sendContextError(HttpResponse response,int code,String msg)
-    	throws IOException
-    {
-        HttpContext context = response.getHttpContext();
-        if (context!=null)
-            context.sendError(response,code,msg);
-        else
-            response.sendError(code,msg);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** True set statistics recording on for this context.
-     * @param on If true, statistics will be recorded for this context.
-     */
-    public void setStatsOn(boolean on)
-    {
-        log.info("setStatsOn "+on+" for "+this);
-        _statsOn=on;
-        statsReset();
-    }
-
-    /* ------------------------------------------------------------ */
-    public boolean getStatsOn() {return _statsOn;}
-
-    /* ------------------------------------------------------------ */
-    public long getStatsOnMs()
-    {return _statsOn?(System.currentTimeMillis()-_statsStartedAt):0;}
-
-    /* ------------------------------------------------------------ */
-    public void statsReset()
-    {
-        synchronized(_statsLock)
-        {
-            if (_statsOn)
-                _statsStartedAt=System.currentTimeMillis();
-            _requests=0;
-            _requestsActiveMax=_requestsActive;
-            _responses1xx=0;
-            _responses2xx=0;
-            _responses3xx=0;
-            _responses4xx=0;
-            _responses5xx=0;
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Get the number of requests handled by this context
-     * since last call of statsReset(). If setStatsOn(false) then this
-     * is undefined.
-     */
-    public int getRequests() {return _requests;}
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Number of requests currently active.
-     * Undefined if setStatsOn(false).
-     */
-    public int getRequestsActive() {return _requestsActive;}
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Maximum number of active requests
-     * since statsReset() called. Undefined if setStatsOn(false).
-     */
-    public int getRequestsActiveMax() {return _requestsActiveMax;}
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Get the number of responses with a 2xx status returned
-     * by this context since last call of statsReset(). Undefined if
-     * if setStatsOn(false).
-     */
-    public int getResponses1xx() {return _responses1xx;}
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Get the number of responses with a 100 status returned
-     * by this context since last call of statsReset(). Undefined if
-     * if setStatsOn(false).
-     */
-    public int getResponses2xx() {return _responses2xx;}
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Get the number of responses with a 3xx status returned
-     * by this context since last call of statsReset(). Undefined if
-     * if setStatsOn(false).
-     */
-    public int getResponses3xx() {return _responses3xx;}
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Get the number of responses with a 4xx status returned
-     * by this context since last call of statsReset(). Undefined if
-     * if setStatsOn(false).
-     */
-    public int getResponses4xx() {return _responses4xx;}
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Get the number of responses with a 5xx status returned
-     * by this context since last call of statsReset(). Undefined if
-     * if setStatsOn(false).
-     */
-    public int getResponses5xx() {return _responses5xx;}
-
-
-    /* ------------------------------------------------------------ */
-    /** Log a request and response.
-     * Statistics are also collected by this method.
-     * @param request
-     * @param response
-     */
-    public void log(HttpRequest request,
-                    HttpResponse response,
-                    int length)
-    {
-        if (_statsOn)
-        {
-            synchronized(_statsLock)
-            {
-                if (--_requestsActive<0)
-                    _requestsActive=0;
-
-                if (response!=null)
-                {
-                    switch(response.getStatus()/100)
-                    {
-                      case 1: _responses1xx++;break;
-                      case 2: _responses2xx++;break;
-                      case 3: _responses3xx++;break;
-                      case 4: _responses4xx++;break;
-                      case 5: _responses5xx++;break;
-                    }
-                }
-            }
-        }
-
-        if (_requestLog!=null &&
-            request!=null &&
-            response!=null)
-            _requestLog.log(request,response,length);
-        else if (_httpServer!=null)
-            _httpServer.log(request,response,length);
-    }
-
-    
-
-    /* ------------------------------------------------------------ */
-    /* Class to save scope of nested context calls
-     */
-    private static class Scope 
-    {
-        ClassLoader _classLoader;
-        HttpContext _httpContext;
-    }
-
-    /* 
-     * @see org.mortbay.http.HttpHandler#getName()
-     */
-    public String getName()
-    {
-        return this.getContextPath();
-    }
-
-    /* 
-     * @see org.mortbay.http.HttpHandler#getHttpContext()
-     */
-    public HttpContext getHttpContext()
-    {
-        return this;
-    }
-
-    /* 
-     * @see org.mortbay.http.HttpHandler#initialize(org.mortbay.http.HttpContext)
-     */
-    public void initialize(HttpContext context)
-    {
-        throw new UnsupportedOperationException();
-    }   
-    
-    
-    /**
-     * @return
-     */
-    public Resource getBaseResource()
-    {
-        return _resources.getBaseResource();
-    }
-    /**
-     * @param type
-     * @return
-     */
-    public String getEncodingByMimeType(String type)
-    {
-        return _resources.getEncodingByMimeType(type);
-    }
-    /**
-     * @return
-     */
-    public Map getEncodingMap()
-    {
-        return _resources.getEncodingMap();
-    }
-    /**
-     * @return
-     */
-    public int getMaxCachedFileSize()
-    {
-        return _resources.getMaxCachedFileSize();
-    }
-    /**
-     * @return
-     */
-    public int getMaxCacheSize()
-    {
-        return _resources.getMaxCacheSize();
-    }
-    /**
-     * @param filename
-     * @return
-     */
-    public String getMimeByExtension(String filename)
-    {
-        return _resources.getMimeByExtension(filename);
-    }
-    /**
-     * @return
-     */
-    public Map getMimeMap()
-    {
-        return _resources.getMimeMap();
-    }
-    /**
-     * @param pathInContext
-     * @return
-     * @throws IOException
-     */
-    public Resource getResource(String pathInContext) throws IOException
-    {
-        return _resources.getResource(pathInContext);
-    }
-    /**
-     * @return
-     */
-    public String getResourceBase()
-    {
-        return _resources.getResourceBase();
-    }
-    /**
-     * @param resource
-     * @return
-     */
-    public ResourceMetaData getResourceMetaData(Resource resource)
-    {
-        return _resources.getResourceMetaData(resource);
-    }
-    /**
-     * @param base
-     */
-    public void setBaseResource(Resource base)
-    {
-        _resources.setBaseResource(base);
-    }
-    /**
-     * @param encodingMap
-     */
-    public void setEncodingMap(Map encodingMap)
-    {
-        _resources.setEncodingMap(encodingMap);
-    }
-    /**
-     * @param maxCachedFileSize
-     */
-    public void setMaxCachedFileSize(int maxCachedFileSize)
-    {
-        _resources.setMaxCachedFileSize(maxCachedFileSize);
-    }
-    /**
-     * @param maxCacheSize
-     */
-    public void setMaxCacheSize(int maxCacheSize)
-    {
-        _resources.setMaxCacheSize(maxCacheSize);
-    }
-    /**
-     * @param mimeMap
-     */
-    public void setMimeMap(Map mimeMap)
-    {
-        _resources.setMimeMap(mimeMap);
-    }
-    /**
-     * @param extension
-     * @param type
-     */
-    public void setMimeMapping(String extension, String type)
-    {
-        _resources.setMimeMapping(extension, type);
-    }
-    /**
-     * @param resourceBase
-     */
-    public void setResourceBase(String resourceBase)
-    {
-        _resources.setResourceBase(resourceBase);
-    }
-    /**
-     * @param mimeType
-     * @param encoding
-     */
-    public void setTypeEncoding(String mimeType, String encoding)
-    {
-        _resources.setTypeEncoding(mimeType, encoding);
-    }
-}
diff --git a/apps/jetty/java/src/org/mortbay/http/I2PRequestLog.java b/apps/jetty/java/src/org/mortbay/http/I2PRequestLog.java
deleted file mode 100644
index c83756332481175d81906eebd5f989579d08133a..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/http/I2PRequestLog.java
+++ /dev/null
@@ -1,182 +0,0 @@
-// ========================================================================
-// $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
-// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-
-package org.mortbay.http;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.Locale;
-import java.util.TimeZone;
-
-import javax.servlet.http.Cookie;
-
-import org.apache.commons.logging.Log;
-import org.mortbay.log.LogFactory;
-import org.mortbay.util.DateCache;
-import org.mortbay.util.LogSupport;
-import org.mortbay.util.RolloverFileOutputStream;
-import org.mortbay.util.StringUtil;
-
-
-/* ------------------------------------------------------------ */
-/** NCSA HTTP Request Log.
- *
- * Override log() to put in the requestor's destination hash,
- * instead of 127.0.0.1,
- * which is placed in the X-I2P-DestHash field in the request headers
- * by I2PTunnelHTTPServer.
- *
- * NCSA common or NCSA extended (combined) request log.
- * @version $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
- * @author Tony Thompson
- * @author Greg Wilkins
- */
-public class I2PRequestLog extends NCSARequestLog
-{
-    /* ------------------------------------------------------------ */
-    /** Constructor.
-     */
-    public I2PRequestLog()
-    {
-        super();
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * @param filename Filename, which can be in
-     * rolloverFileOutputStream format
-     * @see org.mortbay.util.RolloverFileOutputStream
-     * @exception IOException 
-     */
-    public I2PRequestLog(String filename)
-        throws IOException
-    {
-        super(filename);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Log a request.
-     * @param request The request
-     * @param response The response to this request.
-     * @param responseLength The bytes written to the response.
-     */
-    public void log(HttpRequest request,
-                    HttpResponse response,
-                    int responseLength)
-    {
-        try{
-            // ignore ignorables
-            if (_ignorePathMap != null &&
-                _ignorePathMap.getMatch(request.getPath()) != null)
-                return;
-
-            // log the rest
-            if (_fileOut==null)
-                return;
-
-            StringBuilder buf = new StringBuilder(160);
-            
-            String addr = request.getField("X-I2P-DestHash");
-            if(addr != null)
-                buf.append(addr).append(".i2p");
-            else
-                buf.append(request.getRemoteAddr());
-            
-            buf.append(" - ");
-            String user = request.getAuthUser();
-            buf.append((user==null)?"-":user);
-            buf.append(" [");
-            buf.append(_logDateCache.format(request.getTimeStamp()));
-            buf.append("] \"");
-            buf.append(request.getMethod());
-            buf.append(' ');
-            buf.append(request.getURI());
-            buf.append(' ');
-            buf.append(request.getVersion());
-            buf.append("\" ");
-            int status=response.getStatus();    
-            buf.append((char)('0'+((status/100)%10)));
-            buf.append((char)('0'+((status/10)%10)));
-            buf.append((char)('0'+(status%10)));
-            if (responseLength>=0)
-            {
-                buf.append(' ');
-                if (responseLength>99999)
-                    buf.append(Integer.toString(responseLength));
-                else
-                {
-                    if (responseLength>9999) 
-                        buf.append((char)('0'+((responseLength/10000)%10)));
-                    if (responseLength>999) 
-                        buf.append((char)('0'+((responseLength/1000)%10)));
-                    if (responseLength>99) 
-                        buf.append((char)('0'+((responseLength/100)%10)));
-                    if (responseLength>9) 
-                        buf.append((char)('0'+((responseLength/10)%10)));
-                    buf.append((char)('0'+(responseLength%10)));
-                }
-                buf.append(' ');
-            }
-            else
-                buf.append(" - ");
-
-            String log =buf.toString();
-            synchronized(_writer)
-            {
-                _writer.write(log);
-                if (isExtended())
-                {
-                    logExtended(request,response,_writer);
-                    if (!getLogCookies())
-                        _writer.write(" -");
-                }
-                
-                if (getLogCookies())
-                {
-                    Cookie[] cookies = request.getCookies();
-                    if (cookies==null || cookies.length==0)
-                        _writer.write(" -");
-                    else
-                    {
-                        _writer.write(" \"");
-                        for (int i=0;i<cookies.length;i++)
-                        {
-                            if (i!=0)
-                                _writer.write(';');
-                            _writer.write(cookies[i].getName());
-                            _writer.write('=');
-                            _writer.write(cookies[i].getValue());
-                        }
-                        _writer.write("\"");
-                    }
-                }
-                
-                if (getLogLatency())
-                    _writer.write(" "+(System.currentTimeMillis()-request.getTimeStamp()));
-                
-                _writer.write(StringUtil.__LINE_SEPARATOR);
-                _writer.flush();
-            }
-        }
-        catch(IOException e)
-        {
-            log.warn(LogSupport.EXCEPTION,e);
-        }
-    }
-
-}
-
diff --git a/apps/jetty/java/src/org/mortbay/http/NCSARequestLog.java b/apps/jetty/java/src/org/mortbay/http/NCSARequestLog.java
deleted file mode 100644
index a898624eaa52f6a69b7912c748519065e1418c4f..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/http/NCSARequestLog.java
+++ /dev/null
@@ -1,505 +0,0 @@
-// ========================================================================
-// $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
-// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-
-package org.mortbay.http;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.util.Locale;
-import java.util.TimeZone;
-
-import javax.servlet.http.Cookie;
-
-import org.apache.commons.logging.Log;
-import org.mortbay.log.LogFactory;
-import org.mortbay.util.DateCache;
-import org.mortbay.util.LogSupport;
-import org.mortbay.util.RolloverFileOutputStream;
-import org.mortbay.util.StringUtil;
-
-
-/* ------------------------------------------------------------ */
-/** NCSA HTTP Request Log.
- * NCSA common or NCSA extended (combined) request log.
- *
- * Taken from 5.1.12 source and modded to change some private vars to protected
- * so we can extend it for I2P.
- *
- * @version $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $
- * @author Tony Thompson
- * @author Greg Wilkins
- */
-public class NCSARequestLog implements RequestLog
-{
-    protected static Log log = LogFactory.getLog(NCSARequestLog.class);
-
-    private String _filename;
-    private boolean _extended;
-    private boolean _append;
-    private int _retainDays;
-    private boolean _closeOut;
-    private boolean _preferProxiedForAddress;
-    private String _logDateFormat="dd/MMM/yyyy:HH:mm:ss ZZZ";
-    private Locale _logLocale=Locale.getDefault();
-    private String _logTimeZone=TimeZone.getDefault().getID();
-    private String[] _ignorePaths;
-    private boolean _logLatency=false;
-    private boolean _logCookies=false;
-    
-    protected transient OutputStream _out;
-    protected transient OutputStream _fileOut;
-    protected transient DateCache _logDateCache;
-    protected transient PathMap _ignorePathMap;
-    protected transient Writer _writer;
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor.
-     */
-    public NCSARequestLog()
-    {
-        _extended=true;
-        _append=true;
-        _retainDays=31;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * @param filename Filename, which can be in
-     * rolloverFileOutputStream format
-     * @see org.mortbay.util.RolloverFileOutputStream
-     * @exception IOException 
-     */
-    public NCSARequestLog(String filename)
-        throws IOException
-    {
-        _extended=true;
-        _append=true;
-        _retainDays=31;
-        setFilename(filename);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Set the log filename.
-     * @see NCSARequestLog#setRetainDays(int)
-     * @param filename The filename to use. If the filename contains the
-     * string "yyyy_mm_dd", then a RolloverFileOutputStream is used and the
-     * log is rolled over nightly and aged according setRetainDays. If no
-     * filename is set or a null filename
-     * passed, then requests are logged to System.err.
-     */
-    public void setFilename(String filename)
-    {
-        if (filename!=null)
-        {
-            filename=filename.trim();
-            if (filename.length()==0)
-                filename=null;
-        }
-        _filename=filename;        
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the log filename.
-     * @see NCSARequestLog#getDatedFilename()
-     * @return The log filename without any date expansion.
-     */
-    public String getFilename()
-    {
-        return _filename;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the dated log filename.
-     * @see NCSARequestLog#getFilename()
-     * @return The log filename with any date encoding expanded.
-     */
-    public String getDatedFilename()
-    {
-        if (_fileOut instanceof RolloverFileOutputStream)
-            return ((RolloverFileOutputStream)_fileOut).getDatedFilename();
-        return null;
-    }
-    
-    
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param format The date format to use within the log file.
-     */
-    public void setLogDateFormat(String format)
-    {
-        _logDateFormat=format;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** 
-     * @return The date format to use within the log file.
-     */
-    public String getLogDateFormat()
-    {
-        return _logDateFormat;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param tz The date format timezone to use within the log file.
-     */
-    public void setLogTimeZone(String tz)
-    {
-        _logTimeZone=tz;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** 
-     * @return The date format timezone to use within the log file.
-     */
-    public String getLogTimeZone()
-    {
-        return _logTimeZone;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** 
-     * @return The number of days to retain rollovered log files.
-     */
-    public int getRetainDays()
-    {
-        return _retainDays;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param retainDays The number of days to retain rollovered log files.
-     */
-    public void setRetainDays(int retainDays)
-    {
-        _retainDays = retainDays;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** 
-     * @return True if NCSA extended format is to be used.
-     */
-    public boolean isExtended()
-    {
-        return _extended;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param e True if NCSA extended format is to be used.
-     */
-    public void setExtended(boolean e)
-    {
-        _extended=e;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** 
-     * @return True if logs are appended to existing log files.
-     */
-    public boolean isAppend()
-    {
-        return _append;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param a True if logs are appended to existing log files.
-     */
-    public void setAppend(boolean a)
-    {
-        _append=a;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * @deprecated ignored
-     */
-    public void setBuffered(boolean b)
-    {}
-    
-    /* ------------------------------------------------------------ */
-    /** Set which paths to ignore.
-     *
-     * @param ignorePaths Array of path specifications to ignore
-     */
-    public void setIgnorePaths(String[] ignorePaths)
-    {
-        // Contributed by  Martin Vilcans (martin@jadestone.se)
-        _ignorePaths = ignorePaths;
-    }
-
-    /* ------------------------------------------------------------ */
-    public String[] getIgnorePaths()
-    {
-        return _ignorePaths;
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Returns the logCookies.
-     */
-    public boolean getLogCookies()
-    {
-        return _logCookies;
-    }
-    /* ------------------------------------------------------------ */
-    /**
-     * @param logCookies The logCookies to set.
-     */
-    public void setLogCookies(boolean logCookies)
-    {
-        _logCookies = logCookies;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * @return Returns true if logging latency
-     */
-    public boolean getLogLatency()
-    {
-        return _logLatency;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * @param logLatency If true, latency is logged at the end of the log line
-     */
-    public void setLogLatency(boolean logLatency)
-    {
-        _logLatency = logLatency;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /**
-    * Prefer to log the proxied-for IP address (if present in
-    * the request header) over the native requester IP address.
-    * Useful in reverse-proxy situations when you'd rather see
-    * the IP address of the host before the most recent proxy
-    * server, as opposed to your own proxy server(s) every time.
-    *
-    * jlrobins@socialserve.com, March 2004.
-    **/
-    public void setPreferProxiedForAddress(boolean value)
-    {
-       _preferProxiedForAddress = value;
-    }
-    
-    /* ------------------------------------------------------------ */
-    public void start()
-        throws Exception
-    {
-        _logDateCache=new DateCache(_logDateFormat,_logLocale);
-        _logDateCache.setTimeZoneID(_logTimeZone);
-        
-        if (_filename != null)
-        {
-            _fileOut=new RolloverFileOutputStream(_filename,_append,_retainDays);
-            _closeOut=true;
-        }
-        else
-            _fileOut=System.err;
-
-        _out=_fileOut;
-
-        if (_ignorePaths!=null && _ignorePaths.length>0)
-        {
-            _ignorePathMap=new PathMap();
-            for (int i=0;i<_ignorePaths.length;i++)
-                _ignorePathMap.put(_ignorePaths[i],_ignorePaths[i]);
-        }
-        else
-            _ignorePathMap=null;
-
-        _writer=new OutputStreamWriter(_out);
-    }
-
-    /* ------------------------------------------------------------ */
-    public boolean isStarted()
-    {
-        return _fileOut!=null;
-    }
-    
-    /* ------------------------------------------------------------ */
-    public void stop()
-    {
-        try{if (_writer!=null)_writer.flush();} catch (IOException e){LogSupport.ignore(log,e);}
-        if (_out!=null && _closeOut)
-            try{_out.close();}catch(IOException e){LogSupport.ignore(log,e);}
-        _out=null;
-        _fileOut=null;
-        _closeOut=false;
-        _logDateCache=null;
-        _writer=null;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Log a request.
-     * @param request The request
-     * @param response The response to this request.
-     * @param responseLength The bytes written to the response.
-     */
-    public void log(HttpRequest request,
-                    HttpResponse response,
-                    int responseLength)
-    {
-        try{
-            // ignore ignorables
-            if (_ignorePathMap != null &&
-                _ignorePathMap.getMatch(request.getPath()) != null)
-                return;
-
-            // log the rest
-            if (_fileOut==null)
-                return;
-
-            StringBuffer buf = new StringBuffer(160);
-            
-            String addr = null;
-            if(_preferProxiedForAddress)
-            {
-                // If header is not present, addr will remain null ...
-                addr = request.getField(HttpFields.__XForwardedFor);
-            }
-            if(addr == null)
-                addr = request.getRemoteAddr();
-            buf.append(addr);
-            
-            buf.append(" - ");
-            String user = request.getAuthUser();
-            buf.append((user==null)?"-":user);
-            buf.append(" [");
-            buf.append(_logDateCache.format(request.getTimeStamp()));
-            buf.append("] \"");
-            buf.append(request.getMethod());
-            buf.append(' ');
-            buf.append(request.getURI());
-            buf.append(' ');
-            buf.append(request.getVersion());
-            buf.append("\" ");
-            int status=response.getStatus();    
-            buf.append((char)('0'+((status/100)%10)));
-            buf.append((char)('0'+((status/10)%10)));
-            buf.append((char)('0'+(status%10)));
-            if (responseLength>=0)
-            {
-                buf.append(' ');
-                if (responseLength>99999)
-                    buf.append(Integer.toString(responseLength));
-                else
-                {
-                    if (responseLength>9999) 
-                        buf.append((char)('0'+((responseLength/10000)%10)));
-                    if (responseLength>999) 
-                        buf.append((char)('0'+((responseLength/1000)%10)));
-                    if (responseLength>99) 
-                        buf.append((char)('0'+((responseLength/100)%10)));
-                    if (responseLength>9) 
-                        buf.append((char)('0'+((responseLength/10)%10)));
-                    buf.append((char)('0'+(responseLength%10)));
-                }
-                buf.append(' ');
-            }
-            else
-                buf.append(" - ");
-
-            String log =buf.toString();
-            synchronized(_writer)
-            {
-                _writer.write(log);
-                if (_extended)
-                {
-                    logExtended(request,response,_writer);
-                    if (!_logCookies)
-                        _writer.write(" -");
-                }
-                
-                if (_logCookies)
-                {
-                    Cookie[] cookies = request.getCookies();
-                    if (cookies==null || cookies.length==0)
-                        _writer.write(" -");
-                    else
-                    {
-                        _writer.write(" \"");
-                        for (int i=0;i<cookies.length;i++)
-                        {
-                            if (i!=0)
-                                _writer.write(';');
-                            _writer.write(cookies[i].getName());
-                            _writer.write('=');
-                            _writer.write(cookies[i].getValue());
-                        }
-                        _writer.write("\"");
-                    }
-                }
-                
-                if (_logLatency)
-                    _writer.write(" "+(System.currentTimeMillis()-request.getTimeStamp()));
-                
-                _writer.write(StringUtil.__LINE_SEPARATOR);
-                _writer.flush();
-            }
-        }
-        catch(IOException e)
-        {
-            log.warn(LogSupport.EXCEPTION,e);
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Log Extended fields.
-     * This method can be extended by a derived class to add extened fields to
-     * each log entry.  It is called by the log method after all standard
-     * fields have been added, but before the line terminator.
-     * Derived implementations should write extra fields to the Writer
-     * provided.
-     * The default implementation writes the referer and user agent.
-     * @param request The request to log.
-     * @param response The response to log.
-     * @param log The writer to write the extra fields to.
-     * @exception IOException Problem writing log
-     */
-    protected void logExtended(HttpRequest request,
-                               HttpResponse response,
-                               Writer log)
-        throws IOException
-    {
-        String referer = request.getField(HttpFields.__Referer);
-        if(referer==null)
-            log.write("\"-\" ");
-        else
-        {
-            log.write('"');
-            log.write(referer);
-            log.write("\" ");
-        }
-        
-        String agent = request.getField(HttpFields.__UserAgent);
-        if(agent==null)
-            log.write("\"-\"");
-        else
-        {
-            log.write('"');
-            log.write(agent);
-            log.write('"');
-        }
-        
-
-    }
-}
-
diff --git a/apps/jetty/java/src/org/mortbay/http/handler/ResourceHandler.java b/apps/jetty/java/src/org/mortbay/http/handler/ResourceHandler.java
deleted file mode 100644
index d1a57159bf0ab75ad44f4c1634f49975141cf3ea..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/http/handler/ResourceHandler.java
+++ /dev/null
@@ -1,809 +0,0 @@
-// ========================================================================
-// $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $
-// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-
-package org.mortbay.http.handler;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Enumeration;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.mortbay.log.LogFactory;
-import org.mortbay.http.HttpException;
-import org.mortbay.http.HttpFields;
-import org.mortbay.http.HttpRequest;
-import org.mortbay.http.HttpResponse;
-import org.mortbay.http.InclusiveByteRange;
-import org.mortbay.http.MultiPartResponse;
-import org.mortbay.http.ResourceCache;
-import org.mortbay.util.CachedResource;
-import org.mortbay.util.IO;
-import org.mortbay.util.LogSupport;
-import org.mortbay.util.Resource;
-import org.mortbay.util.StringMap;
-import org.mortbay.util.TypeUtil;
-import org.mortbay.util.URI;
-
-/* ------------------------------------------------------------ */
-/** Handler to serve files and resources.
- * Serves files from a given resource URL base and implements
- * the GET, HEAD, DELETE, OPTIONS, PUT, MOVE methods and the
- * IfModifiedSince and IfUnmodifiedSince header fields.
- * A simple memory cache is also provided to reduce file I/O.
- * HTTP/1.1 ranges are supported.
- * 
- * @version $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $
- * @author Nuno Pregui?a (sorry, wasn't UTF-8)
- * @author Greg Wilkins
- */
-public class ResourceHandler extends AbstractHttpHandler
-{
-    private static Log log = LogFactory.getLog(ResourceHandler.class);
-
-    /* ----------------------------------------------------------------- */
-    private boolean _acceptRanges=true;
-    private boolean _redirectWelcomeFiles ;
-    private String[] _methods=null;
-    private String _allowed;
-    private boolean _dirAllowed=true;
-    private int _minGzipLength =-1;
-    private StringMap _methodMap = new StringMap();
-    {
-        setAllowedMethods(new String[]
-            {
-                HttpRequest.__GET,
-                HttpRequest.__POST,
-                HttpRequest.__HEAD,
-                HttpRequest.__OPTIONS,
-                HttpRequest.__TRACE
-            });
-    }
-
-    /* ----------------------------------------------------------------- */
-    /** Construct a ResourceHandler.
-     */
-    public ResourceHandler()
-    {}
-
- 
-    /* ----------------------------------------------------------------- */
-    public synchronized void start()
-        throws Exception
-    {        
-        super.start();
-    }
- 
-    /* ----------------------------------------------------------------- */
-    public void stop()
-        throws InterruptedException
-    {
-        super.stop();
-    }
-
-    /* ------------------------------------------------------------ */
-    public String[] getAllowedMethods()
-    {
-        return _methods;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void setAllowedMethods(String[] methods)
-    {
-        StringBuffer b = new StringBuffer();
-        _methods=methods;
-        _methodMap.clear();
-        for (int i=0;i<methods.length;i++)
-        {
-            _methodMap.put(methods[i],methods[i]);
-            if (i>0)
-                b.append(',');
-            b.append(methods[i]);
-        }
-        _allowed=b.toString();
-    }
-
-    /* ------------------------------------------------------------ */
-    public boolean isMethodAllowed(String method)
-    {
-        return _methodMap.get(method)!=null;
-    }
-
-    /* ------------------------------------------------------------ */
-    public String getAllowedString()
-    {
-        return _allowed;
-    }
-    
-    /* ------------------------------------------------------------ */
-    public boolean isDirAllowed()
-    {
-        return _dirAllowed;
-    }
-    
-    /* ------------------------------------------------------------ */
-    public void setDirAllowed(boolean dirAllowed)
-    {
-        _dirAllowed = dirAllowed;
-    }
-    
-    /* ------------------------------------------------------------ */
-    public boolean isAcceptRanges()
-    {
-        return _acceptRanges;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** 
-     * @return True if welcome files are redirected to. False if forward is used.
-     */
-    public boolean getRedirectWelcome()
-    {
-        return _redirectWelcomeFiles;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param redirectWelcome True if welcome files are redirected to. False
-     * if forward is used. 
-     */
-    public void setRedirectWelcome(boolean redirectWelcome)
-    {
-        _redirectWelcomeFiles = redirectWelcome;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set if the handler accepts range requests.
-     * Default is false;
-     * @param ar True if the handler should accept ranges
-     */
-    public void setAcceptRanges(boolean ar)
-    {
-        _acceptRanges=ar;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get minimum content length for GZIP encoding.
-     * @return Minimum length of content for gzip encoding or -1 if disabled.
-     */
-    public int getMinGzipLength()
-    {
-        return _minGzipLength;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set minimum content length for GZIP encoding.
-     * @param minGzipLength If set to a positive integer, then static content
-     * larger than this will be served as gzip content encoded
-     * if a matching resource is found ending with ".gz"
-     */
-    public void setMinGzipLength(int minGzipLength)
-    {
-        _minGzipLength = minGzipLength;
-    }
-
-    
-    /* ------------------------------------------------------------ */
-    /** get Resource to serve.
-     * Map a path to a resource. The default implementation calls
-     * HttpContext.getResource but derived handers may provide
-     * their own mapping.
-     * @param pathInContext The path to find a resource for.
-     * @return The resource to serve.
-     */
-    protected Resource getResource(String pathInContext)
-        throws IOException
-    {
-        return getHttpContext().getResource(pathInContext);
-    }
-    
-    /* ------------------------------------------------------------ */
-    public void handle(String pathInContext,
-                       String pathParams,
-                       HttpRequest request,
-                       HttpResponse response)
-        throws HttpException, IOException
-    {
-        Resource resource = getResource(pathInContext);
-        if (resource==null)
-            return;
-
-        // Is the method allowed?
-        if (!isMethodAllowed(request.getMethod()))
-        {
-            if(log.isDebugEnabled())log.debug("Method not allowed: "+request.getMethod());
-            if (resource.exists())
-            {
-                setAllowHeader(response);
-                response.sendError(HttpResponse.__405_Method_Not_Allowed);
-            }
-            return;
-        }
-
-        // Handle the request
-        try
-        {
-            if(log.isDebugEnabled())log.debug("PATH="+pathInContext+" RESOURCE="+resource);
-            
-            // check filename
-            String method=request.getMethod();
-            if (method.equals(HttpRequest.__GET) ||
-                method.equals(HttpRequest.__POST) ||
-                method.equals(HttpRequest.__HEAD))
-                handleGet(request, response, pathInContext, pathParams, resource);  
-            else if (method.equals(HttpRequest.__PUT))
-                handlePut(request, response, pathInContext, resource);
-            else if (method.equals(HttpRequest.__DELETE))
-                handleDelete(request, response, pathInContext, resource);
-            else if (method.equals(HttpRequest.__OPTIONS))
-                handleOptions(response, pathInContext);
-            else if (method.equals(HttpRequest.__MOVE))
-                handleMove(request, response, pathInContext, resource);
-            else if (method.equals(HttpRequest.__TRACE))
-                handleTrace(request, response);
-            else
-            {
-                if(log.isDebugEnabled())log.debug("Unknown action:"+method);
-                // anything else...
-                try{
-                    if (resource.exists())
-                        response.sendError(HttpResponse.__501_Not_Implemented);
-                }
-                catch(Exception e) {LogSupport.ignore(log,e);}
-            }
-        }
-        catch(IllegalArgumentException e)
-        {
-            LogSupport.ignore(log,e);
-        }
-        finally
-        {
-            if (resource!=null && !(resource instanceof CachedResource))
-                resource.release();
-        }
-    }
-
-    /* ------------------------------------------------------------------- */
-    public void handleGet(HttpRequest request,
-                          HttpResponse response,
-                          String pathInContext,
-                          String pathParams,
-                          Resource resource)
-        throws IOException
-    {
-        if(log.isDebugEnabled())log.debug("Looking for "+resource);
-        
-        if (resource!=null && resource.exists())
-        {            
-            // check if directory
-            if (resource.isDirectory())
-            {
-                if (!pathInContext.endsWith("/") && !pathInContext.equals("/"))
-                {
-                    log.debug("Redirect to directory/");
-                    
-                    String q=request.getQuery();
-                    
-                    // Properly fix URI
-                    URI urifix = new URI(request.getRequestURL().toString());
-                    urifix.setPath(urifix.getPath());
-                    StringBuffer buf = new StringBuffer(urifix.toString());
-                    urifix = null;
-                    
-                    if (q!=null&&q.length()!=0)
-                    {
-                        buf.append('?');
-                        buf.append(q);
-                    }
-                    response.setField(HttpFields.__Location, URI.addPaths(buf.toString(),"/"));
-                    response.setStatus(302);
-                    request.setHandled(true);
-                    return;
-                }
-  
-                // See if index file exists
-                String welcome=getHttpContext().getWelcomeFile(resource);
-                if (welcome!=null)
-                {     
-                    // Forward to the index
-                    String ipath=URI.addPaths(pathInContext,welcome);
-                    if (_redirectWelcomeFiles)
-                    {
-                        // Redirect to the index
-                        ipath=URI.addPaths(getHttpContext().getContextPath(),ipath);
-                        response.setContentLength(0);
-                        response.sendRedirect(ipath);
-                    }
-                    else
-                    {
-                        URI uri=request.getURI();
-                        uri.setPath(URI.addPaths(uri.getPath(),welcome));
-                        getHttpContext().handle(ipath,pathParams,request,response);
-                    }
-                    return;
-                }
-
-                // Check modified dates
-                if (!passConditionalHeaders(request,response,resource))
-                    return;
-                // If we got here, no forward to index took place
-                sendDirectory(request,response,resource,pathInContext.length()>1);
-            }
-            // check if it is a file
-            else if (resource.exists())
-            {
-                // Check modified dates
-                if (!passConditionalHeaders(request,response,resource))
-                    return;
-                sendData(request,response,pathInContext,resource,true);
-            }
-            else
-                // don't know what it is
-                log.warn("Unknown file type");
-        }
-    }
-
- 
-    /* ------------------------------------------------------------ */
-    /* Check modification date headers.
-     */
-    private boolean passConditionalHeaders(HttpRequest request,
-                                           HttpResponse response,
-                                           Resource resource)
-        throws IOException
-    {
-        if (!request.getMethod().equals(HttpRequest.__HEAD))
-        {
-            // If we have meta data for the file
-            // Try a direct match for most common requests. Avoids
-            // parsing the date.
-            ResourceCache.ResourceMetaData metaData =
-                (ResourceCache.ResourceMetaData)resource.getAssociate();
-            if (metaData!=null)
-            {
-                String ifms=request.getField(HttpFields.__IfModifiedSince);
-                String mdlm=metaData.getLastModified();
-                if (ifms!=null && mdlm!=null && ifms.equals(mdlm))
-                {
-                    response.setStatus(HttpResponse.__304_Not_Modified);
-                    request.setHandled(true);
-                    return false;
-                }
-            }
-
-            
-            long date=0;
-            // Parse the if[un]modified dates and compare to resource
-            
-            if ((date=request.getDateField(HttpFields.__IfUnmodifiedSince))>0)
-            {
-                if (resource.lastModified()/1000 > date/1000)
-                {
-                    response.sendError(HttpResponse.__412_Precondition_Failed);
-                    return false;
-                }
-            }
-            
-            if ((date=request.getDateField(HttpFields.__IfModifiedSince))>0)
-            {
-                
-                if (resource.lastModified()/1000 <= date/1000)
-                {
-                    response.setStatus(HttpResponse.__304_Not_Modified);
-                    request.setHandled(true);
-                    return false;
-                }
-            }
-   
-        }
-        return true;
-    }
- 
- 
-    /* ------------------------------------------------------------ */
-    void handlePut(HttpRequest request,
-                   HttpResponse response,
-                   String pathInContext,
-                   Resource resource)
-        throws IOException
-    {
-        if(log.isDebugEnabled())log.debug("PUT "+pathInContext+" in "+resource);
-
-        boolean exists=resource!=null && resource.exists();
-        if (exists &&
-            !passConditionalHeaders(request,response,resource))
-            return;
-        
-        if (pathInContext.endsWith("/"))
-        {
-            if (!exists)
-            {
-                if (!resource.getFile().mkdirs())
-                    response.sendError(HttpResponse.__403_Forbidden, "Directories could not be created");
-                else
-                {
-                    request.setHandled(true);
-                    response.setStatus(HttpResponse.__201_Created);
-                    response.commit();
-                }
-            }
-            else
-            {
-                request.setHandled(true);
-                response.setStatus(HttpResponse.__200_OK);
-                response.commit();
-            }
-        }
-        else
-        {
-            try
-            {
-                int toRead = request.getContentLength();
-                InputStream in = request.getInputStream();
-                OutputStream out = resource.getOutputStream();
-                if (toRead>=0)
-                    IO.copy(in,out,toRead);
-                else
-                    IO.copy(in,out);
-                out.close();
-                request.setHandled(true);
-                response.setStatus(exists
-                                   ?HttpResponse.__200_OK
-                                   :HttpResponse.__201_Created);
-                response.commit();
-            }
-            catch (Exception ex)
-            {
-                log.warn(LogSupport.EXCEPTION,ex);
-                response.sendError(HttpResponse.__403_Forbidden,
-                                   ex.getMessage());
-            }
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    void handleDelete(HttpRequest request,
-                      HttpResponse response,
-                      String pathInContext,
-                      Resource resource)
-        throws IOException
-    {
-        if(log.isDebugEnabled())log.debug("DELETE "+pathInContext+" from "+resource);  
- 
-        if (!resource.exists() ||
-            !passConditionalHeaders(request,response,resource))
-            return;
- 
-        try
-        {
-            // delete the file
-            if (resource.delete())
-                response.setStatus(HttpResponse.__204_No_Content);
-            else
-                response.sendError(HttpResponse.__403_Forbidden);
-
-            // Send response
-            request.setHandled(true);
-        }
-        catch (SecurityException sex)
-        {
-            log.warn(LogSupport.EXCEPTION,sex);
-            response.sendError(HttpResponse.__403_Forbidden, sex.getMessage());
-        }
-    }
-
- 
-    /* ------------------------------------------------------------ */
-    void handleMove(HttpRequest request,
-                    HttpResponse response,
-                    String pathInContext,
-                    Resource resource)
-        throws IOException
-    {
-        if (!resource.exists() || !passConditionalHeaders(request,response,resource))
-            return;
-
- 
-        String newPath = URI.canonicalPath(request.getField("New-uri"));
-        if (newPath==null)
-        {
-            response.sendError(HttpResponse.__405_Method_Not_Allowed,
-                               "Bad new uri");
-            return;
-        }
-
-        String contextPath = getHttpContext().getContextPath();
-        if (contextPath!=null && !newPath.startsWith(contextPath))
-        {
-            response.sendError(HttpResponse.__405_Method_Not_Allowed,
-                               "Not in context");
-            return;
-        }
-        
-
-        // Find path
-        try
-        {
-            // TODO - Check this
-            String newInfo=newPath;
-            if (contextPath!=null)
-                newInfo=newInfo.substring(contextPath.length());
-            Resource newFile = getHttpContext().getBaseResource().addPath(newInfo);
-     
-            if(log.isDebugEnabled())log.debug("Moving "+resource+" to "+newFile);
-            resource.renameTo(newFile);
-    
-            response.setStatus(HttpResponse.__204_No_Content);
-            request.setHandled(true);
-        }
-        catch (Exception ex)
-        {
-            log.warn(LogSupport.EXCEPTION,ex);
-            setAllowHeader(response);
-            response.sendError(HttpResponse.__405_Method_Not_Allowed,
-                               "Error:"+ex);
-            return;
-        }
-    }
- 
-    /* ------------------------------------------------------------ */
-    void handleOptions(HttpResponse response, String pathInContext)
-        throws IOException
-    {
-        if ("*".equals(pathInContext))
-            return;
-        setAllowHeader(response);
-        response.commit();
-    }
- 
-    /* ------------------------------------------------------------ */
-    void setAllowHeader(HttpResponse response)
-    {
-        response.setField(HttpFields.__Allow, getAllowedString());
-    }
-    
-    /* ------------------------------------------------------------ */
-    public void writeHeaders(HttpResponse response,Resource resource, long count)
-        throws IOException
-    {
-        ResourceCache.ResourceMetaData metaData =
-            (ResourceCache.ResourceMetaData)resource.getAssociate();
-
-        response.setContentType(metaData.getMimeType());
-        if (count != -1)
-        {
-            if (count==resource.length())
-                response.setField(HttpFields.__ContentLength,metaData.getLength());
-            else
-                response.setContentLength((int)count);
-        }
-
-        response.setField(HttpFields.__LastModified,metaData.getLastModified());
-        
-        if (_acceptRanges && response.getHttpRequest().getDotVersion()>0)
-            response.setField(HttpFields.__AcceptRanges,"bytes");
-    }
-
-    /* ------------------------------------------------------------ */
-    public void sendData(HttpRequest request,
-                         HttpResponse response,
-                         String pathInContext,
-                         Resource resource,
-                         boolean writeHeaders)
-        throws IOException
-    {
-        long resLength=resource.length();
-        
-        //  see if there are any range headers
-        Enumeration reqRanges =
-            request.getDotVersion()>0
-            ?request.getFieldValues(HttpFields.__Range)
-            :null;
-        
-        if (!writeHeaders || reqRanges == null || !reqRanges.hasMoreElements())
-        {
-            // look for a gziped content.
-            Resource data=resource;
-            if (_minGzipLength>0)
-            {
-                String accept=request.getField(HttpFields.__AcceptEncoding);
-                if (accept!=null && resLength>_minGzipLength &&
-                    !pathInContext.endsWith(".gz"))
-                {
-                    Resource gz = getHttpContext().getResource(pathInContext+".gz");
-                    if (gz.exists() && accept.indexOf("gzip")>=0)
-                    {
-                        if(log.isDebugEnabled())log.debug("gzip="+gz);
-                        response.setField(HttpFields.__ContentEncoding,"gzip");
-                        data=gz;
-                        resLength=data.length();
-                    }
-                }
-            }
-            writeHeaders(response,resource,resLength);
-            
-            request.setHandled(true);
-            OutputStream out = response.getOutputStream();
-            data.writeTo(out,0,resLength);
-            return;
-        }
-            
-        // Parse the satisfiable ranges
-        List ranges =InclusiveByteRange.satisfiableRanges(reqRanges,resLength);
-        if(log.isDebugEnabled())log.debug("ranges: " + reqRanges + " == " + ranges);
-        
-        //  if there are no satisfiable ranges, send 416 response
-        if (ranges==null || ranges.size()==0)
-        {
-            log.debug("no satisfiable ranges");
-            writeHeaders(response, resource, resLength);
-            response.setStatus(HttpResponse.__416_Requested_Range_Not_Satisfiable);
-            response.setReason((String)HttpResponse.__statusMsg
-                               .get(TypeUtil.newInteger(HttpResponse.__416_Requested_Range_Not_Satisfiable)));
-
-            response.setField(HttpFields.__ContentRange, 
-                              InclusiveByteRange.to416HeaderRangeString(resLength));
-            
-            OutputStream out = response.getOutputStream();
-            resource.writeTo(out,0,resLength);
-            request.setHandled(true);
-            return;
-        }
-
-        
-        //  if there is only a single valid range (must be satisfiable 
-        //  since were here now), send that range with a 216 response
-        if ( ranges.size()== 1)
-        {
-            InclusiveByteRange singleSatisfiableRange =
-                (InclusiveByteRange)ranges.get(0);
-            if(log.isDebugEnabled())log.debug("single satisfiable range: " + singleSatisfiableRange);
-            long singleLength = singleSatisfiableRange.getSize(resLength);
-            writeHeaders(response,resource,singleLength);
-            response.setStatus(HttpResponse.__206_Partial_Content);
-            response.setReason((String)HttpResponse.__statusMsg
-                               .get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
-            response.setField(HttpFields.__ContentRange, 
-                              singleSatisfiableRange.toHeaderRangeString(resLength));
-            OutputStream out = response.getOutputStream();
-            resource.writeTo(out,
-                             singleSatisfiableRange.getFirst(resLength), 
-                             singleLength);
-            request.setHandled(true);
-            return;
-        }
-
-        
-        //  multiple non-overlapping valid ranges cause a multipart
-        //  216 response which does not require an overall 
-        //  content-length header
-        //
-        ResourceCache.ResourceMetaData metaData =
-            (ResourceCache.ResourceMetaData)resource.getAssociate();
-        String encoding = metaData.getMimeType();
-        MultiPartResponse multi = new MultiPartResponse(response);
-        response.setStatus(HttpResponse.__206_Partial_Content);
-        response.setReason((String)HttpResponse.__statusMsg
-                           .get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content)));
-
-	// If the request has a "Request-Range" header then we need to
-	// send an old style multipart/x-byteranges Content-Type. This
-	// keeps Netscape and acrobat happy. This is what Apache does.
-	String ctp;
-	if (request.containsField(HttpFields.__RequestRange))
-	    ctp = "multipart/x-byteranges; boundary=";
-	else
-	    ctp = "multipart/byteranges; boundary=";
-	response.setContentType(ctp+multi.getBoundary());
-
-        InputStream in=(resource instanceof CachedResource)
-            ?null:resource.getInputStream();
-        OutputStream out = response.getOutputStream();
-        long pos=0;
-            
-        for (int i=0;i<ranges.size();i++)
-        {
-            InclusiveByteRange ibr = (InclusiveByteRange) ranges.get(i);
-            String header=HttpFields.__ContentRange+": "+
-                ibr.toHeaderRangeString(resLength);
-            if(log.isDebugEnabled())log.debug("multi range: "+encoding+" "+header);
-            multi.startPart(encoding,new String[]{header});
-
-            long start=ibr.getFirst(resLength);
-            long size=ibr.getSize(resLength);
-            if (in!=null)
-            {
-                // Handle non cached resource
-                if (start<pos)
-                {
-                    in.close();
-                    in=resource.getInputStream();
-                    pos=0;
-                }
-                if (pos<start)
-                {
-                    in.skip(start-pos);
-                    pos=start;
-                }
-                IO.copy(in,out,size);
-                pos+=size;
-            }
-            else
-                // Handle cached resource
-                resource.writeTo(out,start,size);
-            
-        }
-        if (in!=null)
-            in.close();
-        multi.close();
-
-        request.setHandled(true);
-
-        return;
-    }
-
-
-    /* ------------------------------------------------------------------- */
-    void sendDirectory(HttpRequest request,
-                       HttpResponse response,
-                       Resource resource,
-                       boolean parent)
-        throws IOException
-    {
-        if (!_dirAllowed)
-        {
-            response.sendError(HttpResponse.__403_Forbidden);
-            return;
-        }
-        
-        request.setHandled(true);
-        
-        if(log.isDebugEnabled())log.debug("sendDirectory: "+resource);
-        byte[] data=null;
-        if (resource instanceof CachedResource)
-            data=((CachedResource)resource).getCachedData();
-        
-        if (data==null)
-        {
-            String base = URI.addPaths(request.getPath(),"/");
-            String dir = resource.getListHTML(URI.encodePath(base),parent);
-            if (dir==null)
-            {
-                response.sendError(HttpResponse.__403_Forbidden,
-                                   "No directory");
-                return;
-            }
-            data=dir.getBytes("UTF8");
-            if (resource instanceof CachedResource)
-                ((CachedResource)resource).setCachedData(data);
-        }
-        
-        response.setContentType("text/html; charset=UTF8");
-        response.setContentLength(data.length);
-        
-        if (request.getMethod().equals(HttpRequest.__HEAD))
-        {
-            response.commit();
-            return;
-        }
-        
-        response.getOutputStream().write(data,0,data.length);
-        response.commit();
-    }
-}
-
-
-
diff --git a/apps/jetty/java/src/org/mortbay/jetty/Server.java b/apps/jetty/java/src/org/mortbay/jetty/Server.java
deleted file mode 100644
index 409f8a529d4c6496d3284b23bbaf75c358a45b7c..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/jetty/Server.java
+++ /dev/null
@@ -1,617 +0,0 @@
-// ========================================================================
-// $Id: Server.java,v 1.40 2005/10/21 13:52:11 gregwilkins Exp $
-// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-
-package org.mortbay.jetty;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-
-import org.apache.commons.logging.Log;
-import org.mortbay.log.LogFactory;
-import org.mortbay.http.HttpContext;
-import org.mortbay.http.HttpServer;
-import org.mortbay.jetty.servlet.ServletHttpContext;
-import org.mortbay.jetty.servlet.WebApplicationContext;
-import org.mortbay.util.LogSupport;
-import org.mortbay.util.Resource;
-import org.mortbay.xml.XmlConfiguration;
-
-
-/* ------------------------------------------------------------ */
-/** The Jetty HttpServer.
- *
- * This specialization of org.mortbay.http.HttpServer adds knowledge
- * about servlets and their specialized contexts.   It also included
- * support for initialization from xml configuration files
- * that follow the XmlConfiguration dtd.
- *
- * HttpContexts created by Server are of the type
- * org.mortbay.jetty.servlet.ServletHttpContext unless otherwise
- * specified.
- *
- * This class also provides a main() method which starts a server for
- * each config file passed on the command line.  If the system
- * property JETTY_NO_SHUTDOWN_HOOK is not set to true, then a shutdown
- * hook is thread is registered to stop these servers.   
- *
- * @see org.mortbay.xml.XmlConfiguration
- * @see org.mortbay.jetty.servlet.ServletHttpContext
- * @version $Revision: 1.40 $
- * @author Greg Wilkins (gregw)
- */
-public class Server extends HttpServer 
-{
-    static Log log = LogFactory.getLog(Server.class);
-    private String[] _webAppConfigurationClassNames = 
-        new String[]{"org.mortbay.jetty.servlet.XMLConfiguration", "org.mortbay.jetty.servlet.JettyWebConfiguration"};
-    private String _configuration;
-    private String _rootWebApp;
-    private static ShutdownHookThread hookThread = new ShutdownHookThread();
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     */
-    public Server()
-    {
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * @param configuration The filename or URL of the XML
-     * configuration file.
-     */
-    public Server(String configuration)
-        throws IOException
-    {
-        this(Resource.newResource(configuration).getURL());
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * @param configuration The filename or URL of the XML
-     * configuration file.
-     */
-    public Server(Resource configuration)
-        throws IOException
-    {
-        this(configuration.getURL());
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * @param configuration The filename or URL of the XML
-     * configuration file.
-     */
-    public Server(URL configuration)
-        throws IOException
-    {
-        _configuration=configuration.toString();
-        Server.hookThread.add(this);
-        try
-        {
-            XmlConfiguration config=new XmlConfiguration(configuration);
-            config.configure(this);
-        }
-        catch(IOException e)
-        {
-            throw e;
-        }
-        catch(InvocationTargetException e)
-        {
-            log.warn(LogSupport.EXCEPTION,e.getTargetException());
-            throw new IOException("Jetty configuration problem: "+e.getTargetException());
-        }
-        catch(Exception e)
-        {
-            log.warn(LogSupport.EXCEPTION,e);
-            throw new IOException("Jetty configuration problem: "+e);
-        }
-    }
-
-    /* ------------------------------------------------------------ */
-    public boolean getStopAtShutdown()
-    {
-        return hookThread.contains(this);
-    }
-    
-    /* ------------------------------------------------------------ */
-    public void setStopAtShutdown(boolean stop)
-    {
-        if (stop)
-            hookThread.add(this);
-        else
-            hookThread.remove(this);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the root webapp name.
-     * @return The name of the root webapp (eg. "root" for root.war). 
-     */
-    public String getRootWebApp()
-    {
-        return _rootWebApp;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the root webapp name.
-     * @param rootWebApp The name of the root webapp (eg. "root" for root.war). 
-     */
-    public void setRootWebApp(String rootWebApp)
-    {
-        _rootWebApp = rootWebApp;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /**  Configure the server from an XML file.
-     * @param configuration The filename or URL of the XML
-     * configuration file.
-     */
-    public void configure(String configuration)
-        throws IOException
-    {
-
-        URL url=Resource.newResource(configuration).getURL();
-        if (_configuration!=null && _configuration.equals(url.toString()))
-            return;
-        if (_configuration!=null)
-            throw new IllegalStateException("Already configured with "+_configuration);
-        try
-        {
-            XmlConfiguration config=new XmlConfiguration(url);
-            _configuration=url.toString();
-            config.configure(this);
-        }
-        catch(IOException e)
-        {
-            throw e;
-        }
-        catch(Exception e)
-        {
-            log.warn(LogSupport.EXCEPTION,e);
-            throw new IOException("Jetty configuration problem: "+e);
-        }
-    }
-    
-    /* ------------------------------------------------------------ */
-    public String getConfiguration()
-    {
-        return _configuration;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Create a new ServletHttpContext.
-     * Ths method is called by HttpServer to creat new contexts.  Thus
-     * calls to addContext or getContext that result in a new Context
-     * being created will return an
-     * org.mortbay.jetty.servlet.ServletHttpContext instance.
-     * @return ServletHttpContext
-     */
-    protected HttpContext newHttpContext()
-    {
-        return new ServletHttpContext();
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Create a new WebApplicationContext.
-     * Ths method is called by Server to creat new contexts for web 
-     * applications.  Thus calls to addWebApplication that result in 
-     * a new Context being created will return an correct class instance.
-     * Derived class can override this method to create instance of its
-     * own class derived from WebApplicationContext in case it needs more
-     * functionality.
-     * @param webApp The Web application directory or WAR file.
-     * @return WebApplicationContext
-     */
-    protected WebApplicationContext newWebApplicationContext(
-       String webApp
-    )
-    {
-        return new WebApplicationContext(webApp);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Add Web Application.
-     * @param contextPathSpec The context path spec. Which must be of
-     * the form / or /path/*
-     * @param webApp The Web application directory or WAR file.
-     * @return The WebApplicationContext
-     * @exception IOException 
-     */
-    public WebApplicationContext addWebApplication(String contextPathSpec,
-                                                   String webApp)
-        throws IOException
-    {
-        return addWebApplication(null,contextPathSpec,webApp);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Add Web Application.
-     * @param virtualHost Virtual host name or null
-     * @param contextPathSpec The context path spec. Which must be of
-     * the form / or /path/*
-     * @param webApp The Web application directory or WAR file.
-     * @return The WebApplicationContext
-     * @exception IOException 
-     */
-    public WebApplicationContext addWebApplication(String virtualHost,
-                                                   String contextPathSpec,
-                                                   String webApp)
-        throws IOException
-    {
-        WebApplicationContext appContext =
-            newWebApplicationContext(webApp);
-        appContext.setContextPath(contextPathSpec);
-        addContext(virtualHost,appContext);
-        if(log.isDebugEnabled())log.debug("Web Application "+appContext+" added");
-        return appContext;
-    }
-
-    
-    /* ------------------------------------------------------------ */
-    /**  Add Web Applications.
-     * Add auto webapplications to the server.  The name of the
-     * webapp directory or war is used as the context name. If a
-     * webapp is called "root" it is added at "/".
-     * @param webapps Directory file name or URL to look for auto webapplication.
-     * @exception IOException 
-     */
-    public WebApplicationContext[] addWebApplications(String webapps)
-        throws IOException
-    {
-        return addWebApplications(null,webapps,null,false);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /**  Add Web Applications.
-     * Add auto webapplications to the server.  The name of the
-     * webapp directory or war is used as the context name. If the
-     * webapp matches the rootWebApp it is added as the "/" context.
-     * @param host Virtual host name or null
-     * @param webapps Directory file name or URL to look for auto webapplication.
-     * @exception IOException 
-     */
-    public WebApplicationContext[] addWebApplications(String host,
-                                                      String webapps)
-        throws IOException
-    {
-        return addWebApplications(host,webapps,null,false);
-    }
-        
-    /* ------------------------------------------------------------ */
-    /**  Add Web Applications.
-     * Add auto webapplications to the server.  The name of the
-     * webapp directory or war is used as the context name. If the
-     * webapp matches the rootWebApp it is added as the "/" context.
-     * @param host Virtual host name or null
-     * @param webapps Directory file name or URL to look for auto
-     * webapplication.
-     * @param extract If true, extract war files
-     * @exception IOException 
-     */
-    public WebApplicationContext[] addWebApplications(String host,
-                                                      String webapps,
-                                                      boolean extract)
-        throws IOException
-    {
-        return addWebApplications(host,webapps,null,extract);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /**  Add Web Applications.
-     * Add auto webapplications to the server.  The name of the
-     * webapp directory or war is used as the context name. If the
-     * webapp matches the rootWebApp it is added as the "/" context.
-     * @param host Virtual host name or null
-     * @param webapps Directory file name or URL to look for auto
-     * webapplication.
-     * @param defaults The defaults xml filename or URL which is
-     * loaded before any in the web app. Must respect the web.dtd.
-     * If null the default defaults file is used. If the empty string, then
-     * no defaults file is used.
-     * @param extract If true, extract war files
-     * @exception IOException 
-     */
-    public WebApplicationContext[] addWebApplications(String host,
-                                                      String webapps,
-                                                      String defaults,
-                                                      boolean extract)
-        throws IOException
-    {
-        return addWebApplications(host,webapps,defaults,extract,true,null);
-    }
-
-    /* ------------------------------------------------------------ */
-    /**  Add Web Applications.
-     * Add auto webapplications to the server.  The name of the
-     * webapp directory or war is used as the context name. If the
-     * webapp matches the rootWebApp it is added as the "/" context.
-     * @param host Virtual host name or null
-     * @param webapps Directory file name or URL to look for auto
-     * webapplication.
-     * @param defaults The defaults xml filename or URL which is
-     * loaded before any in the web app. Must respect the web.dtd.
-     * If null the default defaults file is used. If the empty string, then
-     * no defaults file is used.
-     * @param extract If true, extract war files
-     * @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications
-     * @exception IOException
-     */
-    public WebApplicationContext[] addWebApplications(String host,
-                                                      String webapps,
-                                                      String defaults,
-                                                      boolean extract,
-						      boolean java2CompliantClassLoader)
-                throws IOException
-    {
-        return addWebApplications(host,webapps,defaults,extract,java2CompliantClassLoader,null);
-
-    }
-    /* ------------------------------------------------------------ */
-    /**  Add Web Applications.
-     * Add auto webapplications to the server.  The name of the
-     * webapp directory or war is used as the context name. If the
-     * webapp matches the rootWebApp it is added as the "/" context.
-     * @param host Virtual host name or null
-     * @param webapps Directory file name or URL to look for auto
-     * webapplication.
-     * @param defaults The defaults xml filename or URL which is
-     * loaded before any in the web app. Must respect the web.dtd.
-     * If null the default defaults file is used. If the empty string, then
-     * no defaults file is used.
-     * @param extract If true, extract war files
-     * @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications
-     * @param Attributes[] A set of attributes to pass to setAttribute, format is first item is the key, second item is the value.
-     * @exception IOException 
-     */
-    public WebApplicationContext[] addWebApplications(String host,
-                                                      String webapps,
-                                                      String defaults,
-                                                      boolean extract,
-						      boolean java2CompliantClassLoader,
-						      String Attributes[])
-        throws IOException
-    {
-        ArrayList wacs = new ArrayList();
-        Resource r=Resource.newResource(webapps);
-        if (!r.exists())
-            throw new IllegalArgumentException("No such webapps resource "+r);
-        
-        if (!r.isDirectory())
-            throw new IllegalArgumentException("Not directory webapps resource "+r);
-        if(Attributes != null) {
-            if(((Attributes.length / 2) * 2) != Attributes.length) {
-                throw new IllegalArgumentException("Attributes must be in pairs of key,value.");
-            }
-        }
-        String[] files=r.list();
-        
-        for (int f=0;files!=null && f<files.length;f++)
-        {
-            String context=files[f];
-            
-            if (context.equalsIgnoreCase("CVS/") ||
-                context.equalsIgnoreCase("CVS") ||
-                context.startsWith("."))
-                continue;
-
-            
-            String app = r.addPath(r.encode(files[f])).toString();
-            if (context.toLowerCase().endsWith(".war") ||
-                context.toLowerCase().endsWith(".jar"))
-            {
-                context=context.substring(0,context.length()-4);
-                Resource unpacked=r.addPath(context);
-                if (unpacked!=null && unpacked.exists() && unpacked.isDirectory())
-                    continue;
-            }
-            
-            if (_rootWebApp!=null && (context.equals(_rootWebApp)||context.equals(_rootWebApp+"/")))
-                context="/";
-            else
-                context="/"+context;
-
-            WebApplicationContext wac= addWebApplication(host,
-                                                         context,
-                                                         app);
-            wac.setExtractWAR(extract);
-	    wac.setClassLoaderJava2Compliant(java2CompliantClassLoader);
-            if (defaults!=null)
-            {
-                if (defaults.length()==0)
-                    wac.setDefaultsDescriptor(null);
-                else
-                    wac.setDefaultsDescriptor(defaults);
-            }
-            if(Attributes != null) {
-                for(int i = 0; i < Attributes.length; i++, i++) {
-                    wac.setAttribute(Attributes[i],Attributes[i + 1]);
-                }
-            }
-            wacs.add(wac);
-        }
-
-        return (WebApplicationContext[])wacs.toArray(new WebApplicationContext[wacs.size()]);
-    }
-
-    
-    /* ------------------------------------------------------------ */
-    /** setWebApplicationConfigurationClasses
-     * Set up the list of classnames of WebApplicationContext.Configuration
-     * implementations that will be applied to configure every webapp.
-     * The list can be overridden by individual WebApplicationContexts.
-     * @param configurationClasses
-     */
-    public void setWebApplicationConfigurationClassNames (String[] configurationClassNames)
-    {
-        if (configurationClassNames != null)
-        {
-            _webAppConfigurationClassNames = new String[configurationClassNames.length];
-            System.arraycopy(configurationClassNames, 0, _webAppConfigurationClassNames, 0, configurationClassNames.length);
-        }
-    }
-    
-    public String[] getWebApplicationConfigurationClassNames ()
-    {
-        return _webAppConfigurationClassNames;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /* ------------------------------------------------------------ */
-    /* ------------------------------------------------------------ */
-    public static void main(String[] arg)
-    {
-        String[] dftConfig={"etc/jetty.xml"};
-        
-        if (arg.length==0)
-        {
-            log.info("Using default configuration: etc/jetty.xml");
-            arg=dftConfig;
-        }
-
-        final Server[] servers=new Server[arg.length];
-
-        // create and start the servers.
-        for (int i=0;i<arg.length;i++)
-        {
-            try
-            {
-                servers[i] = new Server(arg[i]);
-                servers[i].setStopAtShutdown(true);
-                servers[i].start();
-
-            }
-            catch(Exception e)
-            {
-                log.warn(LogSupport.EXCEPTION,e);
-            }
-        }
-        
-        // create and start the servers.
-        for (int i=0;i<arg.length;i++)
-        {
-            try{servers[i].join();}
-            catch (Exception e){LogSupport.ignore(log,e);}
-        }
-    }
-    
-   /**
-    * ShutdownHook thread for stopping all servers.
-    * 
-    * Thread is hooked first time list of servers is changed.
-    */
-  private static class ShutdownHookThread extends Thread {
-    private boolean hooked = false;
-    private ArrayList servers = new ArrayList();
-
-    /**
-     * Hooks this thread for shutdown.
-     * @see java.lang.Runtime#addShutdownHook(java.lang.Thread)
-     */
-    private void createShutdownHook() {
-      if (!Boolean.getBoolean("JETTY_NO_SHUTDOWN_HOOK") && !hooked) {
-        try {
-          Method shutdownHook = java.lang.Runtime.class.getMethod("addShutdownHook",
-              new Class[] { java.lang.Thread.class });
-          shutdownHook.invoke(Runtime.getRuntime(), new Object[] { this });
-          this.hooked = true;
-        } catch (Exception e) {
-          if (log.isDebugEnabled()) log.debug("No shutdown hook in JVM ", e);
-        }
-      }
-    }
-
-    /**
-     * Add Server to servers list.
-     */
-    public boolean add(Server server) {
-      createShutdownHook();
-      return this.servers.add(server);
-    }
-    
-    /**
-     * Contains Server in servers list?
-     */
-    public boolean contains(Server server) {
-      return this.servers.contains(server);
-    }
-
-    /**
-     * Append all Servers from Collection
-     */
-    public boolean addAll(Collection c) {
-      createShutdownHook();
-      return this.servers.addAll(c);
-    }
-
-    /**
-     * Clear list of Servers.
-     */
-    public void clear() {
-      createShutdownHook();
-      this.servers.clear();
-    }
-
-    /**
-     * Remove Server from list.
-     */
-    public boolean remove(Server server) {
-      createShutdownHook();
-      return this.servers.remove(server);
-    }
-
-    /**
-     * Remove all Servers in Collection from list.
-     */
-    public boolean removeAll(Collection c) {
-      createShutdownHook();
-      return this.servers.removeAll(c);
-    }
-
-    /**
-     * Stop all Servers in list.
-     */
-    public void run() {
-      setName("Shutdown");
-      log.info("Shutdown hook executing");
-      Iterator it = servers.iterator();
-      while (it.hasNext()) {
-        Server svr = (Server) it.next();
-        if (svr == null) continue;
-        try {
-          svr.stop();
-        } catch (Exception e) {
-          log.warn(LogSupport.EXCEPTION, e);
-        }
-        log.info("Shutdown hook complete");
-
-        // Try to avoid JVM crash
-        try {
-          Thread.sleep(1000);
-        } catch (Exception e) {
-          log.warn(LogSupport.EXCEPTION, e);
-        }
-      }
-    }
-  }
-}
-
-
-
-
diff --git a/apps/jetty/java/src/org/mortbay/util/FileResource.java b/apps/jetty/java/src/org/mortbay/util/FileResource.java
deleted file mode 100644
index 8788f14fdfb59228ee3c40c0fd351ebb90a2d9b6..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/util/FileResource.java
+++ /dev/null
@@ -1,352 +0,0 @@
-// ========================================================================
-// $Id: FileResource.java,v 1.31 2006/01/04 13:55:31 gregwilkins Exp $
-// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-package org.mortbay.util;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.Permission;
-
-import org.apache.commons.logging.Log;
-import org.mortbay.log.LogFactory;
-
-
-/* ------------------------------------------------------------ */
-/** File Resource.
- *
- * Handle resources of implied or explicit file type.
- * This class can check for aliasing in the filesystem (eg case
- * insensitivity).  By default this is turned on if the platform does
- * not have the "/" path separator, or it can be controlled with the
- * "org.mortbay.util.FileResource.checkAliases" system parameter.
- *
- * If alias checking is turned on, then aliased resources are
- * treated as if they do not exist, nor can they be created.
- *
- * @version $Revision: 1.31 $
- * @author Greg Wilkins (gregw)
- */
-public class FileResource extends URLResource
-{
-	private static Log log = LogFactory.getLog(Credential.class);
-    private static boolean __checkAliases;
-    static
-    {
-        __checkAliases=
-            "true".equalsIgnoreCase
-            (System.getProperty("org.mortbay.util.FileResource.checkAliases","true"));
- 
-       if (__checkAliases)
-            log.info("Checking Resource aliases");
-    }
-    
-    /* ------------------------------------------------------------ */
-    private File _file;
-    private transient URL _alias=null;
-    private transient boolean _aliasChecked=false;
-
-    /* ------------------------------------------------------------------------------- */
-    /** setCheckAliases.
-     * @param checkAliases True of resource aliases are to be checked for (eg case insensitivity or 8.3 short names) and treated as not found.
-     */
-    public static void setCheckAliases(boolean checkAliases)
-    {
-        __checkAliases=checkAliases;
-    }
-
-    /* ------------------------------------------------------------------------------- */
-    /** getCheckAliases.
-     * @return True of resource aliases are to be checked for (eg case insensitivity or 8.3 short names) and treated as not found.
-     */
-    public static boolean getCheckAliases()
-    {
-        return __checkAliases;
-    }
-    
-    /* -------------------------------------------------------- */
-    FileResource(URL url)
-        throws IOException, URISyntaxException
-    {
-        super(url,null);
-
-        try
-        {
-            // Try standard API to convert URL to file.
-            _file =new File(new URI(url.toString()));
-        }
-        catch (Exception e)
-        {
-            LogSupport.ignore(log,e);
-            try
-            {
-                // Assume that File.toURL produced unencoded chars. So try
-                // encoding them.
-                String urls=
-                    "file:"+org.mortbay.util.URI.encodePath(url.toString().substring(5));
-                _file =new File(new URI(urls));
-            }
-            catch (Exception e2)
-            {
-                LogSupport.ignore(log,e2);
-
-                // Still can't get the file.  Doh! try good old hack!
-                checkConnection();
-                Permission perm = _connection.getPermission();
-                _file = new File(perm==null?url.getFile():perm.getName());
-            }
-        }
-        
-        if (_file.isDirectory() && !_urlString.endsWith("/"))
-            _urlString=_urlString+"/";
-    }
-    
-    /* -------------------------------------------------------- */
-    FileResource(URL url, URLConnection connection, File file)
-    {
-        super(url,connection);
-        _file=file;
-        if (_file.isDirectory() && !_urlString.endsWith("/"))
-            _urlString=_urlString+"/";
-    }
-    
-    /* -------------------------------------------------------- */
-    public Resource addPath(String path)
-        throws IOException,MalformedURLException
-    {
-        FileResource r=null;
-
-        if (!isDirectory())
-        {
-            r=(FileResource)super.addPath(path);
-        }
-        else
-        {
-            path = org.mortbay.util.URI.canonicalPath(path);
-            
-            // treat all paths being added as relative
-            String rel=path;
-            if (path.startsWith("/"))
-                rel = path.substring(1);
-            
-            File newFile = new File(_file,rel.replace('/', File.separatorChar));
-            r=new FileResource(newFile.toURI().toURL(),null,newFile);
-        }
-        
-        String encoded=org.mortbay.util.URI.encodePath(path);
-        int expected=r._urlString.length()-encoded.length();
-        int index = r._urlString.lastIndexOf(encoded, expected);
-        
-        if (expected!=index && ((expected-1)!=index || path.endsWith("/") || !r.isDirectory()))
-        {
-            r._alias=r._url;
-            r._aliasChecked=true;
-        }                   
-        return r;
-    }
-   
-    
-    /* ------------------------------------------------------------ */
-    public URL getAlias()
-    {
-        if (__checkAliases) {
-          if (!_aliasChecked)
-          {
-            try
-            {    
-                String abs=_file.getAbsolutePath();
-                String can=_file.getCanonicalPath();
-                
-                if (abs.length()!=can.length() || !abs.equals(can))
-                    _alias=new File(can).toURI().toURL();
-                
-                _aliasChecked=true;
-
-                if (_alias!=null && log.isDebugEnabled())
-                {
-                    log.debug("ALIAS abs="+abs);
-                    log.debug("ALIAS can="+can);
-                }
-            }
-            catch(Exception e)
-            {
-                log.warn(LogSupport.EXCEPTION,e);
-                return getURL();
-            }
-          }                
-        } else return null;
-        return _alias;
-    }
-    
-    /* -------------------------------------------------------- */
-    /**
-     * Returns true if the resource exists.
-     */
-    public boolean exists()
-    {
-        return _file.exists();
-    }
-        
-    /* -------------------------------------------------------- */
-    /**
-     * Returns the last modified time
-     */
-    public long lastModified()
-    {
-        return _file.lastModified();
-    }
-
-    /* -------------------------------------------------------- */
-    /**
-     * Returns true if the respresenetd resource is a container/directory.
-     */
-    public boolean isDirectory()
-    {
-        return _file.isDirectory();
-    }
-
-    /* --------------------------------------------------------- */
-    /**
-     * Return the length of the resource
-     */
-    public long length()
-    {
-        return _file.length();
-    }
-        
-
-    /* --------------------------------------------------------- */
-    /**
-     * Returns the name of the resource
-     */
-    public String getName()
-    {
-        return _file.getAbsolutePath();
-    }
-        
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns an File representing the given resource or NULL if this
-     * is not possible.
-     */
-    public File getFile()
-    {
-        return _file;
-    }
-        
-    /* --------------------------------------------------------- */
-    /**
-     * Returns an input stream to the resource
-     */
-    public InputStream getInputStream() throws IOException
-    {
-        return new FileInputStream(_file);
-    }
-        
-    /* --------------------------------------------------------- */
-    /**
-     * Returns an output stream to the resource
-     */
-    public OutputStream getOutputStream()
-        throws java.io.IOException, SecurityException
-    {
-        return new FileOutputStream(_file);
-    }
-        
-    /* --------------------------------------------------------- */
-    /**
-     * Deletes the given resource
-     */
-    public boolean delete()
-        throws SecurityException
-    {
-        return _file.delete();
-    }
-
-    /* --------------------------------------------------------- */
-    /**
-     * Rename the given resource
-     */
-    public boolean renameTo( Resource dest)
-        throws SecurityException
-    {
-        if( dest instanceof FileResource)
-            return _file.renameTo( ((FileResource)dest)._file);
-        else
-            return false;
-    }
-
-    /* --------------------------------------------------------- */
-    /**
-     * Returns a list of resources contained in the given resource
-     */
-    public String[] list()
-    {
-        String[] list =_file.list();
-        if (list==null)
-            return null;
-        for (int i=list.length;i-->0;)
-        {
-            if (new File(_file,list[i]).isDirectory() &&
-                !list[i].endsWith("/"))
-                list[i]+="/";
-        }
-        return list;
-    }
-         
-    /* ------------------------------------------------------------ */
-    /** Encode according to this resource type.
-     * File URIs are encoded.
-     * @param uri URI to encode.
-     * @return The uri unchanged.
-     */
-    public String encode(String uri)
-    {
-        return uri;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param o
-     * @return 
-     */
-    public boolean equals( Object o)
-    {
-        if (this == o)
-            return true;
-
-        if (null == o || ! (o instanceof FileResource))
-            return false;
-
-        FileResource f=(FileResource)o;
-        return f._file == _file || (null != _file && _file.equals(f._file));
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @return the hashcode.
-     */
-    public int hashCode()
-    {
-       return null == _file ? super.hashCode() : _file.hashCode();
-    }
-}
diff --git a/apps/jetty/java/src/org/mortbay/util/InetAddrPort.java b/apps/jetty/java/src/org/mortbay/util/InetAddrPort.java
deleted file mode 100644
index 7f0968798cad0f1f676b5ecc7cfdd9ee214a962a..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/util/InetAddrPort.java
+++ /dev/null
@@ -1,253 +0,0 @@
-// ========================================================================
-// $Id: InetAddrPort.java,v 1.7 2004/10/23 09:03:22 gregwilkins Exp $
-// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-
-package org.mortbay.util;
-
-import java.io.Serializable;
-import java.net.InetAddress;
-
-/* ======================================================================== */
-/** InetAddress and Port.
- */
-public class InetAddrPort implements Serializable
-{
-    /* ------------------------------------------------------------ */
-    public final static String __0_0_0_0 = "0.0.0.0";
-
-    /* ------------------------------------------------------------ */
-    private InetAddress _addr=null;
-    private boolean _addrIsHost=false;
-    private int _port=0;
-
-    /* ------------------------------------------------------------------- */
-    public InetAddrPort()
-    {}
-
-    /* ------------------------------------------------------------ */
-    /** Constructor for a port on all local host address.
-     * @param port 
-     */
-    public InetAddrPort(int port)
-    {
-        _port=port;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * @param addr 
-     * @param port 
-     */
-    public InetAddrPort(InetAddress addr, int port)
-    {
-        _addr=addr;
-        _port=port;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * @param host
-     * @param port 
-     */
-    public InetAddrPort(String host, int port)
-        throws java.net.UnknownHostException
-    {
-        setHost(host);
-        setPort(port);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * Patched to support [::1]:port for I2P
-     *
-     * @param inetAddrPort String of the form "addr:port"
-     */
-    public InetAddrPort(String inetAddrPort)
-        throws java.net.UnknownHostException
-    {
-        int b = inetAddrPort.indexOf('[');
-        if (b>0)
-            throw new java.net.UnknownHostException("Bad [] syntax");
-        if (b==0) // IPV6
-        {
-            int b2 = inetAddrPort.indexOf(']');
-            if (b2<2)
-                throw new java.net.UnknownHostException("Bad [] syntax");
-            String addr=inetAddrPort.substring(1,b2);
-            if (addr.indexOf('/')>0)
-                addr=addr.substring(addr.indexOf('/')+1);
-            inetAddrPort=inetAddrPort.substring(b2+1);
-            int c = inetAddrPort.indexOf(':');
-            if (c>0)
-                throw new java.net.UnknownHostException("Bad [] syntax");
-            if (c==0)
-                inetAddrPort=inetAddrPort.substring(1);
-        
-            if (addr.length()>0 && ! __0_0_0_0.equals(addr))
-            {
-                _addrIsHost=!Character.isDigit((addr.charAt(0)));   
-                this._addr=InetAddress.getByName(addr);
-            }
-        } else { // IPV4
-            int c = inetAddrPort.indexOf(':');
-            if (c>=0)
-            {
-                String addr=inetAddrPort.substring(0,c);
-                if (addr.indexOf('/')>0)
-                    addr=addr.substring(addr.indexOf('/')+1);
-                inetAddrPort=inetAddrPort.substring(c+1);
-
-                if (addr.length()>0 && ! __0_0_0_0.equals(addr))
-                {
-                    _addrIsHost=!Character.isDigit((addr.charAt(0)));   
-                    this._addr=InetAddress.getByName(addr);
-                }
-            }
-        }
-        
-        _port = Integer.parseInt(inetAddrPort); 
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Constructor. 
-     * @param address InetAddrPort top copy.
-     */
-    public InetAddrPort(InetAddrPort address)
-    {
-        if (address!=null)
-        {
-            _addr=address._addr;
-            _port=address._port;
-        }
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the Host.
-     * @return The IP address
-     */
-    public String getHost()
-    {
-        if (_addr==null)
-            return __0_0_0_0;
-        
-        return _addrIsHost?_addr.getHostName():_addr.getHostAddress();
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the Host.
-     * @param host 
-     * @exception java.net.UnknownHostException 
-     */
-    public void setHost(String host)
-        throws java.net.UnknownHostException
-    {
-        _addr=null;
-        if (host!=null)
-        {
-            if (host.indexOf('/')>0)
-                host=host.substring(0,host.indexOf('/'));
-            _addrIsHost=!Character.isDigit((host.charAt(0)));
-            _addr=InetAddress.getByName(host);
-        }
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the IP address.
-     * @return The IP address
-     */
-    public InetAddress getInetAddress()
-    {
-        return _addr;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the IP address.
-     * @param addr The IP address
-     */
-    public void setInetAddress(InetAddress addr)
-    {
-        _addrIsHost=false;
-        _addr=addr;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get the port.
-     * @return The port number
-     */
-    public int getPort()
-    {
-        return _port;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the port.
-     * @param port The port number
-     */
-    public void setPort(int port)
-    {
-        _port=port;
-    }
-    
-    
-    /* ------------------------------------------------------------------- */
-    public String toString()
-    {
-        return getHost()+':'+_port;
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Clone the InetAddrPort.
-     * @return A new instance.
-     */
-    public Object clone()
-    {
-        return new InetAddrPort(this);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Hash Code.
-     * @return hash Code.
-     */
-    public int hashCode()
-    {
-        return _port+((_addr==null)?0:_addr.hashCode());
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Equals.
-     * @param o 
-     * @return True if is the same address and port.
-     */
-    public boolean equals(Object o)
-    {
-        if (o==null)
-            return false;
-        if (o==this)
-            return true;
-        if (o instanceof InetAddrPort)
-        {
-            InetAddrPort addr=(InetAddrPort)o;
-            return addr._port==_port &&
-                ( addr._addr==_addr ||
-                  addr._addr!=null && addr._addr.equals(_addr));
-        }
-        return false;
-    }
-}
-
-    
-
-
-
-
diff --git a/apps/jetty/java/src/org/mortbay/util/Resource.java b/apps/jetty/java/src/org/mortbay/util/Resource.java
deleted file mode 100644
index ed992cfd55f482ab7d0fa8a4cd3918fcc6c1cba0..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/util/Resource.java
+++ /dev/null
@@ -1,431 +0,0 @@
-// ========================================================================
-// $Id: Resource.java,v 1.32 2009/05/16 01:53:36 gregwilkins Exp $
-// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-package org.mortbay.util;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Serializable;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.text.DateFormat;
-import java.util.Arrays;
-import java.util.Date;
-
-import org.apache.commons.logging.Log;
-import org.mortbay.log.LogFactory;
-
-
-/* ------------------------------------------------------------ */
-/** Abstract resource class.
- *
- * @version $Id: Resource.java,v 1.32 2009/05/16 01:53:36 gregwilkins Exp $
- * @author Nuno Preguica
- * @author Greg Wilkins (gregw)
- */
-public abstract class Resource implements Serializable
-{
-    private static Log log = LogFactory.getLog(Resource.class);
-
-    Object _associate;
-    
-    /* ------------------------------------------------------------ */
-    /** Construct a resource from a url.
-     * @param url A URL.
-     * @return A Resource object.
-     */
-    public static Resource newResource(URL url)
-        throws IOException
-    {
-        if (url==null)
-            return null;
-
-        String urls=url.toExternalForm();
-        if( urls.startsWith( "file:"))
-        {
-            try
-            {
-                FileResource fileResource= new FileResource(url);
-                return fileResource;
-            }
-            catch(Exception e)
-            {
-                log.debug(LogSupport.EXCEPTION,e);
-                return new BadResource(url,e.toString());
-            }
-        }
-        else if( urls.startsWith( "jar:file:"))
-        {
-            return new JarFileResource(url);
-        }
-        else if( urls.startsWith( "jar:"))
-        {
-            return new JarResource(url);
-        }
-
-        return new URLResource(url,null);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Construct a resource from a string.
-     * @param resource A URL or filename.
-     * @return A Resource object.
-     */
-    public static Resource newResource(String resource)
-        throws MalformedURLException, IOException
-    {
-        URL url=null;
-        try
-        {
-            // Try to format as a URL?
-            url = new URL(resource);
-        }
-        catch(MalformedURLException e)
-        {
-            if(!resource.startsWith("ftp:") &&
-               !resource.startsWith("file:") &&
-               !resource.startsWith("jar:"))
-            {
-                try
-                {
-                    // It's a file.
-                    if (resource.startsWith("./"))
-                        resource=resource.substring(2);
-                    
-                    File file=new File(resource).getCanonicalFile();
-                    url=file.toURI().toURL();                    
-                    
-                    URLConnection connection=url.openConnection();
-                    FileResource fileResource= new FileResource(url,connection,file);
-                    return fileResource;
-                }
-                catch(Exception e2)
-                {
-                    log.debug(LogSupport.EXCEPTION,e2);
-                    throw e;
-                }
-            }
-            else
-            {
-                log.warn("Bad Resource: "+resource);
-                throw e;
-            }
-        }
-
-        String nurl=url.toString();
-        if (nurl.length()>0 &&
-            nurl.charAt(nurl.length()-1)!=
-            resource.charAt(resource.length()-1))
-        {
-            if ((nurl.charAt(nurl.length()-1)!='/' ||
-                 nurl.charAt(nurl.length()-2)!=resource.charAt(resource.length()-1))
-                &&
-                (resource.charAt(resource.length()-1)!='/' ||
-                 resource.charAt(resource.length()-2)!=nurl.charAt(nurl.length()-1)
-                 ))
-            {
-                return new BadResource(url,"Trailing special characters stripped by URL in "+resource);
-            }
-        }
-        return newResource(url);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Construct a system resource from a string.
-     * The resource is tried as classloader resource before being
-     * treated as a normal resource.
-     */
-    public static Resource newSystemResource(String resource)
-        throws IOException
-    {
-        URL url=null;
-        // Try to format as a URL?
-        ClassLoader
-            loader=Thread.currentThread().getContextClassLoader();
-        if (loader!=null)
-        {
-            url=loader.getResource(resource);
-            if (url==null && resource.startsWith("/"))
-                url=loader.getResource(resource.substring(1));
-        }
-        if (url==null)
-        {
-            loader=Resource.class.getClassLoader();
-            if (loader!=null)
-            {
-                url=loader.getResource(resource);
-                if (url==null && resource.startsWith("/"))
-                    url=loader.getResource(resource.substring(1));
-            }
-        }
-        
-        if (url==null)
-        {
-            url=ClassLoader.getSystemResource(resource);
-            if (url==null && resource.startsWith("/"))
-                url=loader.getResource(resource.substring(1));
-        }
-        
-        if (url==null)
-            return null;
-        
-        return newResource(url);
-    }
-
-    /* ------------------------------------------------------------ */
-    protected void finalize()
-    {
-        release();
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Release any resources held by the resource.
-     */
-    public abstract void release();
-    
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns true if the respresened resource exists.
-     */
-    public abstract boolean exists();
-    
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns true if the respresenetd resource is a container/directory.
-     * If the resource is not a file, resources ending with "/" are
-     * considered directories.
-     */
-    public abstract boolean isDirectory();
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns the last modified time
-     */
-    public abstract long lastModified();
-
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Return the length of the resource
-     */
-    public abstract long length();
-    
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns an URL representing the given resource
-     */
-    public abstract URL getURL();
-    
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns an File representing the given resource or NULL if this
-     * is not possible.
-     */
-    public abstract File getFile()
-        throws IOException;
-    
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns the name of the resource
-     */
-    public abstract String getName();
-    
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns an input stream to the resource
-     */
-    public abstract InputStream getInputStream()
-        throws java.io.IOException;
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns an output stream to the resource
-     */
-    public abstract OutputStream getOutputStream()
-        throws java.io.IOException, SecurityException;
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * Deletes the given resource
-     */
-    public abstract boolean delete()
-        throws SecurityException;
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * Rename the given resource
-     */
-    public abstract boolean renameTo( Resource dest)
-        throws SecurityException;
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns a list of resource names contained in the given resource
-     * The resource names are not URL encoded.
-     */
-    public abstract String[] list();
-
-    /* ------------------------------------------------------------ */
-    /**
-     * Returns the resource contained inside the current resource with the
-     * given name.
-     * @param path The path segment to add, which should be encoded by the
-     * encode method. 
-     */
-    public abstract Resource addPath(String path)
-        throws IOException,MalformedURLException;
-    
-
-    /* ------------------------------------------------------------ */
-    /** Encode according to this resource type.
-     * The default implementation calls URI.encodePath(uri)
-     * @param uri 
-     * @return String encoded for this resource type.
-     */
-    public String encode(String uri)
-    {
-        return URI.encodePath(uri);
-    }
-    
-        
-    /* ------------------------------------------------------------ */
-    public Object getAssociate()
-    {
-        return _associate;
-    }
-
-    /* ------------------------------------------------------------ */
-    public void setAssociate(Object o)
-    {
-        _associate=o;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * @return The canonical Alias of this resource or null if none.
-     */
-    public URL getAlias()
-    {
-        return null;
-    }
-    
-
-    /* ------------------------------------------------------------ */
-    public CachedResource cache()
-        throws IOException
-    {
-        return new CachedResource(this);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the resource list as a HTML directory listing.
-     * @param base The base URL
-     * @param parent True if the parent directory should be included
-     * @return String of HTML
-     */
-    public String getListHTML(String base,
-                              boolean parent)
-        throws IOException
-    {
-        if (!isDirectory())
-            return null;
-        
-      
-        String[] ls = list();
-        if (ls==null)
-            return null;
-        Arrays.sort(ls);
-        
-        String title = "Directory: "+URI.decodePath(base);
-        title=StringUtil.replace(StringUtil.replace(title,"<","&lt;"),">","&gt;");
-        StringBuffer buf=new StringBuffer(4096);
-        buf.append("<HTML><HEAD><TITLE>");
-        buf.append(title);
-        buf.append("</TITLE></HEAD><BODY>\n<H1>");
-        buf.append(title);
-        buf.append("</H1><TABLE BORDER=0>");
-        
-        if (parent)
-        {
-            buf.append("<TR><TD><A HREF=");
-            buf.append(URI.encodePath(URI.addPaths(base,"../")));
-            buf.append(">Parent Directory</A></TD><TD></TD><TD></TD></TR>\n");
-        }
-        
-        DateFormat dfmt=DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
-                                                       DateFormat.MEDIUM);
-        for (int i=0 ; i< ls.length ; i++)
-        {   
-            String encoded=URI.encodePath(ls[i]);
-            // bugfix for I2P - Backport from Jetty 6 (zero file lengths and last-modified times)
-            // http://jira.codehaus.org/browse/JETTY-361?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel#issue-tabs
-            // See resource.diff attachment
-            //Resource item = addPath(encoded);
-            Resource item = addPath(ls[i]);
-            
-            buf.append("<TR><TD><A HREF=\"");
-            
-            String path=URI.addPaths(base,encoded);
-            
-            if (item.isDirectory() && !path.endsWith("/"))
-                path=URI.addPaths(path,"/");
-            buf.append(path);
-            buf.append("\">");
-            buf.append(StringUtil.replace(StringUtil.replace(ls[i],"<","&lt;"),">","&gt;"));
-            buf.append("</A>&nbsp;");
-            buf.append("</TD><TD ALIGN=right>");
-            buf.append(item.length());
-            buf.append(" bytes&nbsp;</TD><TD>");
-            buf.append(dfmt.format(new Date(item.lastModified())));
-            buf.append("</TD></TR>\n");
-        }
-        buf.append("</TABLE>\n");
-	buf.append("</BODY></HTML>\n");
-        
-        return buf.toString();
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param out 
-     * @param start First byte to write
-     * @param count Bytes to write or -1 for all of them.
-     */
-    public void writeTo(OutputStream out,long start,long count)
-        throws IOException
-    {
-        InputStream in = getInputStream();
-        try
-        {
-            in.skip(start);
-            if (count<0)
-                IO.copy(in,out);
-            else
-                IO.copy(in,out,(int)count);
-        }
-        finally
-        {
-            in.close();
-        }
-    }    
-}
diff --git a/apps/jetty/java/src/org/mortbay/util/URI.java b/apps/jetty/java/src/org/mortbay/util/URI.java
deleted file mode 100644
index 867ef19f40c14273a2b5154e2efe6ebf8127e429..0000000000000000000000000000000000000000
--- a/apps/jetty/java/src/org/mortbay/util/URI.java
+++ /dev/null
@@ -1,1010 +0,0 @@
-// ========================================================================
-// $Id: URI.java,v 1.40 2009/05/16 02:02:00 gregwilkins Exp $
-// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at 
-// http://www.apache.org/licenses/LICENSE-2.0
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// ========================================================================
-package org.mortbay.util;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.mortbay.log.LogFactory;
-
-/* ------------------------------------------------------------ */
-/** URI Holder.
- * This class assists with the decoding and encoding or HTTP URI's.
- * It differs from the java.net.URL class as it does not provide
- * communications ability, but it does assist with query string
- * formatting.
- * <P>ISO_8859_1 encoding is used by default for % encoded characters. This
- * may be overridden with the org.mortbay.util.URI.charset system property.
- * @see UrlEncoded
- * @version $Id: URI.java,v 1.40 2009/05/16 02:02:00 gregwilkins Exp $
- * @author Greg Wilkins (gregw)
- */
-public class URI
-    implements Cloneable
-{
-    private static Log log = LogFactory.getLog(URI.class);
-
-    public static final String __CHARSET=System.getProperty("org.mortbay.util.URI.charset",StringUtil.__UTF_8);
-    public static final boolean __CHARSET_IS_DEFAULT=__CHARSET.equals(StringUtil.__UTF_8);
-    
-    /* ------------------------------------------------------------ */
-    private String _uri;
-    private String _scheme;
-    private String _host;
-    private int _port;
-    private String _path;
-    private String _encodedPath;
-    private String _query;
-    private UrlEncoded _parameters;
-    private boolean _dirty;
-    private static String unreserved = "/0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.~";
-    private static String reserved = "!*'();:@&=+$,?%#[]";
-    private static String hexchars = "0123456789ABCDEF";
-    
-    /* ------------------------------------------------------------ */
-    /** Copy Constructor .
-     * @param uri
-     */
-    public URI(URI uri)
-        throws IllegalArgumentException
-    {
-        _uri=uri.toString();
-        _scheme=uri._scheme;
-        _host=uri._host;
-        _port=uri._port;
-        _path=uri._path;
-        _encodedPath=uri._encodedPath;
-        _query=uri._query;
-        if (uri._parameters!=null) 
-            _parameters=(UrlEncoded)uri._parameters.clone();
-        _dirty=false;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Construct from a String.
-     * The string must contain a URI path, but optionaly may contain a
-     * scheme, host, port and query string.
-     * 
-     * @param uri [scheme://host[:port]]/path[?query]
-     */
-    public URI(String uri)
-        throws IllegalArgumentException
-    {
-        setURI(uri);
-    }
-    
-    /* ------------------------------------------------------------ */
-    public void setURI(String uri)
-        throws IllegalArgumentException
-    {
-        try
-        {    
-            _uri=uri;
-            _scheme=null;
-            _host=null;
-            _port=0;
-            _path=null;
-            _encodedPath=null;
-            _query=null;
-            if (_parameters!=null)
-                _parameters.clear();
-            
-            // Scan _uri for host, port, path & query
-            int maxi=uri.length()-1;
-            int mark=0;
-            int state=0;
-            int i=0;
-
-            if (maxi==0 || uri.charAt(0)=='/' && uri.charAt(1)!='/')
-            {
-                state=3;
-                _scheme=null;
-                _host=null;
-                _port=0;
-            }
-            else
-            {
-                for (i=0;state<3 && i<=maxi;i++)
-                {
-                    char c=uri.charAt(i);
-                    switch(state)
-                    {
-                      case 0: // looking for scheme or path
-                          if (c==':' &&
-                              uri.charAt(i+1)=='/' &&
-                              uri.charAt(i+2)=='/')
-                          {
-                              // found end of scheme & start of host
-                              _scheme=uri.substring(mark,i);
-                              i+=2;
-                              mark=i+1;
-                              state=1;
-                          }
-                          else if (i==0 && c=='/')
-                          {
-                              // Found path
-                              state=3;
-                          }
-                          else if (i==0 && c=='*')
-                          {
-                              state=5;
-                              _path="*";
-                              _encodedPath="*";
-                          }
-                          continue;
-                          
-                      case 1: // Get host & look for port or path
-                          if (c==':')
-                          {
-                              // found port
-                              _host=uri.substring(mark,i);
-                              mark=i+1;
-                              state=2;
-                          }
-                          else if (c=='/')
-                          {
-                              // found path
-                              _host=uri.substring(mark,i);
-                              mark=i;
-                              state=3;
-                          }
-                          continue;
-                          
-                      case 2: // Get port & look for path
-                          if (c=='/')
-                          {
-                              _port=TypeUtil.parseInt(uri,mark,i-mark,10);
-                              mark=i;
-                              state=3;
-                          }
-                          continue;
-                    }
-                }
-            }
-            
-            // State 3 - Get path & look for query
-            _query=null;
-            for (i++;i<=maxi;i++)
-            {
-                char c=uri.charAt(i); 
-                if (c=='?')
-                {
-                    // Found query
-                    _encodedPath=uri.substring(mark,i);
-                    _path=decodePath(_encodedPath);
-
-                    mark=i+1;
-                    state=4;
-                    break;
-                }
-            }
-
-            // complete last state
-            switch(state)
-            {
-              case 0:
-                  _dirty=false;
-                  _encodedPath=_uri;
-                  _path=decodePath(_encodedPath);
-                  break;
-                  
-              case 1:
-                  _dirty=true;
-                  _encodedPath="/";
-                  _path=_encodedPath;
-                  _host=uri.substring(mark);
-                  break;
-                  
-              case 2:
-                  _dirty=true;
-                  _encodedPath="/";
-                  _path=_encodedPath;
-                  _port=TypeUtil.parseInt(uri,mark,-1,10);
-                  break;
-              case 3:
-                  _dirty=(mark==maxi);
-                  _encodedPath=uri.substring(mark);
-                  _path=decodePath(_encodedPath);
-                  break;
-                  
-              case 4:
-                  _dirty=false; 
-                  if (mark<=maxi)
-                      _query=uri.substring(mark);
-                  break;
-                  
-              case 5:
-                  _dirty=false; 
-            }
-        
-            if (_query!=null && _query.length()>0)
-            {
-                if (_parameters==null)
-                    _parameters= new UrlEncoded();
-                else
-                    _parameters.clear();
-                _parameters.decode(_query,__CHARSET);
-                
-            }
-            else
-                _query=null;           
-        }
-        catch (Exception e)
-        {
-            LogSupport.ignore(log,e);
-            throw new IllegalArgumentException("Malformed URI '"+uri+
-                                               "' : "+e.toString());
-        }        
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Is the URI an absolute URL? 
-     * @return True if the URI has a scheme or host
-     */
-    public boolean isAbsolute()
-    {
-        return _scheme!=null || _host!=null;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the uri scheme.
-     * @return the URI scheme
-     */
-    public String getScheme()
-    {
-        return _scheme;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the uri scheme.
-     * @param scheme the uri scheme
-     */
-    public void setScheme(String scheme)
-    {
-        _scheme=scheme;
-        _dirty=true;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the uri host.
-     * @return the URI host
-     */
-    public String getHost()
-    {
-        return _host;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the uri host.
-     * @param host the uri host
-     */
-    public void setHost(String host)
-    {
-        _host=host;
-        _dirty=true;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the uri port.
-     * @return the URI port
-     */
-    public int getPort()
-    {
-        return _port;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the uri port.
-     * A port of 0 implies use the default port.
-     * @param port the uri port
-     */
-    public void setPort(int port)
-    {
-        _port=port;
-        _dirty=true;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the uri path.
-     * @return the URI path
-     */
-    public String getPath()
-    {
-        return _path;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the encoded uri path.
-     * @return the URI path
-     */
-    public String getEncodedPath()
-    {
-        return _encodedPath;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the uri path.
-     * @param path the URI path
-     */
-    public void setPath(String path)
-    {
-        _path=path;
-        _encodedPath=encodePath(_path);
-        _dirty=true;
-    }
-    
-    
-    /* ------------------------------------------------------------ */
-    /** Get the uri query String.
-     * @return the URI query string
-     */
-    public String getQuery()
-    {
-        if (_dirty && _parameters!=null)
-        {
-            _query = _parameters.encode(__CHARSET);
-            if (_query!=null && _query.length()==0)
-                _query=null;
-        }
-        return _query;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Set the uri query String.
-     * @param query the URI query string
-     */
-    public void setQuery(String query)
-    {
-        _query=query;
-        
-        if (_parameters!=null)
-            _parameters.clear();
-        else if (query!=null)
-            _parameters=new UrlEncoded();
-        
-        if (query!=null)
-            _parameters.decode(query,__CHARSET);
-        
-        cleanURI();
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the uri query _parameters names.
-     * @return  Unmodifiable set of URI query _parameters names
-     */
-    public Set getParameterNames()
-    {
-        if (_parameters==null)
-            return Collections.EMPTY_SET;
-        return _parameters.keySet();
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the uri query _parameters.
-     * @return the URI query _parameters
-     */
-    public MultiMap getParameters()
-    {
-        if (_parameters==null)
-            _parameters=new UrlEncoded();
-        _dirty=true;
-        return _parameters;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get the uri query _parameters.
-     * @return the URI query _parameters in an unmodifiable map.
-     */
-    public Map getUnmodifiableParameters()
-    {
-        if (_parameters==null)
-            return Collections.EMPTY_MAP;
-        return Collections.unmodifiableMap(_parameters);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Add the uri query _parameters to a MultiMap
-     */
-    public void putParametersTo(MultiMap map)
-    {
-        if (_parameters!=null && _parameters.size()>0)
-            map.putAll(_parameters);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Clear the URI _parameters.
-     */
-    public void clearParameters()
-    {
-        if (_parameters!=null)
-        {
-            _dirty=true;
-            _parameters.clear();
-        }
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Add encoded _parameters.
-     * @param encoded A HTTP encoded string of _parameters: e.g.. "a=1&b=2"
-     */
-    public void put(String encoded)
-    {
-        UrlEncoded params = new UrlEncoded(encoded);
-        put(params);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Add name value pair to the uri query _parameters.
-     * @param name name of value
-     * @param value The value, which may be a multi valued list or
-     * String array.
-     */
-    public Object put(Object name, Object value)
-    {
-        return getParameters().put(name,value);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Add dictionary to the uri query _parameters.
-     */
-    public void put(Map values)
-    {
-        getParameters().putAll(values);
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Get named value 
-     */
-    public String get(String name)
-    {
-        if (_parameters==null)
-            return null;
-        return (String)_parameters.get(name);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Get named multiple values.
-     * @param name The parameter name
-     * @return Umodifiable list of values or null
-     */
-    public List getValues(String name)
-    {
-        if (_parameters==null)
-            return null;
-        return _parameters.getValues(name);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Remove named value 
-     */
-    public void remove(String name)
-    {
-        if (_parameters!=null)
-        {
-            _dirty=
-                _parameters.remove(name)!=null;
-        }
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** @return the URI string encoded.
-     */
-    public String toString()
-    {
-        if (_dirty)
-        {
-            getQuery();
-            cleanURI();
-        }
-        return _uri;
-    }
-
-    /* ------------------------------------------------------------ */
-    private void cleanURI()
-    {
-        StringBuffer buf = new StringBuffer(_uri.length()*2);
-        synchronized(buf)
-        {
-            if (_scheme!=null)
-            {
-                buf.append(_scheme);
-                buf.append("://");
-                buf.append(_host);
-                if (_port>0)
-                {
-                    buf.append(':');
-                    buf.append(_port);
-                }
-            }
-
-            buf.append(_encodedPath);
-            
-            if (_query!=null && _query.length()>0)
-            {
-                buf.append('?');
-                buf.append(_query);
-            }
-            _uri=buf.toString();
-            _dirty=false;
-        }
-    }
-    
-                
-    /* ------------------------------------------------------------ */
-    /** Encode a URI path.
-     * This is the same encoding offered by URLEncoder, except that
-     * the '/' character is not encoded.
-     * @param path The path the encode
-     * @return The encoded path
-     */
-    public static String encodePath(String path)
-    {
-        if (path==null || path.length()==0)
-            return path;
-        
-        StringBuffer buf = encodePath(null,path);
-        return buf==null?path:buf.toString();
-    }
-        
-    /* ------------------------------------------------------------ */
-    /** Encode a URI path.
-     * @param path The path the encode
-     * @param buf StringBuffer to encode path into (or null)
-     * @return The StringBuffer or null if no substitutions required.
-     */
-    public static StringBuffer encodePath(StringBuffer buf, String path)
-    {
-        /* Convert path to native character set not __CHARSET.
-         * This is important to do this way because the path 
-         * contains *OS specific characters* and __CHARSET could
-         * be wrong and not encode/decode the path correctly.
-         */
-        byte[] b = null;
-        /*
-        Keep commented out unless you can prove that this does the right thing.
-        try {
-            b = path.getBytes(__CHARSET);
-        } catch(UnsupportedEncodingException ex) {
-            return null; // Shouldn't be possible.
-        }
-        */
-        b = path.getBytes();
-        StringBuffer x = new StringBuffer(b.length);
-        for(int i=0; i<b.length; i++) {
-            x.append((char)(b[i]&0xff));
-        }
-        String _path = new String(x);
-        if(buf == null) {
-            loop:
-            for(int i = 0; i < _path.length(); i++) {
-                char c = _path.charAt(i);
-                String cs = "" + c;
-                if(reserved.contains(cs) || !unreserved.contains(cs)) {
-                    buf = new StringBuffer(_path.length() << 1);
-                    break loop;
-                }
-            }
-            if(buf == null) {
-                return null;
-            }
-        }
-        synchronized(buf) {
-            for(int i = 0; i < _path.length(); i++) {
-                char c = _path.charAt(i);
-                String cs = "" + c;
-                if(reserved.contains(cs) || !unreserved.contains(cs)) {
-                    /*
-                    We are already bytes
-                    if((c & 0xff) == c) {
-                        buf.append(gethex(c & 0xff));
-                    } else {
-                        buf.append(gethex((c >> 8) & 0xff));
-                        buf.append(gethex(c & 0xff));
-                    }
-                    */
-                    buf.append(gethex(c & 0xff));
-                } else {
-                    buf.append(c);
-                }
-            }
-        }
-
-        return buf;
-    }
-    
-    /**
-     *
-     * @param decimal value not greater than 255.
-     * @return a percent sign followed by two hexadecimal digits.
-     */
-    private static String gethex(int decimal) {
-        return new String("%" + hexchars.charAt(decimal >> 4) + hexchars.charAt(decimal & 0xF));
-    }
-    /* ------------------------------------------------------------ */
-    /** Encode a URI path.
-     * @param path The path the encode
-     * @param buf StringBuffer to encode path into (or null)
-     * @param encode String of characters to encode. % is always encoded.
-     * @return The StringBuffer or null if no substitutions required.
-     */
-    public static StringBuffer encodeString(StringBuffer buf,
-                                            String path,
-                                            String encode)
-    {
-        if (buf==null)
-        {
-        loop:
-            for (int i=0;i<path.length();i++)
-            {
-                char c=path.charAt(i);
-                if (c=='%' || encode.indexOf(c)>=0)
-                {    
-                    buf=new StringBuffer(path.length()<<1);
-                    break loop;
-                }
-            }
-            if (buf==null)
-                return null;
-        }
-        
-        synchronized(buf)
-        {
-            for (int i=0;i<path.length();i++)
-            {
-                char c=path.charAt(i);
-                if (c=='%' || encode.indexOf(c)>=0)
-                {
-                    buf.append('%');
-                    StringUtil.append(buf,(byte)(0xff&c),16);
-                }
-                else
-                    buf.append(c);
-            }
-        }
-
-        return buf;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /* Decode a URI path.
-     * @param path The path the encode
-     * @param buf StringBuffer to encode path into
-     */
-    public static String decodePath(String path)
-    {
-        int len=path.length();
-        byte[] bytes=null;
-        int n=0;
-        boolean noDecode=true;
-        
-        for (int i=0;i<len;i++)
-        {
-            char c = path.charAt(i);
-            
-            byte b = (byte)(0xff & c);
-
-            if (c=='%' && (i+2)<len)
-            {
-                noDecode=false;
-                b=(byte)(0xff&TypeUtil.parseInt(path,i+1,2,16));
-                i+=2;
-            }
-            else if (bytes==null)
-            {
-                n++;
-                continue;
-            }
-            
-            if (bytes==null)
-            {
-                noDecode=false;
-                bytes=new byte[len];
-                for (int j=0;j<n;j++)
-                    bytes[j]=(byte)(0xff & path.charAt(j));                
-            }
-            
-            bytes[n++]=b;
-        }
-
-        if (noDecode)
-            return path;
-
-        /*
-        Keep commented out unless you can prove that this does the right thing.
-        try
-        {    
-            return new String(bytes,0,n,__CHARSET);
-        }
-        catch(UnsupportedEncodingException e)
-        {
-            log.warn(LogSupport.EXCEPTION,e);
-            return new String(bytes,0,n);
-        }
-        */
-        
-        return new String(bytes,0,n);
-        
-    }
-
-    /* ------------------------------------------------------------ */
-    /** Clone URI.
-     * @return cloned URI
-     */
-    public Object clone()
-	throws CloneNotSupportedException
-    {
-         URI u = (URI)super.clone();
-         if (_parameters!=null)
-             u._parameters=(UrlEncoded)_parameters.clone();
-         _dirty=false;
-         
-         return u;
-    }
-
-
-    /* ------------------------------------------------------------ */
-    /** Add two URI path segments.
-     * Handles null and empty paths, path and query params (eg ?a=b or
-     * ;JSESSIONID=xxx) and avoids duplicate '/'
-     *
-     * WARNING: URI path segments must be encoded properly first!
-     *          Use the encodePath method above BEFORE attaching a path
-     *          that contains characters that need escaping! --Sponge
-     *
-     * @param p1 URI path segment 
-     * @param p2 URI path segment
-     * @return Legally combined path segments.
-     */
-    public static String addPaths(String p1, String p2)
-    {
-        if (p1==null || p1.length()==0)
-        {
-            if (p2==null || p2.length()==0)
-                return p1;
-            return p2;
-        }
-        if (p2==null || p2.length()==0)
-            return p1;
-        
-        int split=p1.indexOf(';');
-        if (split<0)
-            split=p1.indexOf('?');
-        if (split==0)
-            return p2+p1;
-        if (split<0)
-            split=p1.length();
-
-        StringBuffer buf = new StringBuffer(p1.length()+p2.length()+2);
-        buf.append(p1);
-        
-        if (buf.charAt(split-1)=='/')
-        {
-            if (p2.startsWith("/"))
-            {
-                buf.deleteCharAt(split-1);
-                buf.insert(split-1,p2);
-            }
-            else
-                buf.insert(split,p2);
-        }
-        else
-        {
-            if (p2.startsWith("/"))
-                buf.insert(split,p2);
-            else
-            {
-                buf.insert(split,'/');
-                buf.insert(split+1,p2);
-            }
-        }
-
-        return buf.toString();
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Return the parent Path.
-     * Treat a URI like a directory path and return the parent directory.
-     */
-    public static String parentPath(String p)
-    {
-        if (p==null || "/".equals(p))
-            return null;
-        int slash=p.lastIndexOf('/',p.length()-2);
-        if (slash>=0)
-            return p.substring(0,slash+1);
-        return null;
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Strip parameters from a path.
-     * Return path upto any semicolon parameters.
-     */
-    public static String stripPath(String path)
-    {
-        if (path==null)
-            return null;
-        int semi=path.indexOf(';');
-        if (semi<0)
-            return path;
-        return path.substring(0,semi);
-    }
-    
-    /* ------------------------------------------------------------ */
-    /** Convert a path to a cananonical form.
-     * All instances of "." and ".." are factored out.  Null is returned
-     * if the path tries to .. above it's root.
-     * @param path 
-     * @return path or null.
-     */
-    public static String canonicalPath(String path)
-    {
-        if (path==null || path.length()==0)
-            return path;
-
-        int end=path.length();
-        int start = path.lastIndexOf('/', end);
-
-    search:
-        while (end>0)
-        {
-            switch(end-start)
-            {
-              case 2: // possible single dot
-                  if (path.charAt(start+1)!='.')
-                      break;
-                  break search;
-              case 3: // possible double dot
-                  if (path.charAt(start+1)!='.' || path.charAt(start+2)!='.')
-                      break;
-                  break search;
-            }
-            
-            end=start;
-            start=path.lastIndexOf('/',end-1);
-        }
-
-        // If we have checked the entire string
-        if (start>=end)
-            return path;
-        
-        StringBuffer buf = new StringBuffer(path);
-        int delStart=-1;
-        int delEnd=-1;
-        int skip=0;
-        
-        while (end>0)
-        {
-            switch(end-start)
-            {       
-              case 2: // possible single dot
-                  if (buf.charAt(start+1)!='.')
-                  {
-                      if (skip>0 && --skip==0)
-                      {   
-                          delStart=start>=0?start:0;
-                          if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.')
-                              delStart++;
-                      }
-                      break;
-                  }
-                  
-                  if(start<0 && buf.length()>2 && buf.charAt(1)=='/' && buf.charAt(2)=='/')
-                      break;
-                  
-                  if(delEnd<0)
-                      delEnd=end;
-                  delStart=start;
-                  if (delStart<0 || delStart==0&&buf.charAt(delStart)=='/')
-                  {
-                      delStart++;
-                      if (delEnd<buf.length() && buf.charAt(delEnd)=='/')
-                          delEnd++;
-                      break;
-                  }
-                  if (end==buf.length())
-                      delStart++;
-                  
-                  end=start--;
-                  while (start>=0 && buf.charAt(start)!='/')
-                      start--;
-                  continue;
-                  
-              case 3: // possible double dot
-                  if (buf.charAt(start+1)!='.' || buf.charAt(start+2)!='.')
-                  {
-                      if (skip>0 && --skip==0)
-                      {   delStart=start>=0?start:0;
-                      	  if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.')
-                      	      delStart++;
-                      }
-                      break;
-                  }
-                  
-                  delStart=start;
-                  if (delEnd<0)
-                      delEnd=end;
-
-                  skip++;
-                  end=start--;
-                  while (start>=0 && buf.charAt(start)!='/')
-                      start--;
-                  continue;
-
-              default:
-                  if (skip>0 && --skip==0)
-                  {
-                      delStart=start>=0?start:0;
-                      if(delEnd==buf.length() && buf.charAt(delEnd-1)=='.')
-                          delStart++;
-                  }
-            }     
-            
-            // Do the delete
-            if (skip<=0 && delStart>=0 && delStart>=0)
-            {  
-                buf.delete(delStart,delEnd);
-                delStart=delEnd=-1;
-                if (skip>0)
-                    delEnd=end;
-            }
-            
-            end=start--;
-            while (start>=0 && buf.charAt(start)!='/')
-                start--;
-        }      
-
-        // Too many ..
-        if (skip>0)
-            return null;
-        
-        // Do the delete
-        if (delEnd>=0)
-            buf.delete(delStart,delEnd);
-
-        return buf.toString();
-    }
-
-    /* ------------------------------------------------------------ */
-    /** 
-     * @param uri URI
-     * @return True if the uri has a scheme
-     */
-    public static boolean hasScheme(String uri)
-    {
-        for (int i=0;i<uri.length();i++)
-        {
-            char c=uri.charAt(i);
-            if (c==':')
-                return true;
-            if (!(c>='a'&&c<='z' ||
-                  c>='A'&&c<='Z' ||
-                  (i>0 &&(c>='0'&&c<='9' ||
-                          c=='.' ||
-                          c=='+' ||
-                          c=='-'))
-                  ))
-                break;
-        }
-        return false;
-    }
-    
-}
-
-
-
diff --git a/apps/jetty/resources/log4j.properties b/apps/jetty/resources/log4j.properties
new file mode 100644
index 0000000000000000000000000000000000000000..8899c004be3a92ff30135093b8bcea956c81117b
--- /dev/null
+++ b/apps/jetty/resources/log4j.properties
@@ -0,0 +1,9 @@
+
+# This is not needed by Jetty - but it helps with many web apps.
+
+log4j.rootLogger=INFO, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+
diff --git a/apps/routerconsole/java/build.xml b/apps/routerconsole/java/build.xml
index 3dba335781c6f87708177aa15ce91c80d5017dba..ab5e8d77550f6ec18b868bc7de9370f92158ba6c 100644
--- a/apps/routerconsole/java/build.xml
+++ b/apps/routerconsole/java/build.xml
@@ -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/ant.jar" />
+                <pathelement location="../../jetty/jettylib/jsp-api.jar" />
+                <pathelement location="${ant.home}/lib/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" />
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java
index 407f3227a69700c3a981cdd04ccf995f6bde383a..df2f854a76475dd3805c25fff9151a2ba30ef9ba 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java
@@ -14,7 +14,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
@@ -290,7 +290,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");
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java
index b7a892587b09a3661c59e69a4ba74de8038eaf69..e24824e2a2b6293c3f79be8b61dff4d8c1a2b153 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java
@@ -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);
     }
 }
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
index 73bb8248d58acea8ff5184653697d492caa69991..818de376a7ed6732e1ae1cfb42d30f7258a231ea 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
@@ -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() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
index 27fe4e9f800697fa0880ef6f65cc7a1a9f76b462..5e6acb5d0f9e9b9acb76b2d4a137d2db2b686cdd 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
@@ -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;
 
 
 /**
@@ -261,7 +261,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());
@@ -361,8 +361,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());
@@ -382,11 +382,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);
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 3d624c64a2535d9dcf831dd873830ce2480ca50c..db397881078810fda79a7c300090b4e7c31e0c55 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
@@ -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,67 +367,92 @@ 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);
+            rootWebApp.setTempDirectory(tmpdir);
+            rootWebApp.setSessionHandler(new SessionHandler());
+            rootServletHandler = new ServletHandler();
+            rootWebApp.setServletHandler(rootServletHandler);
+            initialize(rootWebApp);
+            chColl.addHandler(rootWebApp);
+
+        } catch (Exception ioe) {
+            ioe.printStackTrace();
+        }
+
+        try {
+            // start does a mapContexts()
+            _server.start();
+        } catch (Throwable me) {
+            // NoClassFoundDefError from a webapp is a throwable, not an exception
+            System.err.println("WARNING: Error starting one or more listeners of the Router Console server.\n" +
+                               "If your console is still accessible at http://127.0.0.1:7657/,\n" +
+                               "this may be a problem only with binding to the IPV6 address ::1.\n" +
+                               "If so, you may ignore this error, or remove the\n" +
+                               "\"::1,\" in the \"clientApp.0.args\" line of the clients.config file.\n" +
+                               "Exception: " + me);
+            me.printStackTrace();
+        }
+
+        // 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++) {
-                    try {
-                        String appName = fileNames[i].substring(0, fileNames[i].lastIndexOf(".war"));
-                        String enabled = props.getProperty(PREFIX + appName + ENABLED);
-                        if (! "false".equals(enabled)) {
+                    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();
-                            tmpdir = new SecureDirectory(workDir, appName + "-" +
-                                                                  (_listenPort != null ? _listenPort : _sslListenPort));
-                            WebAppStarter.addWebApp(I2PAppContext.getGlobalContext(), _server, appName, path, tmpdir);
-
+                            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;
                             }
-                        } else {
+                        } catch (Throwable t) {
+                            System.err.println("ERROR: Failed to start " + appName + ' ' + t);
+                            t.printStackTrace();
                             notStarted.add(appName);
                         }
-                    } catch (IOException ioe) {
-                        System.err.println("Error resolving '" + fileNames[i] + "' in '" + dir);
+                    } else {
+                        notStarted.add(appName);
                     }
                 }
             }
-        } catch (IOException ioe) {
-            ioe.printStackTrace();
+        } else {
+            System.err.println("ERROR: Router console did not start, not starting webapps");
         }
+
         if (rewrite)
             storeWebAppProperties(props);
-        try {
-            _server.start();
-        } catch (Throwable me) {
-            // NoClassFoundDefError from a webapp is a throwable, not an exception
-            System.err.println("WARNING: Error starting one or more listeners of the Router Console server.\n" +
-                               "If your console is still accessible at http://127.0.0.1:7657/,\n" +
-                               "this may be a problem only with binding to the IPV6 address ::1.\n" +
-                               "If so, you may ignore this error, or remove the\n" +
-                               "\"::1,\" in the \"clientApp.0.args\" line of the clients.config file.\n" +
-                               "Exception: " + me);
-            me.printStackTrace();
-        }
 
-        if (baseHandler != null) {
+        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;
+        }
+    }
+
 }
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
index 0943ea4177293327cdbac18f8ecafcc80418f942..249ae4582e97cbd4a8108351ffe3b771280a7e16 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java
@@ -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() {}
 }
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java
index 95fe51d8aae386792fb1b1915617de07e8652fc7..0384bff3904a30cccd4798a4fe299c9b940d6a63 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java
@@ -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;
+    }
 }
diff --git a/apps/routerconsole/jsp/config.jsp b/apps/routerconsole/jsp/config.jsp
index 428933d5112777e743085e076320c752fb94eb4e..70c0e64f00ef0657027eff2df4044ce2f224c195 100644
--- a/apps/routerconsole/jsp/config.jsp
+++ b/apps/routerconsole/jsp/config.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html" %>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -10,7 +11,7 @@
 <%@include file="summary.jsi" %>
 
 <jsp:useBean class="net.i2p.router.web.ConfigNetHelper" id="nethelper" scope="request" />
-<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <h1><%=intl._("I2P Bandwidth Configuration")%></h1>
 <div class="main" id="main">
  <%@include file="confignav.jsi" %>
@@ -18,7 +19,7 @@
  <jsp:useBean class="net.i2p.router.web.ConfigNetHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
 <div class="configure">
  <form action="" method="POST">
diff --git a/apps/routerconsole/jsp/configadvanced.jsp b/apps/routerconsole/jsp/configadvanced.jsp
index 85300a483595aebae665655faa825a4b2a840e34..1dbf23e7d452d17b8aa11ba07ffa9b57b4d4538f 100644
--- a/apps/routerconsole/jsp/configadvanced.jsp
+++ b/apps/routerconsole/jsp/configadvanced.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -10,7 +11,7 @@
 <%@include file="summary.jsi" %>
 
 <jsp:useBean class="net.i2p.router.web.ConfigAdvancedHelper" id="advancedhelper" scope="request" />
-<jsp:setProperty name="advancedhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="advancedhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 
 <h1><%=intl._("I2P Advanced Configuration")%></h1>
 <div class="main" id="main">
@@ -20,7 +21,7 @@
  <jsp:useBean class="net.i2p.router.web.ConfigAdvancedHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
  <div class="configure">
  <div class="wideload">
diff --git a/apps/routerconsole/jsp/configclients.jsp b/apps/routerconsole/jsp/configclients.jsp
index 7df1691175f159a1a5702cdee129a3c748a5b69b..6a700dedaa8b3985fcf5b7043e84893a703c6d12 100644
--- a/apps/routerconsole/jsp/configclients.jsp
+++ b/apps/routerconsole/jsp/configclients.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -15,17 +16,17 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
 <%@include file="summary.jsi" %>
 
 <jsp:useBean class="net.i2p.router.web.ConfigClientsHelper" id="clientshelper" scope="request" />
-<jsp:setProperty name="clientshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
-<jsp:setProperty name="clientshelper" property="edit" value="<%=request.getParameter("edit")%>" />
+<jsp:setProperty name="clientshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+<jsp:setProperty name="clientshelper" property="edit" value="<%=request.getParameter(\"edit\")%>" />
 <h1><%=intl._("I2P Client Configuration")%></h1>
 <div class="main" id="main">
  <%@include file="confignav.jsi" %>
 
  <jsp:useBean class="net.i2p.router.web.ConfigClientsHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
- <jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" />
- <jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+ <jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter(\"action\")%>" />
+ <jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter(\"nonce\")%>" />
  <jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
  <div class="configure">
diff --git a/apps/routerconsole/jsp/configkeyring.jsp b/apps/routerconsole/jsp/configkeyring.jsp
index 57367780d3c42fe4c46c2d5b61f9e77ede374f79..2d853e5eec8838ac650e3c84b559476640ff4536 100644
--- a/apps/routerconsole/jsp/configkeyring.jsp
+++ b/apps/routerconsole/jsp/configkeyring.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -15,10 +16,10 @@
  <jsp:useBean class="net.i2p.router.web.ConfigKeyringHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
  <jsp:useBean class="net.i2p.router.web.ConfigKeyringHelper" id="keyringhelper" scope="request" />
- <jsp:setProperty name="keyringhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="keyringhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <div class="configure"><h2><%=intl._("Keyring")%></h2><p>
  <%=intl._("The router keyring is used to decrypt encrypted leaseSets.")%>
  <%=intl._("The keyring may contain keys for local or remote encrypted destinations.")%></p>
diff --git a/apps/routerconsole/jsp/configlogging.jsp b/apps/routerconsole/jsp/configlogging.jsp
index a753950ca0e71ebbd9558e3901ab9f7f543690f8..8274fcb438dad183170f791923429be3c6d8072f 100644
--- a/apps/routerconsole/jsp/configlogging.jsp
+++ b/apps/routerconsole/jsp/configlogging.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -7,7 +8,7 @@
 <%=intl.title("config logging")%>
 </head><body>
 <jsp:useBean class="net.i2p.router.web.ConfigLoggingHelper" id="logginghelper" scope="request" />
-<jsp:setProperty name="logginghelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="logginghelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 
 <%@include file="summary.jsi" %>
 <h1><%=intl._("I2P Logging Configuration")%></h1>
@@ -17,7 +18,7 @@
  <jsp:useBean class="net.i2p.router.web.ConfigLoggingHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
 <div class="configure">
  <form action="" method="POST">
diff --git a/apps/routerconsole/jsp/confignav.jsi b/apps/routerconsole/jsp/confignav.jsi
index 68bde4bcbe41f87f1b6099ffcd5bea2c90f32465..81f3b0dc63cfe999248883104c094011674babd7 100644
--- a/apps/routerconsole/jsp/confignav.jsi
+++ b/apps/routerconsole/jsp/confignav.jsi
@@ -4,7 +4,7 @@
      */
 %>
 <jsp:useBean class="net.i2p.router.web.ConfigNavHelper" id="navHelper" scope="request" />
-<jsp:setProperty name="navHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="navHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <% navHelper.storeWriter(out); %>
 <div class="confignav" id="confignav">
 <%
diff --git a/apps/routerconsole/jsp/confignet.jsp b/apps/routerconsole/jsp/confignet.jsp
index 59b3f27d336121130407c1a7ba66429a39819d61..22b97ffe657e2f5382cb39d874b38e0330274a22 100644
--- a/apps/routerconsole/jsp/confignet.jsp
+++ b/apps/routerconsole/jsp/confignet.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html" %>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -10,7 +11,7 @@
 <%@include file="summary.jsi" %>
 
 <jsp:useBean class="net.i2p.router.web.ConfigNetHelper" id="nethelper" scope="request" />
-<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="nethelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <h1><%=intl._("I2P Network Configuration")%></h1>
 <div class="main" id="main">
  <%@include file="confignav.jsi" %>
@@ -18,7 +19,7 @@
  <jsp:useBean class="net.i2p.router.web.ConfigNetHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
 <div class="configure">
  <form action="" method="POST">
diff --git a/apps/routerconsole/jsp/configpeer.jsp b/apps/routerconsole/jsp/configpeer.jsp
index 04873ff547ecb2503afb3fce797c052be42aa0b7..4df9e5915d55bb0bd510fcb312ca31d044cabd6d 100644
--- a/apps/routerconsole/jsp/configpeer.jsp
+++ b/apps/routerconsole/jsp/configpeer.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -15,13 +16,13 @@
  <jsp:useBean class="net.i2p.router.web.ConfigPeerHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
 
 
 
  <jsp:useBean class="net.i2p.router.web.ConfigPeerHelper" id="peerhelper" scope="request" />
- <jsp:setProperty name="peerhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="peerhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 
  <% String peer = "";
     if (request.getParameter("peer") != null)
@@ -61,7 +62,7 @@
  </form>
  <a name="shitlist"> </a><h2><%=intl._("Banned Peers")%></h2>
  <jsp:useBean class="net.i2p.router.web.ProfilesHelper" id="profilesHelper" scope="request" />
- <jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <% profilesHelper.storeWriter(out); %>
  <jsp:getProperty name="profilesHelper" property="shitlistSummary" />
  <div class="wideload"><h2><%=intl._("Banned IPs")%></h2>
diff --git a/apps/routerconsole/jsp/configreseed.jsp b/apps/routerconsole/jsp/configreseed.jsp
index 648a14ee953e7678e0d56d5c3a86c07b2bd92d99..a807f22ba2128c06b89af5491ca1ea7576ac2cbc 100644
--- a/apps/routerconsole/jsp/configreseed.jsp
+++ b/apps/routerconsole/jsp/configreseed.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -10,16 +11,16 @@
 <%@include file="summary.jsi" %>
 
 <jsp:useBean class="net.i2p.router.web.ConfigReseedHelper" id="reseedHelper" scope="request" />
-<jsp:setProperty name="reseedHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="reseedHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <h1><%=intl._("I2P Reseeding Configuration")%></h1>
 <div class="main" id="main">
 <%@include file="confignav.jsi" %>
 
 <jsp:useBean class="net.i2p.router.web.ConfigReseedHandler" id="formhandler" scope="request" />
 <% formhandler.storeMethod(request.getMethod()); %>
-<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
-<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" />
-<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
+<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter(\"action\")%>" />
+<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter(\"nonce\")%>" />
 <jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
 <jsp:getProperty name="formhandler" property="allMessages" />
 <div class="configure"><form action="" method="POST">
diff --git a/apps/routerconsole/jsp/configservice.jsp b/apps/routerconsole/jsp/configservice.jsp
index 3a2f7af86dbc0b2358019d9d9cad18bc8cb1c26e..edff6766caf132da5146d1cf8e04ac0eabe516d7 100644
--- a/apps/routerconsole/jsp/configservice.jsp
+++ b/apps/routerconsole/jsp/configservice.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -15,7 +16,7 @@
  <jsp:useBean class="net.i2p.router.web.ConfigServiceHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
  <div class="configure">
  <form action="" method="POST">
diff --git a/apps/routerconsole/jsp/configstats.jsp b/apps/routerconsole/jsp/configstats.jsp
index 7e548a11361c6323e5e15112855c8e03dd36fe13..d9bcb20f43c214b14236ca88f496eb0514f4ae58 100644
--- a/apps/routerconsole/jsp/configstats.jsp
+++ b/apps/routerconsole/jsp/configstats.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -64,11 +65,11 @@ function toggleAll(category)
  <jsp:useBean class="net.i2p.router.web.ConfigStatsHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
 
  <jsp:useBean class="net.i2p.router.web.ConfigStatsHelper" id="statshelper" scope="request" />
- <jsp:setProperty name="statshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="statshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <div class="configure">
  <form id="statsForm" name="statsForm" action="" method="POST">
  <input type="hidden" name="action" value="foo" >
diff --git a/apps/routerconsole/jsp/configtunnels.jsp b/apps/routerconsole/jsp/configtunnels.jsp
index fb3fab1c3a28c2d69359c7acf41bb1f2d410eef9..eeb6a752cfdef8ea6e3e4e120127f70d913eeb70 100644
--- a/apps/routerconsole/jsp/configtunnels.jsp
+++ b/apps/routerconsole/jsp/configtunnels.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -10,16 +11,16 @@
 <%@include file="summary.jsi" %>
 
 <jsp:useBean class="net.i2p.router.web.ConfigTunnelsHelper" id="tunnelshelper" scope="request" />
-<jsp:setProperty name="tunnelshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="tunnelshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <h1><%=intl._("I2P Tunnel Configuration")%></h1>
 <div class="main" id="main">
  <%@include file="confignav.jsi" %>
  <jsp:useBean class="net.i2p.router.web.ConfigTunnelsHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
- <jsp:setProperty name="formhandler" property="shouldsave" value="<%=request.getParameter("shouldsave")%>" />
- <jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" />
- <jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+ <jsp:setProperty name="formhandler" property="shouldsave" value="<%=request.getParameter(\"shouldsave\")%>" />
+ <jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter(\"action\")%>" />
+ <jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter(\"nonce\")%>" />
  <jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
  <div class="configure"><p>
diff --git a/apps/routerconsole/jsp/configui.jsp b/apps/routerconsole/jsp/configui.jsp
index bde01f40b41249462a4e3d95be1b95eca68cb44f..4a214c852419f97e9b8a35ebed8b3a3afed20787 100644
--- a/apps/routerconsole/jsp/configui.jsp
+++ b/apps/routerconsole/jsp/configui.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -10,7 +11,7 @@
 <%@include file="summary.jsi" %>
 
 <jsp:useBean class="net.i2p.router.web.ConfigUIHelper" id="uihelper" scope="request" />
-<jsp:setProperty name="uihelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="uihelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 
 <h1><%=uihelper._("I2P UI Configuration")%></h1>
 <div class="main" id="main">
@@ -20,7 +21,7 @@
  <jsp:useBean class="net.i2p.router.web.ConfigUIHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
 <div class="configure"><div class="topshimten"><h3><%=uihelper._("Router Console Theme")%></h3></div>
  <form action="" method="POST">
diff --git a/apps/routerconsole/jsp/configupdate.jsp b/apps/routerconsole/jsp/configupdate.jsp
index c3066ade634da3c58e851ccca958709539aa5084..691c293e0eb4c4027e915ba25f7e2a1548c235a2 100644
--- a/apps/routerconsole/jsp/configupdate.jsp
+++ b/apps/routerconsole/jsp/configupdate.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -15,10 +16,10 @@
  <jsp:useBean class="net.i2p.router.web.ConfigUpdateHandler" id="formhandler" scope="request" />
  <% formhandler.storeMethod(request.getMethod()); %>
  <jsp:setProperty name="formhandler" property="*" />
- <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="formhandler" property="allMessages" />
  <jsp:useBean class="net.i2p.router.web.ConfigUpdateHelper" id="updatehelper" scope="request" />
- <jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <div class="messages">
  <jsp:getProperty name="updatehelper" property="newsStatus" /></div>
 <div class="configure">
diff --git a/apps/routerconsole/jsp/css.jsi b/apps/routerconsole/jsp/css.jsi
index 33c9312c6aa935cb255d6b12ed45fb8baa88effd..767d0d071e6f0ea75bc91f5b4e800d67e43bb2b2 100644
--- a/apps/routerconsole/jsp/css.jsi
+++ b/apps/routerconsole/jsp/css.jsi
@@ -27,7 +27,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <link rel="shortcut icon" href="/themes/console/images/favicon.ico">
 <jsp:useBean class="net.i2p.router.web.CSSHelper" id="intl" scope="request" />
-<jsp:setProperty name="intl" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="intl" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <%
    String conNonceParam = request.getParameter("consoleNonce");
    if (conNonceParam != null && conNonceParam.equals(System.getProperty("router.consoleNonce"))) {
diff --git a/apps/routerconsole/jsp/debug.jsp b/apps/routerconsole/jsp/debug.jsp
index 9f6aae5740636b8fc2d9e8239d78ef4a06cde564..b9e66345f677234ef6b7166710ba72bb004ae386 100644
--- a/apps/routerconsole/jsp/debug.jsp
+++ b/apps/routerconsole/jsp/debug.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/dumpprofile.jsp b/apps/routerconsole/jsp/dumpprofile.jsp
index af6c8de744c5319a1dbac503ebc66cce641375ef..7b08097434c6e702042cb2c4c9f5babb27a79ece 100644
--- a/apps/routerconsole/jsp/dumpprofile.jsp
+++ b/apps/routerconsole/jsp/dumpprofile.jsp
@@ -1,6 +1,6 @@
 <%@page contentType="text/plain"
 %><jsp:useBean id="helper" class="net.i2p.router.web.StatHelper"
-/><jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>"
-/><jsp:setProperty name="helper" property="peer" value="<%=net.i2p.data.DataHelper.stripHTML(request.getParameter("peer"))%>"
+/><jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>"
+/><jsp:setProperty name="helper" property="peer" value="<%=net.i2p.data.DataHelper.stripHTML(request.getParameter(\"peer\"))%>"
 /><% helper.storeWriter(out);
 %><jsp:getProperty name="helper" property="profile" />
diff --git a/apps/routerconsole/jsp/error.jsp b/apps/routerconsole/jsp/error.jsp
index 7bcfc3318e766d82b115b9cb6577366b57c79f69..69f9fbfa3190ccb8f920b93b1dc045906baca32d 100644
--- a/apps/routerconsole/jsp/error.jsp
+++ b/apps/routerconsole/jsp/error.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/error500.jsp b/apps/routerconsole/jsp/error500.jsp
index 56ebe9b1778e064ae691694465c8a6c7848662ce..2b420e4f6d13b49d60a7e1abd536068130d98fca 100644
--- a/apps/routerconsole/jsp/error500.jsp
+++ b/apps/routerconsole/jsp/error500.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
@@ -57,7 +58,7 @@
 <b>Java version:</b> <%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%> (<%=System.getProperty("java.runtime.name")%> <%=System.getProperty("java.runtime.version")%>)<br>
 <b>Wrapper version:</b> <%=System.getProperty("wrapper.version", "none")%><br>
  <jsp:useBean class="net.i2p.router.web.LogsHelper" id="logsHelper" scope="request" />
- <jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <b>Server version:</b> <jsp:getProperty name="logsHelper" property="jettyVersion" /><br>
 <b>Platform:</b> <%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br>
 <b>Processor:</b> <%=net.i2p.util.NativeBigInteger.cpuModel()%> (<%=net.i2p.util.NativeBigInteger.cpuType()%>)<br>
diff --git a/apps/routerconsole/jsp/graphs.jsp b/apps/routerconsole/jsp/graphs.jsp
index e54133250a7233399a9c3e696fae2a2daf3f3324..54c8e69e055c2fbffda54a20d8ce7dc487e860a2 100644
--- a/apps/routerconsole/jsp/graphs.jsp
+++ b/apps/routerconsole/jsp/graphs.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -7,7 +8,7 @@
 <%=intl.title("graphs")%>
  <jsp:useBean class="net.i2p.router.web.GraphHelper" id="graphHelper" scope="request" />
  <% graphHelper.storeMethod(request.getMethod()); %>
- <jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
  <jsp:setProperty name="graphHelper" property="*" />
 <%
diff --git a/apps/routerconsole/jsp/help.jsp b/apps/routerconsole/jsp/help.jsp
index 9a8f97afb94fcfc43749543cc7ee54c57e227c28..265bbfb6286f01bca2a89020a60ac6669e247e1f 100644
--- a/apps/routerconsole/jsp/help.jsp
+++ b/apps/routerconsole/jsp/help.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/help_ar.jsp b/apps/routerconsole/jsp/help_ar.jsp
index 3672aef97583610f88cdede0f8f8ea73b833efa2..4b471f594fbb478b9141fe373c59fdb1eb3a01b6 100644
--- a/apps/routerconsole/jsp/help_ar.jsp
+++ b/apps/routerconsole/jsp/help_ar.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/help_fr.jsp b/apps/routerconsole/jsp/help_fr.jsp
index 74ff18b400bb6a11492100bd4424eed89bc20591..fd0f8bc2682a6462e3df27d32939b169f524aa09 100644
--- a/apps/routerconsole/jsp/help_fr.jsp
+++ b/apps/routerconsole/jsp/help_fr.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/help_nl.jsp b/apps/routerconsole/jsp/help_nl.jsp
index 57b0d73fa1b95175ee3eacdff43863c2b05ee6a4..944e65e7b9e3bd3e1623e4513df2aa586275cc14 100644
--- a/apps/routerconsole/jsp/help_nl.jsp
+++ b/apps/routerconsole/jsp/help_nl.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/help_ru.jsp b/apps/routerconsole/jsp/help_ru.jsp
index 1b5d9e84c8c343220037dbd27ebc414f911cfa20..d14da013864ecfa4d415301ccbf0516f8ccac416 100644
--- a/apps/routerconsole/jsp/help_ru.jsp
+++ b/apps/routerconsole/jsp/help_ru.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/i2psnark/index.html b/apps/routerconsole/jsp/i2psnark/index.html
deleted file mode 100644
index 681b946562776f185d74ae4946525aacd148ec96..0000000000000000000000000000000000000000
--- a/apps/routerconsole/jsp/i2psnark/index.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html><head><title>I2PSnark Anonymous BitTorrent Client Disabled</title>
-<meta http-equiv="cache-control" content="no-cache" />
-<meta http-equiv="pragma" content="no-cache" />
-</head>
-<body>
-The I2PSnark Anonymous BitTorrent Client is not running. Please visit the <a href="/configclients#webapp">config clients page</a>
-to start it.
-</body></html>
diff --git a/apps/routerconsole/jsp/i2ptunnel/index.jsp b/apps/routerconsole/jsp/i2ptunnel/index.jsp
deleted file mode 100644
index db3648aa07e410fe3ed9fbfb80c45e739ee819b3..0000000000000000000000000000000000000000
--- a/apps/routerconsole/jsp/i2ptunnel/index.jsp
+++ /dev/null
@@ -1,7 +0,0 @@
-<html><head><title>I2P Tunnel Manager Not Running</title>
-<meta http-equiv="cache-control" content="no-cache" />
-<meta http-equiv="pragma" content="no-cache" />
-</head>
-<body>
-The I2P Tunnel Manager is not currently running. Please visit the <a href="/configclients#webapp">Client Configuration</a> page to start it.
-</body></html>
diff --git a/apps/routerconsole/jsp/index.jsp b/apps/routerconsole/jsp/index.jsp
index 238e454e7581d9d08d0ee4648f5e634d8762eb1c..92b8f32fab1b119ec63d051542cc0e13fbd31131 100644
--- a/apps/routerconsole/jsp/index.jsp
+++ b/apps/routerconsole/jsp/index.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -17,7 +18,7 @@
 <%@include file="summary.jsi" %><h1><%=intl._("I2P Router Console")%></h1>
 <div class="news" id="news">
  <jsp:useBean class="net.i2p.router.web.NewsHelper" id="newshelper" scope="request" />
- <jsp:setProperty name="newshelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="newshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <%
    if (newshelper.shouldShowNews()) {
        java.io.File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getRouterDir(), "docs/news.xml");
@@ -30,7 +31,7 @@
    }  // shouldShowNews()
 %>
  <jsp:useBean class="net.i2p.router.web.ConfigUpdateHelper" id="updatehelper" scope="request" />
- <jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="updatehelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="updatehelper" property="newsStatus" /><br>
 </div><div class="main" id="main">
  <jsp:useBean class="net.i2p.router.web.ContentHelper" id="contenthelper" scope="request" />
@@ -61,6 +62,6 @@
  <% java.io.File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getBaseDir(), "docs/readme.html"); %>
  <jsp:setProperty name="contenthelper" property="page" value="<%=fpath.getAbsolutePath()%>" />
  <jsp:setProperty name="contenthelper" property="maxLines" value="300" />
- <jsp:setProperty name="contenthelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="contenthelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <jsp:getProperty name="contenthelper" property="content" />
 </div></body></html>
diff --git a/apps/routerconsole/jsp/jobs.jsp b/apps/routerconsole/jsp/jobs.jsp
index 53916dcd44ed0d2ff65f9eb389b6edb66487974e..2e2e712484cbd9d4a7396b0e8630f9bca59d2d9c 100644
--- a/apps/routerconsole/jsp/jobs.jsp
+++ b/apps/routerconsole/jsp/jobs.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -9,7 +10,7 @@
 <%@include file="summary.jsi" %><h1><%=intl._("I2P Router Job Queue")%></h1>
 <div class="main" id="main">
  <jsp:useBean class="net.i2p.router.web.JobQueueHelper" id="jobQueueHelper" scope="request" />
- <jsp:setProperty name="jobQueueHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="jobQueueHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <% jobQueueHelper.storeWriter(out); %>
  <jsp:getProperty name="jobQueueHelper" property="jobQueueSummary" />
 <hr></div></body></html>
diff --git a/apps/routerconsole/jsp/logs.jsp b/apps/routerconsole/jsp/logs.jsp
index a1551bb57c8045d7ab7765e7e05549c5fed53412..95786e7988030764f468d450bce8a6aabdd36999 100644
--- a/apps/routerconsole/jsp/logs.jsp
+++ b/apps/routerconsole/jsp/logs.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -22,7 +23,7 @@
 <b>Java version:</b> <%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%> (<%=System.getProperty("java.runtime.name")%> <%=System.getProperty("java.runtime.version")%>)<br>
 <b>Wrapper version:</b> <%=System.getProperty("wrapper.version", "none")%><br>
  <jsp:useBean class="net.i2p.router.web.LogsHelper" id="logsHelper" scope="request" />
- <jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <b>Server version:</b> <jsp:getProperty name="logsHelper" property="jettyVersion" /><br>
 <b>Platform:</b> <%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br>
 <b>Processor:</b> <%=net.i2p.util.NativeBigInteger.cpuModel()%> (<%=net.i2p.util.NativeBigInteger.cpuType()%>)<br>
diff --git a/apps/routerconsole/jsp/netdb.jsp b/apps/routerconsole/jsp/netdb.jsp
index 2862e9e0e727df2c9502352bf92d2db603edb2ea..cfbd3b2ac1a572432e3ccfb0351ee9c6caf51842 100644
--- a/apps/routerconsole/jsp/netdb.jsp
+++ b/apps/routerconsole/jsp/netdb.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -11,10 +12,10 @@
 <div class="main" id="main">
  <div class="wideload">
  <jsp:useBean class="net.i2p.router.web.NetDbHelper" id="netdbHelper" scope="request" />
- <jsp:setProperty name="netdbHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="netdbHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <% netdbHelper.storeWriter(out); %>
- <jsp:setProperty name="netdbHelper" property="full" value="<%=request.getParameter("f")%>" />
- <jsp:setProperty name="netdbHelper" property="router" value="<%=request.getParameter("r")%>" />
- <jsp:setProperty name="netdbHelper" property="lease" value="<%=request.getParameter("l")%>" />
+ <jsp:setProperty name="netdbHelper" property="full" value="<%=request.getParameter(\"f\")%>" />
+ <jsp:setProperty name="netdbHelper" property="router" value="<%=request.getParameter(\"r\")%>" />
+ <jsp:setProperty name="netdbHelper" property="lease" value="<%=request.getParameter(\"l\")%>" />
  <jsp:getProperty name="netdbHelper" property="netDbSummary" />
 </div></div></body></html>
diff --git a/apps/routerconsole/jsp/nowebapp.jsp b/apps/routerconsole/jsp/nowebapp.jsp
index f62ae6b162875be0bf4441ee1b3a3b28c387c1c5..1bbec502ddd1eea61bb2911c828bc4b6dcf89d6e 100644
--- a/apps/routerconsole/jsp/nowebapp.jsp
+++ b/apps/routerconsole/jsp/nowebapp.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/oldconsole.jsp b/apps/routerconsole/jsp/oldconsole.jsp
index 3612169e41f1ff9be503ca06e273206d7db3980b..7edb7624097d24134acf92d21871c33844ebacf7 100644
--- a/apps/routerconsole/jsp/oldconsole.jsp
+++ b/apps/routerconsole/jsp/oldconsole.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
@@ -11,7 +12,7 @@
 </head><body>
 <%@include file="summary.jsi" %>
 <jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="conhelper" scope="request" />
-<jsp:setProperty name="conhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="conhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <% conhelper.storeWriter(out); %>
  <h1>I2P Router &raquo; Old Console</h1>
 <div class="main" id="main">
diff --git a/apps/routerconsole/jsp/peers.jsp b/apps/routerconsole/jsp/peers.jsp
index 4b48c5957d56b214c2ba61e574e5903f22241736..6b0ed6b67b0d135d92d70869976aa880f60e1a78 100644
--- a/apps/routerconsole/jsp/peers.jsp
+++ b/apps/routerconsole/jsp/peers.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -10,9 +11,9 @@
 <h1><%=intl._("I2P Network Peers")%></h1>
 <div class="main" id="main"><div class="wideload">
  <jsp:useBean class="net.i2p.router.web.PeerHelper" id="peerHelper" scope="request" />
- <jsp:setProperty name="peerHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="peerHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <% peerHelper.storeWriter(out); %>
  <jsp:setProperty name="peerHelper" property="urlBase" value="peers.jsp" />
- <jsp:setProperty name="peerHelper" property="sort" value="<%=request.getParameter("sort") != null ? request.getParameter("sort") : ""%>" />
+ <jsp:setProperty name="peerHelper" property="sort" value="<%=request.getParameter(\"sort\") != null ? request.getParameter(\"sort\") : \"\"%>" />
  <jsp:getProperty name="peerHelper" property="peerSummary" />
 </div></div></body></html>
diff --git a/apps/routerconsole/jsp/profiles.jsp b/apps/routerconsole/jsp/profiles.jsp
index 98ec4882818f2942d11676d4867e2244f1964b94..8441838e2d8853a80c833e9088e039b57ab12155 100644
--- a/apps/routerconsole/jsp/profiles.jsp
+++ b/apps/routerconsole/jsp/profiles.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -9,9 +10,9 @@
 <h1><%=intl._("I2P Network Peer Profiles")%></h1>
 <div class="main" id="main"><div class="wideload">
  <jsp:useBean class="net.i2p.router.web.ProfilesHelper" id="profilesHelper" scope="request" />
- <jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="profilesHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <% profilesHelper.storeWriter(out); %>
- <jsp:setProperty name="profilesHelper" property="full" value="<%=request.getParameter("f")%>" />
+ <jsp:setProperty name="profilesHelper" property="full" value="<%=request.getParameter(\"f\")%>" />
  <jsp:getProperty name="profilesHelper" property="profileSummary" />
  <a name="shitlist"> </a><h2><%=intl._("Banned Peers")%></h2>
  <jsp:getProperty name="profilesHelper" property="shitlistSummary" />
diff --git a/apps/routerconsole/jsp/stats.jsp b/apps/routerconsole/jsp/stats.jsp
index d2787dea968f2091ff1fdc4f5f57be5c0c20a959..c0596f796117f0c2151bcea09b65e096f69b75d3 100644
--- a/apps/routerconsole/jsp/stats.jsp
+++ b/apps/routerconsole/jsp/stats.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -8,9 +9,9 @@
 </head><body>
 <%@include file="summary.jsi" %>
 <jsp:useBean class="net.i2p.router.web.OldConsoleHelper" id="oldhelper" scope="request" />
-<jsp:setProperty name="oldhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="oldhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <% oldhelper.storeWriter(out); %>
-<jsp:setProperty name="oldhelper" property="full" value="<%=request.getParameter("f")%>" />
+<jsp:setProperty name="oldhelper" property="full" value="<%=request.getParameter(\"f\")%>" />
  <h1><%=intl._("I2P Router Statistics")%></h1>
 <div class="main" id="main">
  <jsp:getProperty name="oldhelper" property="stats" />
diff --git a/apps/routerconsole/jsp/summaryframe.jsp b/apps/routerconsole/jsp/summaryframe.jsp
index 541f0f13f52aeb95ebfe2f29362b5d135d6980a2..bdd4a8cbc1923b44b6f7b54ab901607e5e28a690 100644
--- a/apps/routerconsole/jsp/summaryframe.jsp
+++ b/apps/routerconsole/jsp/summaryframe.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <%
diff --git a/apps/routerconsole/jsp/summarynoframe.jsi b/apps/routerconsole/jsp/summarynoframe.jsi
index 355f4bc0b24d08ed9971810dbcd42819fd8a7575..63c39e6e5449f5a81e4c4efac3b7af31e7466c14 100644
--- a/apps/routerconsole/jsp/summarynoframe.jsi
+++ b/apps/routerconsole/jsp/summarynoframe.jsi
@@ -6,10 +6,10 @@
  */
 %>
 <jsp:useBean class="net.i2p.router.web.SummaryHelper" id="helper" scope="request" />
-<jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
-<jsp:setProperty name="helper" property="action" value="<%=request.getParameter("action")%>" />
-<jsp:setProperty name="helper" property="updateNonce" value="<%=request.getParameter("updateNonce")%>" />
-<jsp:setProperty name="helper" property="consoleNonce" value="<%=request.getParameter("consoleNonce")%>" />
+<jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+<jsp:setProperty name="helper" property="action" value="<%=request.getParameter(\"action\")%>" />
+<jsp:setProperty name="helper" property="updateNonce" value="<%=request.getParameter(\"updateNonce\")%>" />
+<jsp:setProperty name="helper" property="consoleNonce" value="<%=request.getParameter(\"consoleNonce\")%>" />
 <jsp:setProperty name="helper" property="requestURI" value="<%=request.getRequestURI()%>" />
 <% helper.storeWriter(out); %>
 <%
@@ -28,7 +28,7 @@
 %>
 <jsp:useBean class="net.i2p.router.web.UpdateHandler" id="update" scope="request" />
 <jsp:setProperty name="update" property="*" />
-<jsp:setProperty name="update" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="update" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <%
     // moved to java for ease of translation and to avoid 30 copies
     helper.renderSummaryBar();
diff --git a/apps/routerconsole/jsp/susidns/index.jsp b/apps/routerconsole/jsp/susidns/index.jsp
deleted file mode 100644
index 2964615e3153b78ca2dd880c574c22356a81f2b9..0000000000000000000000000000000000000000
--- a/apps/routerconsole/jsp/susidns/index.jsp
+++ /dev/null
@@ -1,8 +0,0 @@
-<html><head><title>SusiDNS Disabled</title>
-<meta http-equiv="cache-control" content="no-cache" />
-<meta http-equiv="pragma" content="no-cache" />
-</head>
-<body>
-SusiDNS is not running. Go to <a href="/configclients#webapp">the config clients page</a>
-to start it.
-</body></html>
diff --git a/apps/routerconsole/jsp/susimail/susimail b/apps/routerconsole/jsp/susimail/susimail
deleted file mode 100644
index 32e9d3787b118f6051fa0ff0adb672c6fb47be0a..0000000000000000000000000000000000000000
--- a/apps/routerconsole/jsp/susimail/susimail
+++ /dev/null
@@ -1,8 +0,0 @@
-<html><head><title>SusiMail Disabled</title>
-<meta http-equiv="cache-control" content="no-cache" />
-<meta http-equiv="pragma" content="no-cache" />
-</head>
-<body>
-SusiMail is not running. Go to <a href="/configclients#webapp">the config clients page</a>
-to start it.
-</body></html>
diff --git a/apps/routerconsole/jsp/tunnels.jsp b/apps/routerconsole/jsp/tunnels.jsp
index e01b331f6bb2a2775b43f4d1b65579791c4665ca..32f86475aea815642b3e28c03d5de51ebaff3b3f 100644
--- a/apps/routerconsole/jsp/tunnels.jsp
+++ b/apps/routerconsole/jsp/tunnels.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -9,7 +10,7 @@
 <%@include file="summary.jsi" %><h1><%=intl._("I2P Tunnel Summary")%></h1>
 <div class="main" id="main">
  <jsp:useBean class="net.i2p.router.web.TunnelHelper" id="tunnelHelper" scope="request" />
- <jsp:setProperty name="tunnelHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+ <jsp:setProperty name="tunnelHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
  <% tunnelHelper.storeWriter(out); %>
  <jsp:getProperty name="tunnelHelper" property="tunnelSummary" />
 </div></body></html>
diff --git a/apps/routerconsole/jsp/viewprofile.jsp b/apps/routerconsole/jsp/viewprofile.jsp
index 36897d4a9aae345d19e760356554b406ca5f39b6..8747a6d88b888639293a3c69cf4f79a774b4120d 100644
--- a/apps/routerconsole/jsp/viewprofile.jsp
+++ b/apps/routerconsole/jsp/viewprofile.jsp
@@ -1,4 +1,5 @@
 <%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@page pageEncoding="UTF-8"%>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
@@ -17,7 +18,7 @@
         peerB64 = net.i2p.data.DataHelper.stripHTML(peerB64);  // XSS
 %>
 <jsp:useBean id="stathelper" class="net.i2p.router.web.StatHelper" />
-<jsp:setProperty name="stathelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
+<jsp:setProperty name="stathelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
 <jsp:setProperty name="stathelper" property="peer" value="<%=peerB64%>" />
 <% stathelper.storeWriter(out); %>
 <h2><%=intl._("Profile for peer {0}", peerB64)%></h2>
diff --git a/apps/susidns/src/WEB-INF/lib/README.txt b/apps/susidns/src/WEB-INF/lib/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0bc353fd417565f925afe51f005bb236cd21aec8
--- /dev/null
+++ b/apps/susidns/src/WEB-INF/lib/README.txt
@@ -0,0 +1,12 @@
+These are 1.2 libs downloaded from http://jstl.java.net/download.html
+Licenses: Common Development and Distribution License (CDDL) version 1.0 + GNU General Public License (GPL) version 2
+          https://glassfish.dev.java.net/public/CDDL+GPL.html
+
+1.2 libs are compatible with JSP 2.1 containers.
+See http://www.coderanch.com/how-to/java/JstlTagLibDefinitions for more info.
+
+The previous files were version 1.1.2 for JSP 2.0.
+Old names kept so they are overwritten in the update and are in the classpath.
+
+jstl-api-1.2.jar  -> jstl.jar
+jstl-impl-1.2.jar -> standard.jar
diff --git a/apps/susidns/src/WEB-INF/lib/jstl.jar b/apps/susidns/src/WEB-INF/lib/jstl.jar
index 893b4dd1dc99f6f23502f645b36fb5c9e6a39382..183ed63f44e0321354755585ab6064dca9b5bb5c 100644
Binary files a/apps/susidns/src/WEB-INF/lib/jstl.jar and b/apps/susidns/src/WEB-INF/lib/jstl.jar differ
diff --git a/apps/susidns/src/WEB-INF/lib/standard.jar b/apps/susidns/src/WEB-INF/lib/standard.jar
index e84c1a23ca74575bca6e8ee5171c68727e906d06..110ca517c35a0ec85415e361aaf93bfe3215b3f9 100644
Binary files a/apps/susidns/src/WEB-INF/lib/standard.jar and b/apps/susidns/src/WEB-INF/lib/standard.jar differ
diff --git a/apps/susidns/src/build.xml b/apps/susidns/src/build.xml
index 3fff55a34c9fce7f4e652c65027842ddd79d6a28..78975eaf5d160214c4b169ab11039595b9878003 100644
--- a/apps/susidns/src/build.xml
+++ b/apps/susidns/src/build.xml
@@ -17,9 +17,10 @@
         <pathelement location="${lib}/jasper-compiler.jar" />
         <pathelement location="${lib}/jasper-runtime.jar" />
         <pathelement location="${lib}/javax.servlet.jar" />
+        <pathelement location="${lib}/jsp-api.jar" />
         <pathelement location="${lib}/commons-logging.jar" />
         <pathelement location="${lib}/commons-el.jar" />
-        <pathelement location="${lib}/ant.jar" />
+        <pathelement location="${ant.home}/lib/ant.jar" />
         <pathelement location="../../../core/java/build/i2p.jar" />
  	</path>
 	<property name="javac.compilerargs" value="" />
diff --git a/apps/susidns/src/jsp/addressbook.jsp b/apps/susidns/src/jsp/addressbook.jsp
index 4736a4dc01c0bf78f99b4879cbd32a508e5cb14c..e2ca96dbda0e20b255997312187d2264e53c772a 100644
--- a/apps/susidns/src/jsp/addressbook.jsp
+++ b/apps/susidns/src/jsp/addressbook.jsp
@@ -29,6 +29,7 @@
 
 %>
 <%@page pageEncoding="UTF-8"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@ page contentType="text/html"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 <jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />
diff --git a/apps/susidns/src/jsp/config.jsp b/apps/susidns/src/jsp/config.jsp
index 23cce5adadc4900af64b849084b49ce547f69427..970bc4cf33fa4b6708feaeb57dac12be270d3744 100644
--- a/apps/susidns/src/jsp/config.jsp
+++ b/apps/susidns/src/jsp/config.jsp
@@ -29,6 +29,7 @@
 
 %>
 <%@page pageEncoding="UTF-8"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@ page contentType="text/html" %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 <jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application"/>
diff --git a/apps/susidns/src/jsp/details.jsp b/apps/susidns/src/jsp/details.jsp
index f9769ecac13f3b655cf730edcbed1a6de7b87552..957ec44bb59fa18e03bd831361ea8ed69a5ad16b 100644
--- a/apps/susidns/src/jsp/details.jsp
+++ b/apps/susidns/src/jsp/details.jsp
@@ -26,6 +26,7 @@
 
 %>
 <%@page pageEncoding="UTF-8"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@ page contentType="text/html"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 <jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />
diff --git a/apps/susidns/src/jsp/index.jsp b/apps/susidns/src/jsp/index.jsp
index 7c55c84651bee7b8a35caa54e6e8ab8f9db03112..1cb170d9df7d4bf756e04e616248fcc69a4000ea 100644
--- a/apps/susidns/src/jsp/index.jsp
+++ b/apps/susidns/src/jsp/index.jsp
@@ -29,6 +29,7 @@
 
 %>
 <%@page pageEncoding="UTF-8"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@ page contentType="text/html"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 <jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />
diff --git a/apps/susidns/src/jsp/subscriptions.jsp b/apps/susidns/src/jsp/subscriptions.jsp
index 8d1c6c24894a4fad5920c93a631687e5e5f8bf7c..77c554686a3bfefff5940896db453b62df804fbb 100644
--- a/apps/susidns/src/jsp/subscriptions.jsp
+++ b/apps/susidns/src/jsp/subscriptions.jsp
@@ -29,6 +29,7 @@
 
 %>
 <%@page pageEncoding="UTF-8"%>
+<%@page trimDirectiveWhitespaces="true"%>
 <%@ page contentType="text/html"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 <jsp:useBean id="version" class="i2p.susi.dns.VersionBean" scope="application" />
diff --git a/apps/susimail/build.xml b/apps/susimail/build.xml
index 3368283d115e8b65a72f790f99e4c982d7f4b75d..4d38794c29f65bafb4ee89f4819b3b2093bd2563 100644
--- a/apps/susimail/build.xml
+++ b/apps/susimail/build.xml
@@ -19,6 +19,7 @@
             <classpath>
                 <pathelement location="../jetty/jettylib/javax.servlet.jar" />
                 <pathelement location="../jetty/jettylib/org.mortbay.jetty.jar" />
+                <pathelement location="../jetty/jettylib/jetty-util.jar" />
                 <pathelement location="../../core/java/build/i2p.jar" />
             </classpath>
         </javac>
diff --git a/apps/susimail/src/WEB-INF/web.xml b/apps/susimail/src/WEB-INF/web.xml
index bab239ed07608375851b22737e772cad46e407b4..e3f93d229f1ae1a0b780dd64fab24a01a08240b0 100644
--- a/apps/susimail/src/WEB-INF/web.xml
+++ b/apps/susimail/src/WEB-INF/web.xml
@@ -15,4 +15,26 @@
   <session-config>
     <session-timeout>15</session-timeout>
   </session-config>
-</web-app>
+
+<!--
+     Jetty 6 mulipart form handling
+     See http://docs.codehaus.org/display/JETTY/File+Upload+in+jetty6
+     and RequestWrapper.java.
+     Unused because it doesn't support content-type until Jetty 8.
+
+    <filter>
+        <filter-name>fileuploadfilter</filter-name>
+        <filter-class>org.mortbay.servlet.MultiPartFilter</filter-class>
+        <init-param>
+            <param-name>deleteFiles</param-name>
+            <param-value>true</param-value>
+        </init-param>
+    </filter>
+
+    <filter-mapping>
+        <filter-name>fileuploadfilter</filter-name>
+        <url-pattern>/susimail</url-pattern>
+    </filter-mapping>
+-->
+
+-</web-app>
diff --git a/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java b/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java
index 98350708ca9156cfbb59b43880fb3fdcea39c516..c02aae599fd23f07312719848632237690e186a3 100644
--- a/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java
+++ b/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java
@@ -35,6 +35,19 @@ import javax.servlet.http.HttpSession;
 import org.mortbay.servlet.MultiPartRequest;
 
 /**
+ *  Required major changes for Jetty 6
+ *  to support change from MultiPartRequest to MultiPartFilter.
+ *  See http://docs.codehaus.org/display/JETTY/File+Upload+in+jetty6
+ *  Unfortunately, Content-type not available until Jetty 8
+ *  See https://bugs.eclipse.org/bugs/show_bug.cgi?id=349110
+ *
+ *  So we could either extend and fix MultiPartFilter, and rewrite everything here,
+ *  or copy MultiParRequest into our war and fix it so it compiles with Jetty 6.
+ *  We do the latter.
+ *
+ *  The filter would have been added in web.xml,
+ *  see that file, where it's commented out.
+ *
  * @author user
  */
 public class RequestWrapper {
diff --git a/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java b/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5effd4ea578746188afd48f5c3e819f756934506
--- /dev/null
+++ b/apps/susimail/src/src/org/mortbay/servlet/MultiPartRequest.java
@@ -0,0 +1,447 @@
+// ========================================================================
+// $Id: MultiPartRequest.java,v 1.16 2005/12/02 20:13:52 gregwilkins Exp $
+// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at 
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================================================================
+
+package org.mortbay.servlet;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.servlet.http.HttpServletRequest;
+
+//import org.apache.commons.logging.Log;
+//import org.mortbay.log.LogFactory;
+import org.mortbay.jetty.HttpHeaders;
+import org.mortbay.util.LineInput;
+import org.mortbay.util.MultiMap;
+import org.mortbay.util.StringUtil;
+
+/* ------------------------------------------------------------ */
+/** Multipart Form Data request.
+ * <p>
+ * This class decodes the multipart/form-data stream sent by
+ * a HTML form that uses a file input item.
+ *
+ * <p><h4>Usage</h4>
+ * Each part of the form data is named from the HTML form and
+ * is available either via getString(name) or getInputStream(name).
+ * Furthermore the MIME parameters and filename can be requested for
+ * each part.
+ * <pre>
+ * </pre>
+ *
+ * Modded to compile with Jetty 6 for I2P
+ *
+ * @version $Id: MultiPartRequest.java,v 1.16 2005/12/02 20:13:52 gregwilkins Exp $
+ * @author  Greg Wilkins
+ * @author  Jim Crossley
+ */
+public class MultiPartRequest
+{
+    //private static Log log = LogFactory.getLog(MultiPartRequest.class);
+
+    /* ------------------------------------------------------------ */
+    HttpServletRequest _request;
+    LineInput _in;
+    String _boundary;
+    String _encoding;
+    byte[] _byteBoundary;
+    MultiMap _partMap = new MultiMap(10);
+    int _char=-2;
+    boolean _lastPart=false;
+    
+    /* ------------------------------------------------------------ */
+    /** Constructor. 
+     * @param request The request containing a multipart/form-data
+     * request
+     * @exception IOException IOException
+     */
+    public MultiPartRequest(HttpServletRequest request)
+        throws IOException
+    {
+        _request=request;
+        String content_type = request.getHeader(HttpHeaders.CONTENT_TYPE);
+        if (!content_type.startsWith("multipart/form-data"))
+            throw new IOException("Not multipart/form-data request");
+
+        //if(log.isDebugEnabled())log.debug("Multipart content type = "+content_type);
+        _encoding = request.getCharacterEncoding();
+        if (_encoding != null)
+            _in = new LineInput(request.getInputStream(), 2048, _encoding);
+        else
+            _in = new LineInput(request.getInputStream());
+        
+        // Extract boundary string
+        _boundary="--"+
+            value(content_type.substring(content_type.indexOf("boundary=")));
+        
+        //if(log.isDebugEnabled())log.debug("Boundary="+_boundary);
+        _byteBoundary= (_boundary+"--").getBytes(StringUtil.__ISO_8859_1);
+        
+        loadAllParts();
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Get the part names.
+     * @return an array of part names
+     */
+    public String[] getPartNames()
+    {
+        Set s = _partMap.keySet();
+        return (String[]) s.toArray(new String[s.size()]);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Check if a named part is present 
+     * @param name The part
+     * @return true if it was included 
+     */
+    public boolean contains(String name)
+    {
+        Part part = (Part)_partMap.get(name);
+        return (part!=null);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Get the data of a part as a string.
+     * @param name The part name 
+     * @return The part data
+     */
+    public String getString(String name)
+    {
+        List part = _partMap.getValues(name);
+        if (part==null)
+            return null;
+        if (_encoding != null)
+        {
+            try 
+            {
+                return new String(((Part)part.get(0))._data, _encoding);
+            } 
+            catch (UnsupportedEncodingException uee) 
+            {
+                //if (log.isDebugEnabled())log.debug("Invalid character set: " + uee);
+                return null;
+            }
+        }
+        else
+            return new String(((Part)part.get(0))._data);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** 
+     * @param name The part name 
+     * @return The parts data
+     */
+    public String[] getStrings(String name)
+    {
+        List parts = _partMap.getValues(name);
+        if (parts==null)
+            return null;
+        String[] strings = new String[parts.size()];
+        
+        if (_encoding == null) 
+        {
+            for (int i=0; i<strings.length; i++) 
+                strings[i] = new String(((Part)parts.get(i))._data);
+        } 
+        else 
+        {
+            try 
+            {
+                for (int i=0; i<strings.length; i++)
+                    strings[i] = new String(((Part)parts.get(i))._data, _encoding);
+            }
+            catch (UnsupportedEncodingException uee) 
+            {
+                //if (log.isDebugEnabled())log.debug("Invalid character set: " + uee);
+                return null;
+            }
+        }
+       
+        return strings;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Get the data of a part as a stream.
+     * @param name The part name 
+     * @return Stream providing the part data
+     */
+    public InputStream getInputStream(String name)
+    {
+        List part = (List)_partMap.getValues(name);
+        if (part==null)
+            return null;
+        return new ByteArrayInputStream(((Part)part.get(0))._data);
+    }
+
+    /* ------------------------------------------------------------ */
+    public InputStream[] getInputStreams(String name) 
+    {
+        List parts = (List)_partMap.getValues(name);
+        if (parts==null)
+            return null;
+        InputStream[] streams = new InputStream[parts.size()];
+        for (int i=0; i<streams.length; i++) {
+            streams[i] = new ByteArrayInputStream(((Part)parts.get(i))._data);
+        }
+        return streams;
+    }
+
+    /* ------------------------------------------------------------ */
+    /** Get the MIME parameters associated with a part.
+     * @param name The part name 
+     * @return Hashtable of parameters
+     */
+    public Hashtable getParams(String name)
+    {
+        List part = (List)_partMap.getValues(name);
+        if (part==null)
+            return null;
+        return ((Part)part.get(0))._headers;
+    }
+
+    /* ------------------------------------------------------------ */
+    public Hashtable[] getMultipleParams(String name) 
+    {
+        List parts = (List)_partMap.getValues(name);
+        if (parts==null)
+            return null;
+        Hashtable[] params = new Hashtable[parts.size()];
+        for (int i=0; i<params.length; i++) {
+            params[i] = ((Part)parts.get(i))._headers;
+        }
+        return params;
+    }
+
+    /* ------------------------------------------------------------ */
+    /** Get any file name associated with a part.
+     * @param name The part name 
+     * @return The filename
+     */
+    public String getFilename(String name)
+    {
+        List part = (List)_partMap.getValues(name);
+        if (part==null)
+            return null;
+        return ((Part)part.get(0))._filename;
+    }
+
+    /* ------------------------------------------------------------ */
+    public String[] getFilenames(String name) 
+    {
+        List parts = (List)_partMap.getValues(name);
+        if (parts==null)
+            return null;
+        String[] filenames = new String[parts.size()];
+        for (int i=0; i<filenames.length; i++) {
+            filenames[i] = ((Part)parts.get(i))._filename;
+        }
+        return filenames;
+    }
+
+    /* ------------------------------------------------------------ */
+    private void loadAllParts()
+        throws IOException
+    {
+        // Get first boundary
+        String line = _in.readLine();
+        if (!line.equals(_boundary))
+        {
+            //log.warn(line);
+            throw new IOException("Missing initial multi part boundary");
+        }
+        
+        // Read each part
+        while (!_lastPart)
+        {
+            // Read Part headers
+            Part part = new Part();
+            
+            String content_disposition=null;
+            while ((line=_in.readLine())!=null)
+            {
+                // If blank line, end of part headers
+                if (line.length()==0)
+                    break;
+
+                //if(log.isDebugEnabled())log.debug("LINE="+line);
+                
+                // place part header key and value in map
+                int c = line.indexOf(':',0);
+                if (c>0)
+                {
+                    String key = line.substring(0,c).trim().toLowerCase();
+                    String value = line.substring(c+1,line.length()).trim();
+                    String ev = (String) part._headers.get(key);
+                    part._headers.put(key,(ev!=null)?(ev+';'+value):value);
+                    //if(log.isDebugEnabled())log.debug(key+": "+value);
+                    if (key.equals("content-disposition"))
+                        content_disposition=value;
+                }
+            }
+
+            // Extract content-disposition
+            boolean form_data=false;
+            if (content_disposition==null)
+            {
+                throw new IOException("Missing content-disposition");
+            }
+            
+            StringTokenizer tok =
+                new StringTokenizer(content_disposition,";");
+            while (tok.hasMoreTokens())
+            {
+                String t = tok.nextToken().trim();
+                String tl = t.toLowerCase();
+                if (t.startsWith("form-data"))
+                    form_data=true;
+                else if (tl.startsWith("name="))
+                    part._name=value(t);
+                else if (tl.startsWith("filename="))
+                    part._filename=value(t);
+            }
+
+            // Check disposition
+            if (!form_data)
+            {
+                //log.warn("Non form-data part in multipart/form-data");
+                continue;
+            }
+            if (part._name==null || part._name.length()==0)
+            {
+                //log.warn("Part with no name in multipart/form-data");
+                continue;
+            }
+            //if(log.isDebugEnabled())log.debug("name="+part._name);
+            //if(log.isDebugEnabled())log.debug("filename="+part._filename);
+            _partMap.add(part._name,part);
+            part._data=readBytes();
+        }       
+    }
+
+    /* ------------------------------------------------------------ */
+    private byte[] readBytes()
+        throws IOException
+    {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        int c;
+        boolean cr=false;
+        boolean lf=false;
+        
+        // loop for all lines`
+        while (true)
+        {
+            int b=0;
+            while ((c=(_char!=-2)?_char:_in.read())!=-1)
+            {
+                _char=-2;
+
+                // look for CR and/or LF
+                if (c==13 || c==10)
+                {
+                    if (c==13) _char=_in.read();
+                    break;
+                }
+
+                // look for boundary
+                if (b>=0 && b<_byteBoundary.length && c==_byteBoundary[b])
+                    b++;
+                else
+                {
+                    // this is not a boundary
+                    if (cr) baos.write(13);
+                    if (lf) baos.write(10);
+                    cr=lf=false;
+                    
+                    if (b>0)
+                        baos.write(_byteBoundary,0,b);
+                    b=-1;
+                  
+                    baos.write(c);
+                }
+            }
+
+            // check partial boundary
+            if ((b>0 && b<_byteBoundary.length-2) ||
+                (b==_byteBoundary.length-1))
+            {
+                if (cr) baos.write(13);
+                if (lf) baos.write(10);
+                cr=lf=false;
+                baos.write(_byteBoundary,0,b);
+                b=-1;
+            }
+            
+            // boundary match
+            if (b>0 || c==-1)
+            {
+                if (b==_byteBoundary.length)
+                    _lastPart=true;
+                if (_char==10) _char=-2;
+                break;
+            }
+            
+            // handle CR LF
+            if (cr) baos.write(13);
+            if (lf) baos.write(10);
+            cr=(c==13);
+            lf=(c==10 || _char==10);
+            if (_char==10) _char=-2;  
+        }
+        //if(log.isTraceEnabled())log.trace(baos.toString());
+        return baos.toByteArray();
+    }
+    
+    
+    /* ------------------------------------------------------------ */
+    private String value(String nameEqualsValue)
+    {   
+        String value =
+            nameEqualsValue.substring(nameEqualsValue.indexOf('=')+1).trim();
+        
+        int i=value.indexOf(';');
+        if (i>0)
+            value=value.substring(0,i);
+        if (value.startsWith("\""))
+        {
+            value=value.substring(1,value.indexOf('"',1));
+        }
+        
+        else
+        {
+            i=value.indexOf(' ');
+            if (i>0)
+                value=value.substring(0,i);
+        }
+        return value;
+    }
+    
+    /* ------------------------------------------------------------ */
+    private class Part
+    {
+        String _name=null;
+        String _filename=null;
+        Hashtable _headers= new Hashtable(10);
+        byte[] _data=null;
+    }    
+};
diff --git a/apps/susimail/src/src/org/mortbay/util/ByteArrayPool.java b/apps/susimail/src/src/org/mortbay/util/ByteArrayPool.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d8a877c0f0354997df6405a52c77fe0a3c07289
--- /dev/null
+++ b/apps/susimail/src/src/org/mortbay/util/ByteArrayPool.java
@@ -0,0 +1,112 @@
+// ========================================================================
+// $Id: ByteArrayPool.java,v 1.9 2004/05/09 20:32:49 gregwilkins Exp $
+// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at 
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================================================================
+
+package org.mortbay.util;
+
+
+/* ------------------------------------------------------------ */
+/** Byte Array Pool
+ * Simple pool for recycling byte arrays of a fixed size.
+ *
+ * @version $Id: ByteArrayPool.java,v 1.9 2004/05/09 20:32:49 gregwilkins Exp $
+ * @author Greg Wilkins (gregw)
+ */
+public class ByteArrayPool
+{
+    public static final int __POOL_SIZE=
+        Integer.getInteger("org.mortbay.util.ByteArrayPool.pool_size",8).intValue();
+    
+    public static final ThreadLocal __pools=new BAThreadLocal();
+    public static int __slot;
+    
+    /* ------------------------------------------------------------ */
+    /** Get a byte array from the pool of known size.
+     * @param size Size of the byte array.
+     * @return Byte array of known size.
+     */
+    public static byte[] getByteArray(int size)
+    {
+        byte[][] pool = (byte[][])__pools.get();
+        boolean full=true;
+        for (int i=pool.length;i-->0;)
+        {
+            if (pool[i]!=null && pool[i].length==size)
+            {
+                byte[]b = pool[i];
+                pool[i]=null;
+                return b;
+            }
+            else
+                full=false;
+        }
+
+        if (full)
+            for (int i=pool.length;i-->0;)
+                pool[i]=null;
+        
+        return new byte[size];
+    }
+
+    /* ------------------------------------------------------------ */
+    public static byte[] getByteArrayAtLeast(int minSize)
+    {
+        byte[][] pool = (byte[][])__pools.get();
+        for (int i=pool.length;i-->0;)
+        {
+            if (pool[i]!=null && pool[i].length>=minSize)
+            {
+                byte[]b = pool[i];
+                pool[i]=null;
+                return b;
+            }
+        }
+        
+        return new byte[minSize];
+    }
+
+
+    /* ------------------------------------------------------------ */
+    public static void returnByteArray(final byte[] b)
+    {
+        if (b==null)
+            return;
+        
+        byte[][] pool = (byte[][])__pools.get();
+        for (int i=pool.length;i-->0;)
+        {
+            if (pool[i]==null)
+            {
+                pool[i]=b;
+                return;
+            }
+        }
+
+        // slot.
+        int s = __slot++;
+        if (s<0)s=-s;
+        pool[s%pool.length]=b;
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    /* ------------------------------------------------------------ */
+    private static final class BAThreadLocal extends ThreadLocal
+    {
+        protected Object initialValue()
+            {
+                return new byte[__POOL_SIZE][];
+            }
+    }
+}
diff --git a/apps/susimail/src/src/org/mortbay/util/LineInput.java b/apps/susimail/src/src/org/mortbay/util/LineInput.java
new file mode 100644
index 0000000000000000000000000000000000000000..e837cfba09e1c27b56e6fcc990a391ba1d94f047
--- /dev/null
+++ b/apps/susimail/src/src/org/mortbay/util/LineInput.java
@@ -0,0 +1,719 @@
+// ========================================================================
+// $Id: LineInput.java,v 1.17 2005/10/05 11:32:40 gregwilkins Exp $
+// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at 
+// http://www.apache.org/licenses/LICENSE-2.0
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================================================================
+
+package org.mortbay.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+
+//import org.apache.commons.logging.Log;
+//import org.mortbay.log.LogFactory;
+
+
+/* ------------------------------------------------------------ */
+/** Fast LineInput InputStream.
+ * This buffered InputStream provides methods for reading lines
+ * of bytes. The lines can be converted to String or character
+ * arrays either using the default encoding or a user supplied
+ * encoding.
+ *
+ * Buffering and data copying are highly optimized, making this
+ * an ideal class for protocols that mix character encoding lines
+ * with arbitrary byte data (eg HTTP).
+ *
+ * The buffer size is also the maximum line length in bytes and/or
+ * characters. If the byte length of a line is less than the max,
+ * but the character length is greater, than then trailing characters
+ * are lost.
+ *
+ * Line termination is forgiving and accepts CR, LF, CRLF or EOF.
+ * Line input uses the mark/reset mechanism, so any marks set
+ * prior to a readLine call are lost.
+ *
+ * @version $Id: LineInput.java,v 1.17 2005/10/05 11:32:40 gregwilkins Exp $
+ * @author Greg Wilkins (gregw)
+ */
+public class LineInput extends FilterInputStream                           
+{
+    //private static Log log = LogFactory.getLog(LineInput.class);
+
+    /* ------------------------------------------------------------ */
+    private byte _buf[];
+    private ByteBuffer _byteBuffer;
+    private InputStreamReader _reader;
+    private int _mark=-1;  // reset marker
+    private int _pos;      // Start marker
+    private int _avail;    // Available back marker, may be byte limited
+    private int _contents; // Absolute back marker of buffer
+    private int _byteLimit=-1;
+    private boolean _newByteLimit;
+    private LineBuffer _lineBuffer;
+    private String _encoding;
+    private boolean _eof=false;
+    private boolean _lastCr=false;
+    private boolean _seenCrLf=false;
+    
+    private final static int LF=10;
+    private final static int CR=13;
+
+    
+    /* ------------------------------------------------------------ */
+    /** Constructor.
+     * Default buffer and maximum line size is 2048.
+     * @param in The underlying input stream.
+     */
+    public LineInput(InputStream in)
+    {
+        this(in,0);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Constructor. 
+     * @param in The underlying input stream.
+     * @param bufferSize The buffer size and maximum line length.
+     */
+    public LineInput(InputStream in, int bufferSize)
+    {
+        super(in);
+        _mark=-1;
+        if (bufferSize==0)
+            bufferSize=8192;
+        _buf=ByteArrayPool.getByteArray(bufferSize);
+        _byteBuffer=new ByteBuffer(_buf);
+        _lineBuffer=new LineBuffer(bufferSize);
+        
+        try
+        {
+            _reader=new InputStreamReader(_byteBuffer,"UTF-8");
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            _reader=new InputStreamReader(_byteBuffer);
+        }
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Constructor. 
+     * @param in The underlying input stream.
+     * @param bufferSize The buffer size and maximum line length.
+     * @param encoding the character encoding to use for readLine methods.
+     * @exception UnsupportedEncodingException 
+     */
+    public LineInput(InputStream in, int bufferSize, String encoding)
+        throws UnsupportedEncodingException
+    {
+        super(in);
+        _mark=-1;
+        if (bufferSize==0)
+            bufferSize=2048;
+        _buf=ByteArrayPool.getByteArray(bufferSize);
+        _byteBuffer=new ByteBuffer(_buf);
+        _lineBuffer=new LineBuffer(bufferSize);
+        _reader=new InputStreamReader(_byteBuffer,encoding);
+        _encoding=encoding;
+    }
+    
+    /* ------------------------------------------------------------ */
+    public InputStream getInputStream()
+    {
+        return in;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Set the byte limit.
+     * If set, only this number of bytes are read before EOF.
+     * @param bytes Limit number of bytes, or -1 for no limit.
+     */
+    public void setByteLimit(int bytes)
+    {
+        _byteLimit=bytes;
+        
+        if (bytes>=0)
+        {
+            _newByteLimit=true;
+            _byteLimit-=_contents-_pos;
+            if (_byteLimit<0)
+            {
+                _avail+=_byteLimit;
+                _byteLimit=0;
+            }
+        }
+        else
+        {
+            _newByteLimit=false;
+            _avail=_contents;
+            _eof=false;
+        }
+    }
+    
+    
+    /* ------------------------------------------------------------ */
+    /** Get the byte limit.
+     * @return Number of bytes until EOF is returned or -1 for no limit.
+     */
+    public int getByteLimit()
+    {
+        if (_byteLimit<0)
+            return _byteLimit;
+        
+        return _byteLimit+_avail-_pos;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Read a line ended by CR, LF or CRLF.
+     * The default or supplied encoding is used to convert bytes to
+     * characters.
+     * @return The line as a String or null for EOF.
+     * @exception IOException 
+     */
+    public synchronized String readLine()
+        throws IOException
+    {
+        int len=fillLine(_buf.length);
+        
+        if (len<0)
+            return null;
+
+        String s=null;
+        if (_encoding==null)
+            s=new String(_buf,_mark,len);
+        else
+        {
+            try
+            {
+                s=new String(_buf,_mark,len,_encoding);
+            }
+            catch(UnsupportedEncodingException e)
+            {
+                //log.warn(LogSupport.EXCEPTION,e);
+            }
+        }
+        _mark=-1;
+
+        return s;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Read a line ended by CR, LF or CRLF.
+     * The default or supplied encoding is used to convert bytes to
+     * characters.
+     * @param c Character buffer to place the line into.
+     * @param off Offset into the buffer.
+     * @param len Maximum length of line.
+     * @return The length of the line or -1 for EOF.
+     * @exception IOException 
+     */
+    public int readLine(char[] c,int off,int len)
+        throws IOException
+    {
+        int blen=fillLine(len);
+
+        if (blen<0)
+            return -1;
+        if (blen==0)
+            return 0;
+        
+        _byteBuffer.setStream(_mark,blen);
+        
+        int read=0;
+        while(read<len && _reader.ready())
+        {
+            int r = _reader.read(c,off+read,len-read);
+            if (r<=0)
+                break;
+            read+=r;
+        }
+        
+        _mark=-1;
+
+        return read;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Read a line ended by CR, LF or CRLF.
+     * @param b Byte array to place the line into.
+     * @param off Offset into the buffer.
+     * @param len Maximum length of line.
+     * @return The length of the line or -1 for EOF.
+     * @exception IOException 
+     */
+    public int readLine(byte[] b,int off,int len)
+        throws IOException
+    {
+        len=fillLine(len);
+
+        if (len<0)
+            return -1;
+        if (len==0)
+            return 0;
+        
+        System.arraycopy(_buf,_mark, b, off, len);
+        _mark=-1;
+
+        return len;
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    /** Read a Line ended by CR, LF or CRLF.
+     * Read a line into a shared LineBuffer instance.  The LineBuffer is
+     * resused between calls and should not be held by the caller.
+     * The default or supplied encoding is used to convert bytes to
+     * characters.
+     * @return LineBuffer instance or null for EOF.
+     * @exception IOException 
+     */
+    public LineBuffer readLineBuffer()
+        throws IOException
+    {
+        return readLineBuffer(_buf.length);
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Read a Line ended by CR, LF or CRLF.
+     * Read a line into a shared LineBuffer instance.  The LineBuffer is
+     * resused between calls and should not be held by the caller.
+     * The default or supplied encoding is used to convert bytes to
+     * characters.
+     * @param len Maximum length of a line, or 0 for default
+     * @return LineBuffer instance or null for EOF.
+     * @exception IOException 
+     */
+    public LineBuffer readLineBuffer(int len)
+        throws IOException
+    {
+        len=fillLine(len>0?len:_buf.length);
+
+        if (len<0)
+            return null;
+        
+        if (len==0)
+        {
+            _lineBuffer.size=0;
+            return _lineBuffer;
+        }
+
+        _byteBuffer.setStream(_mark,len);
+        
+        _lineBuffer.size=0;
+        int read=0;
+        while(read<len && _reader.ready())
+        {
+            int r = _reader.read(_lineBuffer.buffer,
+                                 read,
+                                 len-read);
+            if (r<=0)
+                break;
+            read+=r;
+        }
+        _lineBuffer.size=read;
+        _mark=-1;
+
+        return _lineBuffer;
+    }
+    
+    /* ------------------------------------------------------------ */
+    public synchronized int read() throws IOException
+    {
+        int b;
+        if (_pos >=_avail)
+            fill();
+        if (_pos >=_avail)
+            b=-1;
+        else
+            b=_buf[_pos++]&255;
+        
+        return b;
+    }
+ 
+ 
+    /* ------------------------------------------------------------ */
+    public synchronized int read(byte b[], int off, int len) throws IOException
+    {
+        int avail=_avail-_pos;
+        if (avail <=0)
+        {
+            fill();
+            avail=_avail-_pos;
+        }
+
+        if (avail <=0)
+            len=-1;
+        else
+        {
+            len=(avail < len) ? avail : len;
+            System.arraycopy(_buf,_pos,b,off,len);
+            _pos +=len;
+        }
+        
+        return len;
+    }
+    
+    /* ------------------------------------------------------------ */
+    public long skip(long n) throws IOException
+    {
+        int avail=_avail-_pos;
+        if (avail <=0)
+        {
+            fill();
+            avail=_avail-_pos;
+        }
+
+        if (avail <=0)
+            n=0;
+        else
+        {
+            n=(avail < n) ? avail : n;
+            _pos +=n;
+        }
+        
+        return n;
+    }
+
+
+    /* ------------------------------------------------------------ */
+    public synchronized int available()
+        throws IOException
+    {
+        int in_stream=in.available();
+        if (_byteLimit>=0 && in_stream>_byteLimit)
+            in_stream=_byteLimit;
+        
+        return _avail - _pos + in_stream;
+    }
+
+    /* ------------------------------------------------------------ */
+    public synchronized void mark(int limit)
+        throws IllegalArgumentException
+    {
+        if (limit>_buf.length)
+        {
+            byte[] new_buf=new byte[limit];
+            System.arraycopy(_buf,_pos,new_buf,_pos,_avail-_pos);
+            _buf=new_buf;
+            if (_byteBuffer!=null)
+                _byteBuffer.setBuffer(_buf);
+        }
+        _mark=_pos;
+    }
+
+    /* ------------------------------------------------------------ */
+    public synchronized void reset()
+        throws IOException
+    {
+        if (_mark < 0)
+            throw new IOException("Resetting to invalid mark");
+        _pos=_mark;
+        _mark=-1;
+    }
+
+    /* ------------------------------------------------------------ */
+    public boolean markSupported()
+    {
+        return true;
+    }
+    
+    /* ------------------------------------------------------------ */
+    private void fill()
+        throws IOException
+    {
+        // if the mark is in the middle of the buffer
+        if (_mark > 0)
+        {
+            // moved saved bytes to start of buffer
+            int saved=_contents - _mark;
+            System.arraycopy(_buf, _mark, _buf, 0, saved);
+            _pos-=_mark;
+            _avail-=_mark;
+            _contents=saved;
+            _mark=0;
+        }
+        else if (_mark<0 && _pos>0)
+        {
+            // move remaining bytes to start of buffer
+            int saved=_contents-_pos;
+            System.arraycopy(_buf,_pos, _buf, 0, saved);
+            _avail-=_pos;
+            _contents=saved;
+            _pos=0;
+        }
+        else if (_mark==0 && _pos>0 && _contents==_buf.length)
+        {
+            // Discard the mark as we need the space.
+            _mark=-1;
+            fill();
+            return;
+        }
+
+        // Get ready to top up the buffer
+        int n=0;
+        _eof=false;
+
+        // Handle byte limited EOF
+        if (_byteLimit==0)
+            _eof=true;
+        // else loop until something is read.
+        else while (!_eof && n==0 && _buf.length>_contents)
+        {
+            // try to read as much as will fit.
+            int space=_buf.length-_contents;
+
+            n=in.read(_buf,_contents,space);
+
+            if (n<=0)
+            {
+                // If no bytes - we could be NBIO, so we want to avoid
+                // a busy loop.
+                if (n==0)
+                {
+                    // Yield to give a chance for some bytes to turn up
+                    Thread.yield();
+
+                    // Do a byte read as that is blocking
+                    int b = in.read();
+                    if (b>=0)
+                    {
+                        n=1;
+                        _buf[_contents++]=(byte)b;
+                    }
+                    else
+                        _eof=true;
+                }
+                else
+                    _eof=true;
+            }
+            else
+                _contents+=n;
+            _avail=_contents;
+
+            // If we have a byte limit
+            if (_byteLimit>0)
+            {
+                // adjust the bytes available
+                if (_contents-_pos >=_byteLimit)
+                    _avail=_byteLimit+_pos;
+                
+                if (n>_byteLimit)
+                    _byteLimit=0;
+                else if (n>=0)
+                    _byteLimit-=n;
+                else if (n==-1)
+                    throw new IOException("Premature EOF");
+            }
+        }
+        
+        // If we have some characters and the last read was a CR and
+        // the first char is a LF, skip it
+        if (_avail-_pos>0 && _lastCr && _buf[_pos]==LF)
+        {
+            _seenCrLf=true;
+            _pos++;
+            if (_mark>=0)
+                _mark++;
+            _lastCr=false;
+
+            // If the byte limit has just been imposed, dont count
+            // LF as content.
+            if(_byteLimit>=0 && _newByteLimit)
+            {
+                if (_avail<_contents)
+                    _avail++;
+                else
+                    _byteLimit++;
+            }
+            // If we ate all that ws filled, fill some more
+            if (_pos==_avail)
+                fill();
+        }
+        _newByteLimit=false;
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    private int fillLine(int maxLen)
+        throws IOException
+    {
+        _mark=_pos;
+        
+        if (_pos>=_avail)
+            fill();
+        if (_pos>=_avail)
+            return -1;
+        
+        byte b;  
+        boolean cr=_lastCr;
+        boolean lf=false;
+        _lastCr=false;
+        int len=0;
+        
+    LineLoop:
+        while (_pos<=_avail)
+        {
+            // if we have gone past the end of the buffer
+            while (_pos==_avail)
+            {
+                // If EOF or no more space in the buffer,
+                // return a line.
+                if (_eof || (_mark==0 && _contents==_buf.length))
+                {
+                    _lastCr=!_eof && _buf[_avail-1]==CR;
+                    
+                    cr=true;
+                    lf=true;
+                    break LineLoop;
+                }
+                
+                // If we have a CR and no more characters are available
+                if (cr && in.available()==0 && !_seenCrLf)
+                {
+                    _lastCr=true;
+                    cr=true;
+                    lf=true;
+                    break LineLoop;
+                }
+                else
+                {
+                    // Else just wait for more...
+                    _pos=_mark;
+                    fill();
+                    _pos=len;
+                    cr=false;
+                }
+            }
+
+            // Get the byte
+            b=_buf[_pos++];
+            
+            switch(b)
+            {
+              case LF:
+                  if (cr) _seenCrLf=true;
+                  lf=true;
+                  break LineLoop;
+                
+              case CR: 
+                  if (cr)
+                  {
+                      // Double CR
+                      if (_pos>1)
+                      {
+                          _pos--;
+                          break LineLoop;
+                      }
+                  }
+                  cr=true;
+                  break;
+                
+              default:
+                  if(cr)
+                  {
+                      if (_pos==1)
+                          cr=false;
+                      else
+                      {
+                          _pos--;
+                          break LineLoop;
+                      }
+                  }
+                  
+                  len++;
+                  if (len==maxLen)
+                  {
+                      // look for EOL
+                      if (_mark!=0 && _pos+2>=_avail && _avail<_buf.length)
+                          fill();
+                          
+                      if (_pos<_avail && _buf[_pos]==CR)
+                      {
+                          cr=true;
+                          _pos++;
+                      }
+                      if (_pos<_avail && _buf[_pos]==LF)
+                      {
+                          lf=true;
+                          _pos++;
+                      }
+                      
+                      if (!cr && !lf)
+                      {
+                          // fake EOL
+                          lf=true;
+                          cr=true;
+                      }
+                      break LineLoop;
+                  }
+                  
+                  break;
+            }
+        }
+        
+        if (!cr && !lf && len==0)
+            len=-1;
+        
+        return len;
+    }
+
+    /* ------------------------------------------------------------ */
+    private static class ByteBuffer extends ByteArrayInputStream
+    {
+        ByteBuffer(byte[] buffer)
+        {
+            super(buffer);
+        }
+        
+        void setBuffer(byte[] buffer)
+        {
+            buf=buffer;
+        }
+        
+        void setStream(int offset,int length)
+        {
+            pos=offset;
+            count=offset+length;
+            mark=-1;
+        }        
+    }
+    
+    /* ------------------------------------------------------------ */
+    /** Reusable LineBuffer.
+     * Externalized LineBuffer for fast line parsing.
+     */
+    public static class LineBuffer
+    {
+        public char[] buffer;
+        public int size;
+        public LineBuffer(int maxLineLength)
+        {buffer=new char[maxLineLength];}
+
+        public String toString(){return new String(buffer,0,size);}
+    }
+
+    /* ------------------------------------------------------------ */
+    public void destroy()
+    {
+        ByteArrayPool.returnByteArray(_buf);
+        _byteBuffer=null;
+        _reader=null;
+        _lineBuffer=null;
+        _encoding=null;
+    }
+
+    
+}
+
diff --git a/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java b/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java
index f32492a38975b3070f26d6c613cc5c09069fd816..75e5c18c8718955dd22ac74785ad3e4e149a9a27 100644
--- a/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java
+++ b/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java
@@ -77,6 +77,11 @@ public class UrlLauncher {
                 try {
                    test.close();
                 } catch (IOException ioe) {}
+                // Jetty 6 seems to start the Connector before the
+                // webapp is completely ready
+                try {
+                   Thread.sleep(2*1000);
+                } catch (InterruptedException ie) {}
                 return true;
             } catch (Exception e) {}
             if (System.currentTimeMillis() > done)
diff --git a/build.properties b/build.properties
index f3ead757658b05a21cdbe376cf30d28353927db9..a3fed3726433b28ea881d9b62563f785bec99f1a 100644
--- a/build.properties
+++ b/build.properties
@@ -10,7 +10,7 @@
 # Javadocs
 # Note: Include the trailing slash! Don't surround the URL in quotes!
 javasedocs.url=http://docs.oracle.com/javase/6/docs/api/
-jettydocs.url=http://docs.i2p2.de/jetty/javadoc/
+jettydocs.url=http://jetty.codehaus.org/jetty/jetty-6/apidocs/
 jrobindocs.url=http://docs.i2p-projekt.de/jrobin/javadoc/
 wrapperdocs.url=http://wrapper.tanukisoftware.com/jdoc/
 # these are only for unit test javadocs
diff --git a/build.xml b/build.xml
index 64157cf9d95ff1134a5ee12139b6e1a1989b56ae..b2621940a15bbea17987f117e922679a61987133 100644
--- a/build.xml
+++ b/build.xml
@@ -36,6 +36,7 @@
         <echo message="  updaterWithJavadoc: updater including the javadocs, for display in the console" />
         <echo message="  updater200WithJavadoc: updater including the javadocs, for display in the console (creates i2pupdate200.zip)" />
         <echo message="  updaterWithJetty: Updater including Jetty" />
+        <echo message="  updater200withJetty: Updater including Jetty" />
         <echo message="  updaterWithJettyFixes: updater including local jetty patches" />
         <echo message="  updaterWithGeoIP: updater including GeoIP Files" />
         <echo message="  updaterWithJettyFixesAndGeoIP" />
@@ -51,26 +52,28 @@
         <echo message="  javadoc-test: Javadocs for unit test classes (build/javadoc-test)" />
         <echo message="  slackpkg:  generate Slackware packages in ./Slackware/i2p and ./Slackware/i2p-base" />
         <echo message="  debianhowto: instructions on building Debian packages" />
-	<echo message="  debian: generate Debian packages in ../" />
-	<echo message="          run &quot;ant debianhowto&quot; for instructions" />
-	<echo message="  debian-clean: rollback debian specific patches and run the &quot;distclean&quot; target (done automatically at the end of the &quot;debian&quot; target)" />
-	<!-- <echo message="  debianrepo: build a Debian repository (reprepro required)" /> -->
+        <echo message="  debian: generate Debian packages in ../" />
+        <echo message="          run &quot;ant debianhowto&quot; for instructions" />
+        <echo message="  debian-clean: rollback debian specific patches and run the &quot;distclean&quot; target (done automatically at the end of the &quot;debian&quot; target)" />
+        <!-- <echo message="  debianrepo: build a Debian repository (reprepro required)" /> -->
         <echo message="  poupdate: update the .po files for translators" />
         <echo message="  pkg-portable-win32:  build a minimum portable version for win32" />
    </target>
     <target name="debianhowto">
-	    <echo message="To build debian packages, you must make sure that you have" />
-	    <echo message="the necessary build-dependencies installed." />
-	    <echo message="The packages required to build can be found in the file "/>
-	    <echo message="&quot;debian/control&quot; in both the Build-Depends and Build-Depends-Indep fields."/>
-	    <echo message="In addition to those packages, be sure to install &quot;fakeroot&quot;,"/>
-	    <echo message="&quot;quilt&quot; and &quot;build-essential&quot;!" />
-	    <echo message="" />
-	    <echo message="The following command will install all dependencies for you:" />
-	    <echo message="apt-get install debhelper ant debconf default-jdk gettext libgmp3-dev po-debconf fakeroot build-essential quilt" />
-	    <echo message=" " />
-	    <echo message="Once the dependencies are installed, run &quot;ant debian&quot;"/>
-	    <echo message="to patch the source and build the packages." />
+            <echo message="To build debian packages, you must make sure that you have" />
+            <echo message="the necessary build-dependencies installed." />
+            <echo message="The packages required to build can be found in the file "/>
+            <echo message="&quot;debian/control&quot; in the &quot;Build-Depends&quot; field."/>
+            <echo message="In addition to those packages, be sure to install &quot;fakeroot&quot;,"/>
+            <echo message="&quot;quilt&quot; and &quot;build-essential&quot;!" />
+            <echo message="" />
+            <echo message="The following command will install all of the dependencies for you:" />
+            <echo message=" " />
+            <echo message="apt-get install debhelper ant debconf default-jdk gettext libgmp3-dev po-debconf fakeroot build-essential \" />
+            <echo message="                   quilt libcommons-el-java libcommons-logging-java libjetty-extra-java libjetty-java" />
+            <echo message=" " />
+            <echo message="Once the dependencies are installed, run &quot;ant debian&quot;"/>
+            <echo message="to patch the source and build the packages." />
     </target>
     <target name="dist" depends="pkg, javadoc">
     </target>
@@ -133,7 +136,7 @@
         <ant dir="apps/routerconsole/java/" target="jar" />
     </target>
 
-    <target name="buildJetty" depends="buildProperties" >
+    <target name="buildJetty" depends="buildCore" >
         <ant dir="apps/jetty" target="build" />
     </target>
 
@@ -198,12 +201,9 @@
     <target name="buildWEB" depends="buildRouterConsole" >
         <copy file="apps/routerconsole/java/build/routerconsole.jar" todir="build/" />
         <copy file="apps/routerconsole/java/build/routerconsole.war" todir="build/" />
-        <copy file="apps/jetty/jettylib/org.mortbay.jetty.jar" todir="build/" />
-        <copy file="apps/jetty/jettylib/jasper-compiler.jar" todir="build/" />
-        <copy file="apps/jetty/jettylib/jasper-runtime.jar" todir="build/" />
-        <copy file="apps/jetty/jettylib/commons-logging.jar" todir="build/" />
-        <copy file="apps/jetty/jettylib/commons-el.jar" todir="build/" />
-        <copy file="apps/jetty/jettylib/javax.servlet.jar" todir="build/" />
+        <copy todir="build/" >
+            <fileset dir="apps/jetty/jettylib" excludes="ant.jar" />
+        </copy>
     </target>
 
     <target name="buildexe">
@@ -404,10 +404,11 @@
             <group title="Desktopgui Application" packages="net.i2p.desktopgui:net.i2p.desktopgui.*" />
             <group title="I2PSnark Application" packages="org.klomp.snark:org.klomp.snark.*" />
             <group title="I2PTunnel Application" packages="net.i2p.i2ptunnel:net.i2p.i2ptunnel.*" />
+            <group title="Jetty Logging" packages="net.i2p.jetty" />
             <group title="SAM Bridge" packages="net.i2p.sam" />
             <group title="SAM Demos" packages="net.i2p.sam.client" />
             <group title="SusiDNS Application" packages="i2p.susi.dns" />
-            <group title="SusiMail Application" packages="i2p.susi.webmail:i2p.susi.webmail.*:i2p.susi.debug:i2p.susi.util" />
+            <group title="SusiMail Application" packages="i2p.susi.webmail:i2p.susi.webmail.*:i2p.susi.debug:i2p.susi.util:org.mortbay.servlet:org.mortbay.util" />
             <group title="Systray Application" packages="net.i2p.apps.systray" />
             <sourcepath>
                 <pathelement location="core/java/src" />
@@ -426,10 +427,16 @@
                 <pathelement location="apps/BOB/Demos/echo/echoserver/src" />
                 <pathelement location="apps/susidns/src/java/src" />
                 <pathelement location="apps/susimail/src/src" />
+                <pathelement location="apps/jetty/java/src" />
             </sourcepath>
             <classpath>
                 <pathelement location="apps/jetty/jettylib/org.mortbay.jetty.jar" />
                 <pathelement location="apps/jetty/jettylib/javax.servlet.jar" />
+                <pathelement location="apps/jetty/jettylib/jetty-sslengine.jar" />
+                <pathelement location="apps/jetty/jettylib/jetty-start.jar" />
+                <pathelement location="apps/jetty/jettylib/jetty-java5-threadpool.jar" />
+                <pathelement location="apps/jetty/jettylib/jetty-util.jar" />
+                <pathelement location="apps/jetty/jettylib/jsp-api.jar" />
                 <pathelement location="apps/systray/java/lib/systray4j.jar" />
                 <pathelement location="apps/jrobin/jrobin-1.5.9.1.jar" />
                 <pathelement location="installer/lib/wrapper/all/wrapper.jar" />
@@ -635,6 +642,15 @@
 	<defaultexcludes default="true"/>
     </target>
 
+    <target name="webappDistclean">
+        <ant dir="apps/i2ptunnel/java/" target="distclean" />
+        <ant dir="apps/routerconsole/java/" target="distclean" />
+        <ant dir="apps/addressbook/" target="distclean" />
+        <ant dir="apps/susimail/" target="distclean" />
+        <ant dir="apps/susidns/src/" target="distclean" />
+        <ant dir="apps/i2psnark/java/" target="distclean" />
+    </target>
+
     <target name="pkg" depends="distclean, updater, preppkg, installer" />
 
     <target name="pkgclean" depends="deletepkg-temp">
@@ -763,14 +779,12 @@
         </delete>
         <copy file="build/i2p.jar" todir="pkg-temp/lib/" />
         <copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
-        <copy file="build/jasper-compiler.jar" todir="pkg-temp/lib/" />
-        <copy file="build/jasper-runtime.jar" todir="pkg-temp/lib/" />
-        <copy file="build/commons-logging.jar" todir="pkg-temp/lib/" />
-        <copy file="build/commons-el.jar" todir="pkg-temp/lib/" />
-        <copy file="build/javax.servlet.jar" todir="pkg-temp/lib/" />
+        <!-- all jetty stuff -->
+        <copy todir="pkg-temp/lib" >
+            <fileset dir="build" includes="commons*.jar jasper*.jar javax*.jar jetty*.jar jsp*.jar org.mortbay.*.jar" />
+        </copy>
         <copy file="build/mstreaming.jar" todir="pkg-temp/lib/" />
         <copy file="build/streaming.jar" todir="pkg-temp/lib/" />
-        <copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" />
         <copy file="build/router.jar" todir="pkg-temp/lib/" />
         <copy file="build/desktopgui.jar" todir="pkg-temp/lib/" />
         <copy file="build/routerconsole.jar" todir="pkg-temp/lib/" />
@@ -817,20 +831,13 @@
         <copy file="installer/resources/uninstall.ico" todir="pkg-temp/docs/" />
         <!-- Eepsite stuff here -->
         <mkdir dir="pkg-temp/eepsite" />
-        <mkdir dir="pkg-temp/eepsite/webapps" />
-        <mkdir dir="pkg-temp/eepsite/logs" />
-        <mkdir dir="pkg-temp/eepsite/cgi-bin" />
-        <mkdir dir="pkg-temp/eepsite/docroot" />
-        <mkdir dir="pkg-temp/eepsite/docroot/help" />
-        <mkdir dir="pkg-temp/eepsite/docroot/help/lib" />
-        <copy todir="pkg-temp/eepsite/docroot/" >
-            <fileset dir="installer/resources/eepsite.help/" />
+        <copy todir="pkg-temp/eepsite/" >
+            <fileset dir="installer/resources/eepsite/" />
         </copy>
         <copy todir="pkg-temp/eepsite/docroot/help/lib/" >
             <fileset dir="installer/resources/icons/flags/" includes="cn.png de.png es.png fr.png ir.png it.png jp.png nl.png ru.png se.png us.png" />
         </copy>
         <copy file="installer/resources/themes/console/images/favicon.ico" tofile="pkg-temp/eepsite/docroot/favicon.ico" />
-        <copy file="installer/resources/jetty.xml" tofile="pkg-temp/eepsite/jetty.xml" />
     </target>
 
     <target name="preplicenses">
@@ -844,6 +851,7 @@
               So we include the MIT one in our binary package
          -->
         <copy file="installer/lib/launch4j/head/LICENSE.txt" tofile="pkg-temp/licenses/LICENSE-Launch4j.txt" />
+        <copy file="apps/jetty/apache-tomcat-deployer/NOTICE" tofile="pkg-temp/licenses/NOTICE-Tomcat.txt" />
         <!--  Not sure if these are used or should be included -->
         <copy file="installer/lib/launch4j/lib/foxtrot.LICENSE.txt" tofile="pkg-temp/licenses/LICENSE-Foxtrot.txt" />
         <copy file="installer/lib/launch4j/lib/JGoodies.Forms.LICENSE.txt" tofile="pkg-temp/licenses/LICENSE-JGoodies-Forms.txt" />
@@ -912,6 +920,7 @@
     <target name="updaterWithGeoIP" depends="prepupdate, prepgeoupdate, preplicenses, zipit" />
     <target name="updaterWithJetty" depends="prepjupdate, preplicenses, zipit" />
     <target name="updaterWithJettyRepack" depends="prepjupdate, preplicenses, repack200, zipit" />
+    <target name="updater200WithJetty" depends="prepjupdate, preplicenses, pack200, zipit200" />
     <target name="updaterWithJettyFixes" depends="prepjupdatefixes, preplicenses, zipit" />
     <target name="updaterWithJettyFixesAndJbigi" depends="prepjupdatefixes, prepjbigiupdate, preplicenses, zipit" />
     <target name="updaterWithJettyFixesAndGeoIP" depends="prepjupdatefixes, prepgeoupdate, preplicenses, zipit" />
@@ -1051,16 +1060,26 @@
         </copy>
     </target>
 
+    <!-- All jetty jars required for update.
+         We don't need commons-el or commons-logging, they haven't changed.
+         TODO do we need to bother updating jasper?
+         TODO where is JMX? We don't need it I hope.
+      -->
     <target name="prepjupdate" depends="prepupdate, buildWEB">
-        <copy file="build/jasper-compiler.jar" todir="pkg-temp/lib/" />
-        <copy file="build/jasper-runtime.jar" todir="pkg-temp/lib/" />
-        <copy file="build/commons-logging.jar" todir="pkg-temp/lib/" />
-        <copy file="build/commons-el.jar" todir="pkg-temp/lib/" />
-        <copy file="build/javax.servlet.jar" todir="pkg-temp/lib/" />
-        <copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" />
+        <copy todir="pkg-temp/lib" >
+            <fileset dir="build" includes="commons*.jar jasper*.jar javax*.jar jetty*.jar jsp*.jar org.mortbay.*.jar" />
+        </copy>
+        <!--  We have to package the new eepsite files for MigrateJetty.java, but we
+              can't overwrite an existing eepsite dir in a non-split configuration.
+          -->
+        <copy todir="pkg-temp/eepsite-jetty6" >
+            <fileset dir="installer/resources/eepsite" includes="*.xml contexts/* etc/*" />
+        </copy>
     </target>
+
+    <!-- Jetty 6 I2P logging addons, not really fixes -->
     <target name="prepjupdatefixes" depends="prepupdate, buildWEB">
-        <copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" />
+        <copy file="build/jetty-i2p.jar" todir="pkg-temp/lib/" />
     </target>
 
     <target name="util-list-changes" depends="checkForMtn" if="mtn.available" >
@@ -1492,33 +1511,33 @@
 
     <target name="debian-binary" >
         <echo message="Did you update the version using dch -i?" />
-	<echo message=" " />
-	<echo message="If the changelog was not updated with dch -i, press" />
-	<echo message="press CTRL+C to abort building this Debian package." />
-	<echo message="" />
-	<echo message="Pausing build for ten seconds to give enough time to read this notice." />
-	<exec executable="sleep" failonerror="true">
-		<arg value="10" />
-	</exec>
+        <echo message=" " />
+        <echo message="If the changelog was not updated with dch -i, press" />
+        <echo message="press CTRL+C to abort building this Debian package." />
+        <echo message="" />
+        <echo message="Pausing build for ten seconds to give enough time to read this notice." />
+        <exec executable="sleep" failonerror="true">
+                <arg value="10" />
+        </exec>
         <echo message="====================" />
-        <!-- bundle the jetty 5 lib since there isn't a deb for it -->
-        <ant dir="apps/jetty" target="ensureJettylib" />
-	
-	<exec executable="fakeroot" failonerror="true">
-	    <arg value="debian/rules" />
-	    <arg value="patch" />
-	    <arg value="binary" />
-	    <arg value="clean" />
+
+        <exec executable="fakeroot" failonerror="true">
+            <arg value="debian/rules" />
+            <arg value="patch" />
+            <arg value="binary" />
+            <arg value="clean" />
         </exec>
-	<delete dir=".pc" />
+        <delete dir=".pc" />
     </target>
+
     <target name="debian-clean" depends="buildProperties" >
         <exec executable="fakeroot" failonerror="true">
-	    <arg value="debian/rules" />
-	    <arg value="clean" />
+            <arg value="debian/rules" />
+            <arg value="clean" />
         </exec>
-	<delete dir="./.pc" />
+        <delete dir="./.pc" />
     </target>
+
     <target name="debian-patch" depends="buildProperties" >
         <exec executable="quilt" failonerror="true">
             <arg value="-a" />
@@ -1528,8 +1547,8 @@
     </target>
     <target name="debian-unpatch" depends="buildProperties">
         <exec executable="quilt" failonerror="false">
-	    <arg value="-a" />
-	    <arg value="pop" />
+            <arg value="-a" />
+            <arg value="pop" />
         </exec>
     </target>
 
diff --git a/debian/control b/debian/control
index 31a4641f6c103dec694e9d65424447ab081bb162..9c2528c48749c8c2911cf4f2545f30083a468d33 100644
--- a/debian/control
+++ b/debian/control
@@ -10,9 +10,12 @@ Build-Depends: debhelper (>= 7.0.50~),
  debconf,
  default-jdk,
  gettext,
+ libcommons-el-java,
+ libcommons-logging-java,
  libgmp3-dev,
+ libjetty-extra-java,
+ libjetty-java,
  po-debconf
-##Build-Depends-Indep: tor-geoipdb
 
 Package: i2p
 Architecture: all
@@ -65,7 +68,11 @@ Package: i2p-router
 Architecture: all
 Section: net
 Priority: optional
-Depends: ${misc:Depends}, ${java:Depends}, ${shlibs:Depends}, default-jre-headless | java5-runtime-headless | java6-runtime-headless
+Depends: ${misc:Depends}, ${java:Depends}, ${shlibs:Depends},
+ default-jre-headless | java5-runtime-headless | java6-runtime-headless,
+ libcommons-logging-java,
+ libjetty-java,
+ libtomcat6-java
 Replaces: i2p ( << 0.8.6-5)
 Breaks: i2p (<< 0.8.6-5)
 Recommends: libjbigi-jni (>= ${source:Version}), libjbigi-jni (<< ${source:Version}.1~), ttf-dejavu
diff --git a/debian/i2p-router.install b/debian/i2p-router.install
index 4205beba3f0b50f7590044784e243d851677e178..aa9d9703eeb53d776f854e94f1bd0114cfb90b48 100644
--- a/debian/i2p-router.install
+++ b/debian/i2p-router.install
@@ -1,4 +1,8 @@
+# history.txt is installed to /usr/share/i2p because
+# it's shown in the router console at http://127.0.0.1:7657
+# (this is also why I don't use dh_installchangelogs -k for it)
 history.txt usr/share/i2p
+
 pkg-temp/blocklist.txt usr/share/i2p
 pkg-temp/certificates usr/share/i2p
 pkg-temp/clients.config usr/share/i2p
@@ -10,7 +14,31 @@ pkg-temp/hosts.txt usr/share/i2p
 pkg-temp/i2prouter-nowrapper usr/bin
 pkg-temp/i2psnark.config usr/share/i2p
 pkg-temp/i2ptunnel.config usr/share/i2p
-pkg-temp/lib/*.jar usr/share/i2p/lib
 pkg-temp/router.config usr/share/i2p
 pkg-temp/systray.config usr/share/i2p
 pkg-temp/webapps usr/share/i2p
+
+# We'll selectively copy things from pkg-temp
+# to ensure that potential Jetty jars aren't
+# duplicated
+pkg-temp/lib/BOB.jar usr/share/i2p/lib
+pkg-temp/lib/desktopgui.jar usr/share/i2p/lib
+pkg-temp/lib/i2p.jar usr/share/i2p/lib
+pkg-temp/lib/i2psnark.jar usr/share/i2p/lib
+pkg-temp/lib/i2ptunnel.jar usr/share/i2p/lib
+pkg-temp/lib/jetty-i2p.jar usr/share/i2p/lib
+pkg-temp/lib/jrobin.jar usr/share/i2p/lib
+pkg-temp/lib/mstreaming.jar usr/share/i2p/lib
+pkg-temp/lib/router.jar usr/share/i2p/lib
+pkg-temp/lib/routerconsole.jar usr/share/i2p/lib
+pkg-temp/lib/sam.jar usr/share/i2p/lib
+pkg-temp/lib/standard.jar usr/share/i2p/lib
+pkg-temp/lib/streaming.jar usr/share/i2p/lib
+pkg-temp/lib/systray.jar usr/share/i2p/lib
+pkg-temp/lib/systray4j.jar usr/share/i2p/lib
+
+# These are copied over to avoid depending on libjetty-extra-java
+# and pulling in dependencies that we don't care about
+pkg-temp/lib/commons-el.jar usr/share/i2p/lib
+pkg-temp/lib/jetty-java5-threadpool.jar usr/share/i2p/lib
+pkg-temp/lib/jetty-rewrite-handler.jar usr/share/i2p/lib
diff --git a/debian/i2p-router.links b/debian/i2p-router.links
index 9c79676e9b4f4fb67f9d555d34c1b6ae0546402e..a4f0cf368d2c672c3fc1895a21607d4fa5dfbfde 100644
--- a/debian/i2p-router.links
+++ b/debian/i2p-router.links
@@ -2,3 +2,21 @@ usr/share/common-licenses/GPL-2 usr/share/doc/i2p-router/licenses/LICENSE-GPLv2.
 usr/share/common-licenses/LGPL-2.1 usr/share/doc/i2p-router/licenses/LICENSE-LGPLv2.1.txt
 usr/share/common-licenses/Apache-2.0 usr/share/doc/i2p-router/licenses/LICENSE-Apache2.0.txt
 usr/share/common-licenses/BSD usr/share/doc/i2p-router/licenses/LICENSE-BSD.txt
+
+# From libcommons-logging-java
+usr/share/java/commons-logging.jar usr/share/i2p/lib/commons-logging.jar
+# From libtomcat6-java
+usr/share/java/jasper.jar usr/share/i2p/lib/jasper.jar
+usr/share/java/jasper-el.jar usr/share/i2p/lib/jasper-el.jar
+usr/share/java/tomcat-juli.jar usr/share/i2p/lib/tomcat-juli.jar
+
+# From libjetty-java
+usr/share/java/jetty.jar usr/share/i2p/lib/jetty.jar
+usr/share/java/jetty-util.jar usr/share/i2p/lib/jetty-util.jar
+usr/share/java/jetty-sslengine.jar usr/share/i2p/lib/jetty-sslengine.jar
+usr/share/java/jetty-start.jar usr/share/i2p/lib/jetty-start.jar
+
+# From libservlet2.5-java
+usr/share/java/servlet-api-2.5.jar usr/share/i2p/lib/servlet-api.jar
+usr/share/java/jsp-api-2.1.jar usr/share/i2p/lib/jsp-api.jar
+usr/share/java/el-api-2.1.jar usr/share/i2p/lib/el-api.jar
diff --git a/debian/patches/0004-jetty6.patch b/debian/patches/0004-jetty6.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c245d75df1fe97ca1629ce49f5704f61ba00ae46
--- /dev/null
+++ b/debian/patches/0004-jetty6.patch
@@ -0,0 +1,268 @@
+From: Kill Your TV <killyourtv@i2pmail.org>
+Date: Sun, 1 Jan 2011 22:30:32 +0000
+Subject: Jetty 6
+
+This patch updates 
+
+	apps/i2ptunnel/java/build.xml
+	apps/jetty/build.xml
+	apps/routerconsole/java/build.xml
+	apps/susidns/src/build.xml
+
+so that I2P can be built using Jetty packages from Debian/Ubuntu
+--- a/apps/jetty/build.xml
++++ b/apps/jetty/build.xml
+@@ -2,76 +2,18 @@
+ <project basedir="." default="all" name="jetty">
+ 
+     <property name="jetty.ver" value="6.1.26" />
+-    <property name="jetty.base" value="jetty-${jetty.ver}" />
+-    <property name="jetty.sha1" value="9485913f1a1945a849a90f1a34853d22350bc524" />
+-    <property name="jetty.filename" value="${jetty.base}.zip" />
+-    <property name="jetty.url" value="http://dist.codehaus.org/jetty/${jetty.base}/${jetty.filename}" />
+-    <property name="verified.filename" value="verified.txt" />
+     <property name="javac.compilerargs" value="" />
+ 
+     <target name="all" depends="build" />
+-
+     <target name="ensureJettylib" >
+-        <available property="jetty.zip.available" file="${jetty.filename}" type="file" />
+-        <available property="jetty.zip.extracted" file="jettylib" type="dir" />
+         <ant target="fetchJettylib" />
+         <ant target="verifyJettylib" />
+         <ant target="extractJettylib" />
+     </target>
+ 
+-    <target name="fetchJettylib" unless="jetty.zip.available" >
+-        <echo message="It seems that you don't have '${jetty.filename}' deployed." />
+-        <echo message="The build script can download this file for you automatically," />
+-        <echo message="or alternatively you can obtain it manually from:" />
+-        <echo message="${jetty.url}" />
+-        <echo message="" />
+-        <echo message="The libraries contained in the fetched file provide the Jetty web server" />
+-        <echo message="(http://jetty.mortbay.org/). They are not absolutely necessary" />
+-        <echo message="but strongly recommended, since they are used by some applications" />
+-        <echo message="on top of I2P, like the router console." />
+-        <echo message="" />
+-        <echo message="Even if you deploy the Jetty archive manually into directory apps/jetty/," />
+-        <echo message="the build script will still attempt to verify its checksums, which must be:" />
+-        <echo message="SHA1 ${jetty.sha1}" />
+-        <echo message="" />
+-        <input message="Download Jetty archive automatically?" validargs="y,n" addproperty="jetty.download" />
+-        <fail message="Aborting as requested. Please deploy the Jetty archive manually." >
+-            <condition>
+-                <equals arg1="${jetty.download}" arg2="n"/>
+-            </condition>
+-        </fail>
+-        <get src="${jetty.url}" verbose="true" dest="${jetty.filename}" />
+-    </target>
+-
+-    <condition property="verified.already" >
+-        <and>
+-            <available file="${jetty.filename}" />
+-            <uptodate property="foo.bar.baz" srcfile="${jetty.filename}" targetfile="${verified.filename}" />
+-        </and>
+-    </condition>
+-
+-    <target name="verifyJettylib" unless="verified.already" >
+-        <condition property="jetty.zip.verified" >
+-                <checksum file="${jetty.filename}" algorithm="SHA" property="${jetty.sha1}" />
+-        </condition>
+-        <fail message="Jetty archive does not match its checksum!" >
+-            <condition>
+-                <not>
+-                    <istrue value="${jetty.zip.verified}" />
+-                </not>
+-            </condition>
+-        </fail>
+-        <touch file="${verified.filename}" />
+-    </target>
+-
+-    <target name="extractJettylib" unless="jetty.zip.extracted" >
+-      <!-- for .tgz -->
+-      <!--
+-        <gunzip src="${jetty.filename}" dest="jetty.tar" />
+-        <untar src="jetty.tar" dest="." />
+-      -->
+-      <!-- for .zip -->
+-        <unzip src="${jetty.filename}" dest="." />
++    <target name="verifyJettylib" />
++    <target name="fetchJettylib" />
++    <target name="extractJettylib">
+         <mkdir dir="jettylib" />
+       <!-- We copy everything to names without the version numbers so we
+            can update them later. Where there was something similar in Jetty 5,
+@@ -86,30 +28,27 @@
+               jetty-rewrite-handler: Not used by I2P, but only 20KB and could be useful for eepsites
+               All of these are available in the Ubuntu packages libjetty-java and libjetty-extra-java
+         -->
+-        <copy preservelastmodified="true" file="${jetty.base}/start.jar" tofile="jettylib/jetty-start.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/${jetty.base}.jar" tofile="jettylib/org.mortbay.jetty.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/jetty-util-${jetty.ver}.jar" tofile="jettylib/jetty-util.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-java5-threadpool-${jetty.ver}.jar" tofile="jettylib/jetty-java5-threadpool.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-rewrite-handler-${jetty.ver}.jar" tofile="jettylib/jetty-rewrite-handler.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/ext/jetty-sslengine-${jetty.ver}.jar" tofile="jettylib/jetty-sslengine.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/jsp-2.0/ant-1.6.5.jar" tofile="jettylib/ant.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/jsp-2.0/commons-el-1.0.jar" tofile="jettylib/commons-el.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/jsp-2.0/jasper-compiler-5.5.15.jar" tofile="jettylib/jasper-compiler.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/jsp-2.0/jasper-runtime-5.5.15.jar" tofile="jettylib/jasper-runtime.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/jsp-2.0/jsp-api-2.0.jar" tofile="jettylib/jsp-api.jar" />
+-        <copy preservelastmodified="true" file="${jetty.base}/lib/servlet-api-2.5-20081211.jar" tofile="jettylib/javax.servlet.jar" />
+-        <delete file="jetty.tar" />
+-        <delete dir="${jetty.base}" />
+-        <!-- commons-logging.jar not in Jetty 6 but we have it in launch4j so copy it over, we need it
+-             for org.apache.jasper.JspC compiler
+-          -->
+-        <copy preservelastmodified="true" file="../../installer/lib/launch4j/lib/commons-logging.jar" todir="jettylib/" />
++        <copy preservelastmodified="true" file="/usr/share/java/commons-el-1.0.jar" tofile="jettylib/commons-el.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/commons-logging.jar" todir="jettylib/" />
++        <copy preservelastmodified="true" file="/usr/share/java/el-api-2.1.jar" tofile="jettylib/el-api.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/jasper-el.jar" todir="jettylib/" />
++        <copy preservelastmodified="true" file="/usr/share/java/jetty-java5-threadpool.jar" tofile="jettylib/jetty-java5-threadpool.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/jetty-rewrite-handler.jar" tofile="jettylib/jetty-rewrite-handler.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/jetty-sslengine.jar" tofile="jettylib/jetty-sslengine.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/jetty-start.jar" tofile="jettylib/jetty-start.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/jetty-util.jar" tofile="jettylib/jetty-util.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/jetty.jar" tofile="jettylib/org.mortbay.jetty.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/servlet-api.jar" tofile="jettylib/javax.servlet.jar" />
++        <copy preservelastmodified="true" file="/usr/share/java/tomcat-juli.jar" tofile="jettylib/tomcat-juli.jar" />
++        <copy preservelastmodified="true" file="/usr/share/jetty/lib/jsp-2.1/ant.jar" tofile="jettylib/ant.jar" />
++        <copy preservelastmodified="true" file="/usr/share/jetty/lib/jsp-2.1/jasper.jar" tofile="jettylib/jasper.jar" />
++        <copy preservelastmodified="true" file="/usr/share/jetty/lib/jsp-2.1/jsp-api.jar" tofile="jettylib/jsp-api.jar" />
+     </target>
+ 
+     <target name="build" depends="jar" />
+ 
+     <target name="builddep" />
+-    <target name="compile" depends="builddep, ensureJettylib" >
++    <target name="compile" depends="builddep, extractJettylib" >
+         <mkdir dir="./build" />
+         <mkdir dir="./build/obj" />
+         <javac 
+@@ -173,7 +112,6 @@
+     <target name="cleandep" depends="clean" />
+     <target name="distclean" depends="clean">
+         <delete dir="./jettylib" />
+-        <echo message="Not actually deleting the jetty libs (since they're so large)" />
+     </target>
+     <target name="reallyclean" depends="distclean">
+     </target>
+@@ -181,22 +119,10 @@
+         <delete dir="./jettylib" />
+         <delete file="${jetty.filename}" />
+     </target>
+-    <target name="javadoc" >
+-        <available property="jetty.zip.available" file="${jetty.filename}" type="file" />
+-        <available property="jetty.zip.javadocExtracted" file="build/javadoc" type="dir" />
+-        <ant target="fetchJettylib" />
+-        <ant target="verifyJettylib" />
+-        <ant target="extractJavadoc" />
+-    </target>
+-    <target name="extractJavadoc" unless="jetty.zip.javadocExtracted" >
+-        <mkdir dir="./build" />
+-        <mkdir dir="./build/javadoc" />
+-        <unzip src="${jetty.filename}" dest="./build/javadoc" >
+-            <patternset>
+-                <include name="${jetty.base}/javadoc/" />
+-            </patternset>
+-            <mapper type="glob" from="${jetty.base}/javadoc/*" to="javadoc/*" />
+-        </unzip>
++    <target name="javadoc">
++        <echo message="Javadocs are available in the package &quot;libjetty-java-doc&quot;" />
+     </target>
+ 
++    <target name="extractJavadoc" />
++
+ </project>
+--- a/apps/i2ptunnel/java/build.xml
++++ b/apps/i2ptunnel/java/build.xml
+@@ -164,13 +164,15 @@
+         <!-- there are various jspc ant tasks, but they all seem a bit flakey -->
+         <java classname="org.apache.jasper.JspC" fork="true" failonerror="true">
+             <classpath>
+-                <pathelement location="../../jetty/jettylib/jasper-compiler.jar" />
+-                <pathelement location="../../jetty/jettylib/jasper-runtime.jar" />
+-                <pathelement location="../../jetty/jettylib/javax.servlet.jar" />
+-                <pathelement location="../../jetty/jettylib/commons-logging.jar" />
++                <pathelement location="../../jetty/jettylib/ant.jar" />
+                 <pathelement location="../../jetty/jettylib/commons-el.jar" />
++                <pathelement location="../../jetty/jettylib/commons-logging.jar" />
++                <pathelement location="../../jetty/jettylib/el-api.jar" />
++                <pathelement location="../../jetty/jettylib/jasper-el.jar" />
++                <pathelement location="../../jetty/jettylib/jasper.jar" />
++                <pathelement location="../../jetty/jettylib/javax.servlet.jar" />
+                 <pathelement location="../../jetty/jettylib/jsp-api.jar" />
+-                <pathelement location="../../jetty/jettylib/ant.jar" />
++                <pathelement location="../../jetty/jettylib/tomcat-juli.jar" />
+                 <pathelement location="build/i2ptunnel.jar" />
+             </classpath>
+             <arg value="-d" />
+@@ -187,10 +189,12 @@
+                destdir="../jsp/WEB-INF/classes/" srcdir="../jsp/WEB-INF/classes" includes="**/*.java">
+             <compilerarg line="${javac.compilerargs}" />
+             <classpath>
+-                <pathelement location="../../jetty/jettylib/jasper-runtime.jar" />
+-                <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/commons-logging.jar" />
++                <pathelement location="../../jetty/jettylib/el-api.jar" />
++                <pathelement location="../../jetty/jettylib/jasper-el.jar" />
++                <pathelement location="../../jetty/jettylib/jasper.jar" />
++                <pathelement location="../../jetty/jettylib/javax.servlet.jar" />
+                 <pathelement location="../../jetty/jettylib/jsp-api.jar" />
+                 <pathelement location="build/i2ptunnel.jar" />
+             </classpath>
+--- a/apps/routerconsole/java/build.xml
++++ b/apps/routerconsole/java/build.xml
+@@ -238,8 +238,10 @@
+         -->
+         <java classname="org.apache.jasper.JspC" fork="true" failonerror="true">
+             <classpath>
+-                <pathelement location="../../jetty/jettylib/jasper-compiler.jar" />
+-                <pathelement location="../../jetty/jettylib/jasper-runtime.jar" />
++                <pathelement location="../../jetty/jettylib/jasper.jar" />
++                <pathelement location="../../jetty/jettylib/tomcat-juli.jar" />
++                <pathelement location="../../jetty/jettylib/el-api.jar" />
++                <pathelement location="../../jetty/jettylib/jasper-el.jar" />
+                 <pathelement location="../../jetty/jettylib/javax.servlet.jar" />
+                 <pathelement location="../../jetty/jettylib/commons-logging.jar" />
+                 <pathelement location="../../jetty/jettylib/commons-el.jar" />
+@@ -273,7 +275,10 @@
+                srcdir="../jsp/WEB-INF/classes" includes="**/*.java">
+             <compilerarg line="${javac.compilerargs}" />
+             <classpath>
+-                <pathelement location="../../jetty/jettylib/jasper-runtime.jar" />
++                <pathelement location="../../jetty/jettylib/jasper.jar" />
++                <pathelement location="../../jetty/jettylib/el-api.jar" />
++                <pathelement location="../../jetty/jettylib/jasper-el.jar" />
++                <pathelement location="../../jetty/jettylib/tomcat-juli.jar" />
+                 <pathelement location="../../jetty/jettylib/javax.servlet.jar" />
+                 <pathelement location="../../jetty/jettylib/commons-logging.jar" />
+                 <pathelement location="../../jetty/jettylib/commons-el.jar" />
+--- a/apps/susidns/src/build.xml
++++ b/apps/susidns/src/build.xml
+@@ -14,8 +14,10 @@
+ 		<pathelement location="${lib}/org.mortbay.jetty.jar"/>
+         <pathelement location="WEB-INF/lib/jstl.jar" />
+         <pathelement location="WEB-INF/lib/standard.jar" />
+-        <pathelement location="${lib}/jasper-compiler.jar" />
+-        <pathelement location="${lib}/jasper-runtime.jar" />
++        <pathelement location="${lib}/jasper.jar" />
++        <pathelement location="${lib}/tomcat-juli.jar" />
++        <pathelement location="${lib}/el-api.jar" />
++        <pathelement location="${lib}/jasper-el.jar" />
+         <pathelement location="${lib}/javax.servlet.jar" />
+         <pathelement location="${lib}/jsp-api.jar" />
+         <pathelement location="${lib}/commons-logging.jar" />
+--- a/build.xml
++++ b/build.xml
+@@ -679,7 +679,7 @@
+         <copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
+         <!-- all jetty stuff -->
+         <copy todir="pkg-temp/lib" >
+-            <fileset dir="build" includes="commons*.jar jasper*.jar javax*.jar jetty*.jar jsp*.jar org.mortbay.jetty.jar" />
++            <fileset dir="build" includes="commons*.jar jasper*.jar javax*.jar jetty*.jar jsp*.jar org.mortbay.jetty.jar el-api.jar tomcat-juli.jar" />
+         </copy>
+         <copy file="build/mstreaming.jar" todir="pkg-temp/lib/" />
+         <copy file="build/streaming.jar" todir="pkg-temp/lib/" />
diff --git a/debian/patches/series b/debian/patches/series
index 32c3c507a6f6abc78bf6ec7ba0ead27e5cc3227e..8d42ccd70d0c64042c4c6571f2faa5375f8e2b99 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -2,3 +2,5 @@
 0002-jbigi-soname.patch
 0003-renaming-jcpuid.patch
 0004-oom-listener.patch
+#debian-version.patch
+0004-jetty6.patch
diff --git a/debian/rules b/debian/rules
index 07a8ffe44a836fcd1a1c7e1f1e7e1aa9bfd68af2..60cc23e2c9fa787e712341cc655c4e49b8f9f3bd 100755
--- a/debian/rules
+++ b/debian/rules
@@ -43,10 +43,9 @@ override_dh_auto_clean:
 	-[ -r $(CURDIR)/debian/routerversion.java.bak ] && mv -f $(CURDIR)/debian/routerversion.java.bak $(ROUTERVERSION)
 	dh_auto_clean
 	ant distclean
-	# The next line is used by KYTV when building from source packages
-	#rm -f apps/jetty/jetty-5.1.15.tgz
 	rm -f core/c/jbigi/*.[s]o
 	rm -rf core/c/jcpuid/lib/
+	#rm -f $(CURDIR)/installer/lib/wrapper/all/wrapper.jar
 	debconf-updatepo
 
 override_dh_auto_build:
@@ -62,7 +61,6 @@ build-indep:
 	ant preppkg-unix javadoc
 	echo router.updateDisabled=true > $(I2P)/router.config
 	mv $(I2P)/runplain.sh $(I2P)/i2prouter-nowrapper
-	#-cp -fv /usr/share/tor/geoip $(CURDIR)/pkg-temp/geoip/geoip.txt
 	
 
 binary-arch: build-arch
diff --git a/installer/resources/clients.config b/installer/resources/clients.config
index 08c6c62ba88e0e01d1d90b64e04f48f29e59ed30..8dc6573381073a17b680d4271377d88b49019cbe 100644
--- a/installer/resources/clients.config
+++ b/installer/resources/clients.config
@@ -40,8 +40,14 @@ clientApp.2.args=i2ptunnel.config
 clientApp.2.startOnLoad=true
 
 # run our own eepsite with a seperate jetty instance
-clientApp.3.main=org.mortbay.jetty.Server
+clientApp.3.main=org.mortbay.start.Main
 clientApp.3.name=I2P webserver (eepsite)
+## To use the rewrite handler, edit jetty-rewrite.xml and use:
+#clientApp.3.args="/path/to/jetty.xml" "/path/to/jetty-rewrite.xml"
+## To use local SSL, edit jetty-ssl.xml and use:
+#clientApp.3.args="/path/to/jetty.xml" "/path/to/jetty-ssl.xml"
+## To use local or remote JMX, edit jetty-jmx.xml and use:
+#clientApp.3.args="/path/to/jetty.xml" "/path/to/jetty-jmx.xml"
 clientApp.3.args="eepsite/jetty.xml"
 clientApp.3.delay=30
 clientApp.3.startOnLoad=true
diff --git a/installer/resources/eepsite/contexts/base-context.xml b/installer/resources/eepsite/contexts/base-context.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1eac073303674f107fb2d32136663f6d647b1923
--- /dev/null
+++ b/installer/resources/eepsite/contexts/base-context.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"  encoding="ISO-8859-1"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+<!--
+Configure a custom context for the eepsite.
+
+This context contains only a ServletHandler with a default servlet
+to serve static html files and images.
+-->
+
+<Configure class="org.mortbay.jetty.handler.ContextHandler">
+  <Set name="contextPath">/</Set>
+  <Set name="resourceBase">./eepsite/docroot/</Set>
+  <Set name="handler">
+    <New class="org.mortbay.jetty.handler.ResourceHandler">
+      <Set name="welcomeFiles">
+        <Array type="String">
+          <Item>index.html</Item>
+        </Array>
+      </Set>
+      <Set name="cacheControl">max-age=3600,public</Set>
+    </New>
+  </Set>
+</Configure>
+
diff --git a/installer/resources/eepsite/contexts/cgi-context.xml b/installer/resources/eepsite/contexts/cgi-context.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77126f5a5cab628d0a89829245ec9e05e95684a0
--- /dev/null
+++ b/installer/resources/eepsite/contexts/cgi-context.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"  encoding="ISO-8859-1"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+<!--
+Configure a custom context for the eepsite.
+
+ * CGI Servlet.
+ * 
+ * The cgi bin directory can be set with the "cgibinResourceBase" init parameter
+ * or it will default to the resource base of the context.
+ * 
+ * The "commandPrefix" init parameter may be used to set a prefix to all
+ * commands passed to exec. This can be used on systems that need assistance to
+ * execute a particular file type. For example on windows this can be set to
+ * "perl" so that perl scripts are executed.
+ * 
+ * The "Path" init param is passed to the exec environment as PATH. Note: Must
+ * be run unpacked somewhere in the filesystem.
+ * 
+ * Any initParameter that starts with ENV_ is used to set an environment
+ * variable with the name stripped of the leading ENV_ and using the init
+ * parameter value.
+-->
+
+<Configure class="org.mortbay.jetty.handler.ContextHandler">
+  <Set name="contextPath">/cgi-bin</Set>
+  <Set name="resourceBase">./eepsite/cgi-bin/</Set>
+  <Set name="handler">
+    <New class="org.mortbay.jetty.servlet.ServletHandler" >
+      <Call name="addServletWithMapping">
+        <Arg>
+          <New class="org.mortbay.jetty.servlet.ServletHolder">
+            <Arg>
+              <New class="org.mortbay.servlet.CGI" />
+            </Arg>
+            <Call name="setInitParameter">
+              <Arg>Path</Arg>
+              <Arg>/usr/local/bin:/bin:/usr/bin</Arg>
+            </Call>
+          </New>
+        </Arg>
+        <Arg>/</Arg>
+      </Call>
+    </New>
+  </Set>
+</Configure>
diff --git a/installer/resources/eepsite.help/help/index.html b/installer/resources/eepsite/docroot/help/index.html
similarity index 100%
rename from installer/resources/eepsite.help/help/index.html
rename to installer/resources/eepsite/docroot/help/index.html
diff --git a/installer/resources/eepsite.help/help/index_de.html b/installer/resources/eepsite/docroot/help/index_de.html
similarity index 100%
rename from installer/resources/eepsite.help/help/index_de.html
rename to installer/resources/eepsite/docroot/help/index_de.html
diff --git a/installer/resources/eepsite.help/help/index_fr.html b/installer/resources/eepsite/docroot/help/index_fr.html
similarity index 100%
rename from installer/resources/eepsite.help/help/index_fr.html
rename to installer/resources/eepsite/docroot/help/index_fr.html
diff --git a/installer/resources/eepsite.help/help/index_na.html b/installer/resources/eepsite/docroot/help/index_na.html
similarity index 100%
rename from installer/resources/eepsite.help/help/index_na.html
rename to installer/resources/eepsite/docroot/help/index_na.html
diff --git a/installer/resources/eepsite.help/help/index_nl.html b/installer/resources/eepsite/docroot/help/index_nl.html
similarity index 100%
rename from installer/resources/eepsite.help/help/index_nl.html
rename to installer/resources/eepsite/docroot/help/index_nl.html
diff --git a/installer/resources/eepsite.help/help/index_ru.html b/installer/resources/eepsite/docroot/help/index_ru.html
similarity index 100%
rename from installer/resources/eepsite.help/help/index_ru.html
rename to installer/resources/eepsite/docroot/help/index_ru.html
diff --git a/installer/resources/eepsite.help/help/index_sv.html b/installer/resources/eepsite/docroot/help/index_sv.html
similarity index 100%
rename from installer/resources/eepsite.help/help/index_sv.html
rename to installer/resources/eepsite/docroot/help/index_sv.html
diff --git a/installer/resources/eepsite.help/help/lib/bg.png b/installer/resources/eepsite/docroot/help/lib/bg.png
similarity index 100%
rename from installer/resources/eepsite.help/help/lib/bg.png
rename to installer/resources/eepsite/docroot/help/lib/bg.png
diff --git a/installer/resources/eepsite.help/help/lib/brown.png b/installer/resources/eepsite/docroot/help/lib/brown.png
similarity index 100%
rename from installer/resources/eepsite.help/help/lib/brown.png
rename to installer/resources/eepsite/docroot/help/lib/brown.png
diff --git a/installer/resources/eepsite.help/help/lib/eepsite.css b/installer/resources/eepsite/docroot/help/lib/eepsite.css
similarity index 100%
rename from installer/resources/eepsite.help/help/lib/eepsite.css
rename to installer/resources/eepsite/docroot/help/lib/eepsite.css
diff --git a/installer/resources/eepsite.help/help/lib/h2bg.png b/installer/resources/eepsite/docroot/help/lib/h2bg.png
similarity index 100%
rename from installer/resources/eepsite.help/help/lib/h2bg.png
rename to installer/resources/eepsite/docroot/help/lib/h2bg.png
diff --git a/installer/resources/eepsite.help/help/lib/itoopie.png b/installer/resources/eepsite/docroot/help/lib/itoopie.png
similarity index 100%
rename from installer/resources/eepsite.help/help/lib/itoopie.png
rename to installer/resources/eepsite/docroot/help/lib/itoopie.png
diff --git a/installer/resources/eepsite.help/help/pagetemplate.html b/installer/resources/eepsite/docroot/help/pagetemplate.html
similarity index 100%
rename from installer/resources/eepsite.help/help/pagetemplate.html
rename to installer/resources/eepsite/docroot/help/pagetemplate.html
diff --git a/installer/resources/eepsite.help/index.html b/installer/resources/eepsite/docroot/index.html
similarity index 100%
rename from installer/resources/eepsite.help/index.html
rename to installer/resources/eepsite/docroot/index.html
diff --git a/installer/resources/eepsite.help/robots.txt b/installer/resources/eepsite/docroot/robots.txt
similarity index 100%
rename from installer/resources/eepsite.help/robots.txt
rename to installer/resources/eepsite/docroot/robots.txt
diff --git a/installer/resources/eepsite/etc/realm.properties b/installer/resources/eepsite/etc/realm.properties
new file mode 100644
index 0000000000000000000000000000000000000000..f9e4e7fa3cc98993b87428c51606c514c3f51757
--- /dev/null
+++ b/installer/resources/eepsite/etc/realm.properties
@@ -0,0 +1,21 @@
+#
+# This file defines users passwords and roles for a HashUserRealm
+#
+# The format is
+#  <username>: <password>[,<rolename> ...]
+#
+# Passwords may be clear text, obfuscated or checksummed.  The class 
+# org.mortbay.util.Password should be used to generate obfuscated
+# passwords or password checksums
+#
+# If DIGEST Authentication is used, the password must be in a recoverable
+# format, either plain text or OBF:.
+#
+jetty: MD5:164c88b302622e17050af52c89945d44,user
+admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin
+other: OBF:1xmk1w261u9r1w1c1xmq
+plain: plain
+user: password
+
+# This entry is for digest auth.  The credential is a MD5 hash of username:realmname:password
+digest: MD5:6e120743ad67abfbc385bc2bb754e297
diff --git a/installer/resources/eepsite/etc/webdefault.xml b/installer/resources/eepsite/etc/webdefault.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b8d01141697e4373b1be279693401ed5615b6547
--- /dev/null
+++ b/installer/resources/eepsite/etc/webdefault.xml
@@ -0,0 +1,410 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!-- ===================================================================== -->
+<!-- This file contains the default descriptor for web applications.       -->
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- The intent of this descriptor is to include jetty specific or common  -->
+<!-- configuration for all webapps.   If a context has a webdefault.xml    -->
+<!-- descriptor, it is applied before the contexts own web.xml file        -->
+<!--                                                                       -->
+<!-- A context may be assigned a default descriptor by:                    -->
+<!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->
+<!--  + Passed an arg to addWebApplications                                -->
+<!--                                                                       -->
+<!-- This file is used both as the resource within the jetty.jar (which is -->
+<!-- used as the default if no explicit defaults descriptor is set) and it -->
+<!-- is copied to the etc directory of the Jetty distro and explicitly     -->
+<!-- by the jetty.xml file.                                                -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+<web-app 
+   xmlns="http://java.sun.com/xml/ns/javaee" 
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
+   metadata-complete="true"
+   version="2.5"> 
+
+  <description>
+    Default web.xml file.  
+    This file is applied to a Web application before it's own WEB_INF/web.xml file
+  </description>
+
+
+  <!-- ==================================================================== -->
+  <!-- Context params to control Session Cookies                            -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- UNCOMMENT TO ACTIVATE
+  <context-param>
+    <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
+    <param-value>127.0.0.1</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
+    <param-value>/</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>org.mortbay.jetty.servlet.MaxAge</param-name>
+    <param-value>-1</param-value>
+  </context-param>
+  -->
+
+  <context-param>
+    <param-name>org.mortbay.jetty.webapp.NoTLDJarPattern</param-name>
+    <param-value>start.jar|ant-.*\.jar|dojo-.*\.jar|jetty-.*\.jar|jsp-api-.*\.jar|junit-.*\.jar|servlet-api-.*\.jar|dnsns\.jar|rt\.jar|jsse\.jar|tools\.jar|sunpkcs11\.jar|sunjce_provider\.jar|xerces.*\.jar</param-value>
+  </context-param>
+            
+
+
+  <!-- ==================================================================== -->
+  <!-- The default servlet.                                                 -->
+  <!-- This servlet, normally mapped to /, provides the handling for static -->
+  <!-- content, OPTIONS and TRACE methods for the context.                  -->
+  <!-- The following initParameters are supported:                          -->
+  <!--                                                                      -->
+  <!--   acceptRanges     If true, range requests and responses are         -->
+  <!--                    supported                                         -->
+  <!--                                                                      -->
+  <!--   dirAllowed       If true, directory listings are returned if no    -->
+  <!--                    welcome file is found. Else 403 Forbidden.        -->
+  <!--                                                                      -->
+  <!--   welcomeServlets  If true, attempt to dispatch to welcome files     -->
+  <!--                    that are servlets, if no matching static          --> 
+  <!--                    resources can be found.                           -->
+  <!--                                                                      -->
+  <!--   redirectWelcome  If true, redirect welcome file requests           -->
+  <!--                    else use request dispatcher forwards              -->
+  <!--                                                                      -->
+  <!--   gzip             If set to true, then static content will be served--> 
+  <!--                    as gzip content encoded if a matching resource is -->
+  <!--                    found ending with ".gz"                           -->
+  <!--                                                                      -->
+  <!--   resoureBase      Can be set to replace the context resource base   -->
+  <!--                                                                      -->
+  <!--   relativeResourceBase                                               -->
+  <!--                    Set with a pathname relative to the base of the   -->
+  <!--                    servlet context root. Useful for only serving     -->
+  <!--                    static content from only specific subdirectories. -->
+  <!--                                                                      -->
+  <!--   useFileMappedBuffer                                                -->
+  <!--                    If set to true (the default), a  memory mapped    -->
+  <!--                    file buffer will be used to serve static content  -->
+  <!--                    when using an NIO connector. Setting this value   -->
+  <!--                    to false means that a direct buffer will be used  -->
+  <!--                    instead. If you are having trouble with Windows   -->
+  <!--                    file locking, set this to false.                  -->
+  <!--                                                                      -->
+  <!--  cacheControl      If set, all static content will have this value   -->
+  <!--                    set as the cache-control header.                  -->
+  <!--                                                                      -->
+  <!--  maxCacheSize      Maximum size of the static resource cache         -->
+  <!--                                                                      -->
+  <!--  maxCachedFileSize Maximum size of any single file in the cache      -->
+  <!--                                                                      -->
+  <!--  maxCachedFiles    Maximum number of files in the cache              -->
+  <!--                                                                      -->
+  <!--  cacheType         "nio", "bio" or "both" to determine the type(s)   -->
+  <!--                    of resource cache. A bio cached buffer may be used-->
+  <!--                    by nio but is not as efficient as a nio buffer.   -->
+  <!--                    An nio cached buffer may not be used by bio.      -->
+  <!--                                                                      -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <servlet>
+    <servlet-name>default</servlet-name>
+    <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
+    <init-param>
+      <param-name>acceptRanges</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>dirAllowed</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>welcomeServlets</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>redirectWelcome</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCacheSize</param-name>
+      <param-value>256000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCachedFileSize</param-name>
+      <param-value>10000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCachedFiles</param-name>
+      <param-value>1000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>cacheType</param-name>
+      <param-value>both</param-value>
+    </init-param>
+    <init-param>
+      <param-name>gzip</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>useFileMappedBuffer</param-name>
+      <param-value>true</param-value>
+    </init-param>  
+    <!--
+    <init-param>
+      <param-name>cacheControl</param-name>
+      <param-value>max-age=3600,public</param-value>
+    </init-param>
+    -->
+    <load-on-startup>0</load-on-startup>
+  </servlet> 
+
+  <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
+  
+
+  <!-- ==================================================================== -->
+  <!-- JSP Servlet                                                          -->
+  <!-- This is the jasper JSP servlet from the jakarta project              -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- The JSP page compiler and execution servlet, which is the mechanism  -->
+  <!-- used by Glassfish to support JSP pages.  Traditionally, this servlet -->
+  <!-- is mapped to URL patterh "*.jsp".  This servlet supports the         -->
+  <!-- following initialization parameters (default values are in square    -->
+  <!-- brackets):                                                           -->
+  <!--                                                                      -->
+  <!--   checkInterval       If development is false and reloading is true, -->
+  <!--                       background compiles are enabled. checkInterval -->
+  <!--                       is the time in seconds between checks to see   -->
+  <!--                       if a JSP page needs to be recompiled. [300]    -->
+  <!--                                                                      -->
+  <!--   compiler            Which compiler Ant should use to compile JSP   -->
+  <!--                       pages.  See the Ant documenation for more      -->
+  <!--                       information. [javac]                           -->
+  <!--                                                                      -->
+  <!--   classdebuginfo      Should the class file be compiled with         -->
+  <!--                       debugging information?  [true]                 -->
+  <!--                                                                      -->
+  <!--   classpath           What class path should I use while compiling   -->
+  <!--                       generated servlets?  [Created dynamically      -->
+  <!--                       based on the current web application]          -->
+  <!--                       Set to ? to make the container explicitly set  -->
+  <!--                       this parameter.                                -->
+  <!--                                                                      -->
+  <!--   development         Is Jasper used in development mode (will check -->
+  <!--                       for JSP modification on every access)?  [true] -->
+  <!--                                                                      -->
+  <!--   enablePooling       Determines whether tag handler pooling is      -->
+  <!--                       enabled  [true]                                -->
+  <!--                                                                      -->
+  <!--   fork                Tell Ant to fork compiles of JSP pages so that -->
+  <!--                       a separate JVM is used for JSP page compiles   -->
+  <!--                       from the one Tomcat is running in. [true]      -->
+  <!--                                                                      -->
+  <!--   ieClassId           The class-id value to be sent to Internet      -->
+  <!--                       Explorer when using <jsp:plugin> tags.         -->
+  <!--                       [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93]   -->
+  <!--                                                                      -->
+  <!--   javaEncoding        Java file encoding to use for generating java  -->
+  <!--                       source files. [UTF-8]                          -->
+  <!--                                                                      -->
+  <!--   keepgenerated       Should we keep the generated Java source code  -->
+  <!--                       for each page instead of deleting it? [true]   -->
+  <!--                                                                      -->
+  <!--   logVerbosityLevel   The level of detailed messages to be produced  -->
+  <!--                       by this servlet.  Increasing levels cause the  -->
+  <!--                       generation of more messages.  Valid values are -->
+  <!--                       FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
+  <!--                       [WARNING]                                      -->
+  <!--                                                                      -->
+  <!--   mappedfile          Should we generate static content with one     -->
+  <!--                       print statement per input line, to ease        -->
+  <!--                       debugging?  [false]                            -->
+  <!--                                                                      -->
+  <!--                                                                      -->
+  <!--   reloading           Should Jasper check for modified JSPs?  [true] -->
+  <!--                                                                      -->
+  <!--   suppressSmap        Should the generation of SMAP info for JSR45   -->
+  <!--                       debugging be suppressed?  [false]              -->
+  <!--                                                                      -->
+  <!--   dumpSmap            Should the SMAP info for JSR45 debugging be    -->
+  <!--                       dumped to a file? [false]                      -->
+  <!--                       False if suppressSmap is true                  -->
+  <!--                                                                      -->
+  <!--   scratchdir          What scratch directory should we use when      -->
+  <!--                       compiling JSP pages?  [default work directory  -->
+  <!--                       for the current web application]               -->
+  <!--                                                                      -->
+  <!--   tagpoolMaxSize      The maximum tag handler pool size  [5]         -->
+  <!--                                                                      -->
+  <!--   xpoweredBy          Determines whether X-Powered-By response       -->
+  <!--                       header is added by generated servlet  [false]  -->
+  <!--                                                                      -->
+  <!-- If you wish to use Jikes to compile JSP pages:                       -->
+  <!--   Set the init parameter "compiler" to "jikes".  Define              -->
+  <!--   the property "-Dbuild.compiler.emacs=true" when starting Jetty     -->
+  <!--   to cause Jikes to emit error messages in a format compatible with  -->
+  <!--   Jasper.                                                            -->
+  <!--   If you get an error reporting that jikes can't use UTF-8 encoding, -->
+  <!--   try setting the init parameter "javaEncoding" to "ISO-8859-1".     -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <servlet id="jsp">
+    <servlet-name>jsp</servlet-name>
+    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+    <init-param>
+        <param-name>logVerbosityLevel</param-name>
+        <param-value>DEBUG</param-value>
+    </init-param>
+    <init-param>
+        <param-name>fork</param-name>
+        <param-value>false</param-value>
+    </init-param>
+    <init-param>
+        <param-name>xpoweredBy</param-name>
+        <param-value>false</param-value>
+    </init-param>
+    <!--  
+    <init-param>
+        <param-name>classpath</param-name>
+        <param-value>?</param-value>
+    </init-param>
+    -->
+    <load-on-startup>0</load-on-startup>
+  </servlet>
+
+  <servlet-mapping> 
+    <servlet-name>jsp</servlet-name> 
+    <url-pattern>*.jsp</url-pattern> 
+    <url-pattern>*.jspf</url-pattern>
+    <url-pattern>*.jspx</url-pattern>
+    <url-pattern>*.xsp</url-pattern>
+    <url-pattern>*.JSP</url-pattern> 
+    <url-pattern>*.JSPF</url-pattern>
+    <url-pattern>*.JSPX</url-pattern>
+    <url-pattern>*.XSP</url-pattern>
+  </servlet-mapping>
+  
+  <!-- ==================================================================== -->
+  <!-- Dynamic Servlet Invoker.                                             -->
+  <!-- This servlet invokes anonymous servlets that have not been defined   -->
+  <!-- in the web.xml or by other means. The first element of the pathInfo  -->
+  <!-- of a request passed to the envoker is treated as a servlet name for  -->
+  <!-- an existing servlet, or as a class name of a new servlet.            -->
+  <!-- This servlet is normally mapped to /servlet/*                        -->
+  <!-- This servlet support the following initParams:                       -->
+  <!--                                                                      -->
+  <!--  nonContextServlets       If false, the invoker can only load        -->
+  <!--                           servlets from the contexts classloader.    -->
+  <!--                           This is false by default and setting this  -->
+  <!--                           to true may have security implications.    -->
+  <!--                                                                      -->
+  <!--  verbose                  If true, log dynamic loads                 -->
+  <!--                                                                      -->
+  <!--  *                        All other parameters are copied to the     -->
+  <!--                           each dynamic servlet as init parameters    -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- Uncomment for dynamic invocation
+  <servlet>
+    <servlet-name>invoker</servlet-name>
+    <servlet-class>org.mortbay.jetty.servlet.Invoker</servlet-class>
+    <init-param>
+      <param-name>verbose</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>nonContextServlets</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>dynamicParam</param-name>
+      <param-value>anyValue</param-value>
+    </init-param>
+    <load-on-startup>0</load-on-startup>
+  </servlet>
+
+  <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
+  -->
+
+
+
+  <!-- ==================================================================== -->
+  <session-config>
+    <session-timeout>30</session-timeout>
+  </session-config>
+
+  <!-- ==================================================================== -->
+  <!-- Default MIME mappings                                                -->
+  <!-- The default MIME mappings are provided by the mime.properties        -->
+  <!-- resource in the org.mortbay.jetty.jar file.  Additional or modified  -->
+  <!-- mappings may be specified here                                       -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- UNCOMMENT TO ACTIVATE
+  <mime-mapping>
+    <extension>mysuffix</extension>
+    <mime-type>mymime/type</mime-type>
+  </mime-mapping>
+  -->
+
+  <!-- ==================================================================== -->
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+    <welcome-file>index.htm</welcome-file>
+    <welcome-file>index.jsp</welcome-file>
+  </welcome-file-list>
+
+  <!-- ==================================================================== -->
+  <locale-encoding-mapping-list>
+    <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>     
+    <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>   
+  </locale-encoding-mapping-list>
+  
+  <security-constraint>
+    <web-resource-collection>
+      <web-resource-name>Disable TRACE</web-resource-name>
+      <url-pattern>/</url-pattern>
+      <http-method>TRACE</http-method>
+    </web-resource-collection>
+    <auth-constraint/>
+  </security-constraint>
+  
+</web-app>
+
diff --git a/installer/resources/eepsite/jetty-jmx.xml b/installer/resources/eepsite/jetty-jmx.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dbf076858de72f4610cfcbbb01fd8f1183bb4fea
--- /dev/null
+++ b/installer/resources/eepsite/jetty-jmx.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+
+<!-- =============================================================== -->
+<!-- Configure the JVM JMX Server                                    -->
+<!-- this configuration file should be used in combination with      -->
+<!-- other configuration files.  e.g.                                -->
+<!--    java -jar start.jar etc/jetty-jmx.xml etc/jetty.xml          -->
+<!-- See jetty-jmx-mx4j.xml for a non JVM server solution            -->
+<!-- =============================================================== -->
+<Configure id="Server" class="org.mortbay.jetty.Server">
+
+    <!-- =========================================================== -->
+    <!-- Initialize an mbean server                                  -->
+    <!-- =========================================================== -->
+    <!-- Use the jdk 1.5 platformMBeanServer -->
+    <Call id="MBeanServer" class="java.lang.management.ManagementFactory" name="getPlatformMBeanServer"/>
+
+    <!-- =========================================================== -->
+    <!-- Initialize the Jetty MBean container                        -->
+    <!-- =========================================================== -->
+    <Get id="Container" name="container">
+      <Call name="addEventListener">
+        <Arg>
+          <New class="org.mortbay.management.MBeanContainer">
+            <Arg><Ref id="MBeanServer"/></Arg>
+            <Call name="start" />
+          </New>
+        </Arg>
+      </Call>
+    </Get>
+
+    <!-- =========================================================== -->
+    <!-- Enable stats (why else are you using JMX?                                -->
+    <!-- Sneakily replace the top-level handler with a StatisticsHandler          -->
+    <!-- Note we could use AtomicStatisticsHandler in jetty-java5-stats.jar (4KB) -->
+    <!-- but it really isn't worth bundling it.                                   -->
+    <!-- http://blog.markfeeney.com/2010/10/jmx-statistics-in-jetty-6-6122.html   -->
+    <!-- =========================================================== -->
+    <Get id="oldhandler" name="handler"/>
+    <Set name="handler">
+      <New id="StatsHandler" class="org.mortbay.jetty.handler.StatisticsHandler">
+        <Set name="handler"><Ref id="oldhandler"/></Set>
+      </New>
+    </Set>
+
+
+    <!--
+    When setting up the JMXConnectorServer via RMI, two TCP ports are used to communicate with
+    the remote server:
+    * the rmiregistry port (by default 1099) from where the RMI stub is downloaded
+    * the rmi server port (by default randomly chosen) where the actual RMI communication happens
+    The JMXServiceURL for the default configuration is therefore:
+
+    service:jmx:rmi:///jndi/rmi://<remotehost>:1099/jmxrmi
+
+    In case a firewall is restricting port access, you need to make sure that the rmi server port
+    is not chosen randomly, and this can be specified with the following JMXServiceURL:
+
+    service:jmx:rmi://<host>:2100/jndi/rmi://<host>:2099/jmxrmi
+
+    where 2099 is the rmiregistry port and 2100 is the rmi server port.
+    Make sure the firewall allow access to those ports.
+
+    When using the XML configuration below, you don't need to specify any of the JMX system properties
+    on the command line (see http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html).
+    -->
+
+    <!-- Setup the RMIRegistry on a specific port
+    <Call id="rmiRegistry" class="java.rmi.registry.LocateRegistry" name="createRegistry">
+      <Arg type="int">2099</Arg>
+    </Call>
+    -->
+    <!-- Setup the JMXConnectorServer on a specific rmi server port
+    <Call id="jmxConnectorServer" class="javax.management.remote.JMXConnectorServerFactory" name="newJMXConnectorServer">
+      <Arg>
+        <New  class="javax.management.remote.JMXServiceURL">
+          <Arg>service:jmx:rmi://localhost:2100/jndi/rmi://localhost:2099/jmxrmi</Arg>
+        </New>
+      </Arg>
+      <Arg/>
+      <Arg><Ref id="MBeanServer"/></Arg>
+      <Call name="start"/>
+    </Call>
+    -->
+
+</Configure>
+
diff --git a/installer/resources/eepsite/jetty-rewrite.xml b/installer/resources/eepsite/jetty-rewrite.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ef5043aac00bea97acb40f55ea55276abdc5553d
--- /dev/null
+++ b/installer/resources/eepsite/jetty-rewrite.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Mixin the RewriteHandler                                        -->
+<!-- =============================================================== -->
+
+
+<Configure id="Server" class="org.mortbay.jetty.Server">
+
+    <!-- =========================================================== -->
+    <!-- Configure Rewrite Handler                                   --> 
+    <!-- =========================================================== -->
+    <Get id="oldhandler" name="handler"/>
+
+    <Set name="handler">
+     <New id="Rewrite" class="org.mortbay.jetty.handler.rewrite.RewriteHandler">
+     
+      <Set name="handler"><Ref id="oldhandler"/></Set>
+      <Set name="rewriteRequestURI">true</Set>
+      <Set name="rewritePathInfo">false</Set>
+      <Set name="originalPathAttribute">requestedPath</Set>
+
+      <Set name="rules">
+          <Array type="org.mortbay.jetty.handler.rewrite.Rule">
+
+           <!-- return an error message if low on threads; put this at the top so it will be processed first -->
+           <Item>
+             <New id="lowThreads" class="org.mortbay.jetty.handler.rewrite.LowThreadsRuleContainer">                
+                <!-- set the trigger for low threads ridiculously low 
+                uncomment the block below to see it in action -->
+                <!--Ref id="Server">
+                  <Get id="serverThreadPool" name="threadPool">
+                    <Set name="minThreads">3</Set>
+                    <Set name="maxThreads">4</Set>
+                    <Set name="lowThreads">0</Set>
+                  </Get>
+                </Ref>
+
+                <Set name="threadPool"><Ref id="serverThreadPool"/></Set-->
+                
+                <Call name="addRule">
+                  <Arg>
+                    <New id="busyresponse" class="org.mortbay.jetty.handler.rewrite.ResponsePatternRule">
+                        <Set name="pattern">/*</Set>
+                        <Set name="code">500</Set>
+                        <Set name="reason">Server busy</Set>
+                   </New>
+                  </Arg>
+                </Call>
+             </New>
+           </Item>
+
+            <!-- Add rule to protect against IE ssl bug -->
+            <Item>
+              <New class="org.mortbay.jetty.handler.rewrite.MsieSslRule"/>
+            </Item>
+
+            <!-- protect favicon handling -->
+            <Item>
+              <New class="org.mortbay.jetty.handler.rewrite.HeaderPatternRule">
+                <Set name="pattern">/favicon.ico</Set>
+                <Set name="name">Cache-Control</Set>
+                <Set name="value">Max-Age=3600,public</Set>
+                <Set name="terminating">true</Set>
+              </New>
+            </Item>
+
+
+            <!-- add a regex rule -->
+            <Item>
+              <New class="org.mortbay.jetty.handler.rewrite.RewriteRegexRule">
+                <Set name="regex">/rewrite/dump/regex/([^/]*)/(.*)</Set>
+                <Set name="replacement">/test/dump/$2/$1</Set>
+              </New>
+            </Item>
+
+            <!-- add a rewrite rule -->
+            <Item>
+              <New id="" class="org.mortbay.jetty.handler.rewrite.RewritePatternRule">
+                <Set name="pattern">/rewrite</Set>
+                <Set name="replacement">/rewrittento</Set>
+              </New>
+            </Item>
+            
+            <!-- add a response rule -->
+            <Item>
+              <New id="response" class="org.mortbay.jetty.handler.rewrite.ResponsePatternRule">
+                <Set name="pattern">/rewrite/session/</Set>
+                <Set name="code">401</Set>
+                <Set name="reason">Setting error code 401</Set>
+              </New>
+            </Item>
+
+            <!-- add a header pattern rule -->
+            <Item>
+              <New id="header" class="org.mortbay.jetty.handler.rewrite.HeaderPatternRule">
+                <Set name="pattern">*.jsp</Set>
+                <Set name="name">Server</Set>
+                <Set name="value">Server for JSP</Set>
+              </New>
+            </Item>
+
+            <!-- add a redirect -->
+            <Item>
+              <New id="redirect" class="org.mortbay.jetty.handler.rewrite.RedirectPatternRule">
+                <Set name="pattern">/rewrite/dispatch</Set>
+                <Set name="location">http://jetty.mortbay.org</Set>
+              </New>
+            </Item>
+
+            <Item>
+              <New id="forwardedHttps" class="org.mortbay.jetty.handler.rewrite.ForwardedSchemeHeaderRule">
+                <Set name="header">X-Forwarded-Scheme</Set>
+                <Set name="headerValue">https</Set>
+                <Set name="scheme">https</Set>
+              </New>
+            </Item>
+
+            <Item>
+              <New id="virtualHost" class="org.mortbay.jetty.handler.rewrite.VirtualHostRuleContainer">
+
+                <Set name="virtualHosts">
+                  <Array type="java.lang.String">
+                    <Item>mortbay.com</Item>
+                    <Item>www.mortbay.com</Item>
+                    <Item>mortbay.org</Item>
+                    <Item>www.mortbay.org</Item>
+                  </Array>
+                </Set>
+
+                <Call name="addRule">
+                  <Arg>
+                    <New class="org.mortbay.jetty.handler.rewrite.CookiePatternRule">
+                      <Set name="pattern">/*</Set>
+                      <Set name="name">CookiePatternRule</Set>
+                      <Set name="value">1</Set>
+                    </New>
+                  </Arg>
+                </Call>
+     
+             </New>
+           </Item>           
+          </Array>
+        </Set>
+      </New>
+    </Set>
+    
+</Configure>
diff --git a/installer/resources/eepsite/jetty-ssl.xml b/installer/resources/eepsite/jetty-ssl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..49421d69c3ae28da0ee9e63dfb331ecc76aaec3a
--- /dev/null
+++ b/installer/resources/eepsite/jetty-ssl.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure SSL for the Jetty Server                              -->
+<!-- this configuration file should be used in combination with      -->
+<!-- other configuration files.  e.g.                                -->
+<!--    java -jar start.jar etc/jetty.xml etc/jetty-ssl.xml          -->
+<!-- =============================================================== -->
+<Configure id="Server" class="org.mortbay.jetty.Server">
+
+
+
+  <Call name="addConnector">
+    <Arg>
+      <New class="org.mortbay.jetty.security.SslSocketConnector">
+        <Set name="Port">8443</Set>
+        <Set name="maxIdleTime">30000</Set>
+        <Set name="handshakeTimeout">2000</Set>
+        <Set name="keystore">./eepsite/etc/keystore.ks</Set>
+        <Set name="password">OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4</Set>
+        <Set name="keyPassword">OBF:1u2u1wml1z7s1z7a1wnl1u2g</Set>
+        <Set name="truststore">./eepsite/etc/keystore.ks</Set>
+        <Set name="trustPassword">OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4</Set>
+        <Set name="handshakeTimeout">2000</Set>
+        <!-- Set name="ThreadPool">
+          <New class="org.mortbay.thread.QueuedThreadPool">
+            <Set name="minThreads">0</Set>
+            <Set name="maxThreads">16</Set>
+         </New>
+        </Set -->
+      </New>
+    </Arg>
+  </Call>
+</Configure>
diff --git a/installer/resources/eepsite/jetty.xml b/installer/resources/eepsite/jetty.xml
new file mode 100644
index 0000000000000000000000000000000000000000..33a1226e282947dd743f2cf66d46714ed25a167d
--- /dev/null
+++ b/installer/resources/eepsite/jetty.xml
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8" ?> 
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure 1.2//EN" "http://jetty.mortbay.org/configure_1_2.dtd">
+
+<!-- ========================================================================= -->
+<!-- This file configures the Jetty server.                                    -->
+<!-- All changes require a restart of I2P.                                     -->
+<!--                                                                           -->
+<!-- Commonly changed settings:                                                -->
+<!--   * host: Change 127.0.0.1 to 0.0.0.0 in the addListener section          -->
+<!--           to access the server directly (bypassing i2p)                   -->
+<!--           from other computers. The included version of Jetty has         -->
+<!--           been patched to allow IPv6 addresses as well,                   -->
+<!--           enclosed in brackets e.g. [::1]                                 -->
+<!--   * port: Default 7658 in the addListener section                         -->
+<!--   * docroot: Change the ResourceBase in the addContext section            -->
+<!--           to serve files from a different location.                       -->
+<!--   * threads: Raise MinThreads and/or MaxThreads in the addListener section -->
+<!--           if you have a high-traffic site and get a lot of warnings.      -->
+<!--   * Uncomment the addWebApplications section to use to enable             -->
+<!--           war files placed in the webapps/ dir.                           -->
+<!--   * Uncomment the line to allow Jetty to follow symlinks                  -->
+<!--                                                                           -->
+<!-- I2P uses Jetty 5.1.15. We have no plans to upgrade to Jetty 6, due to     -->
+<!-- the significant changes in the API. If you need web server features not   -->
+<!-- found in Jetty 5, you may install and run Jetty 6 in a different JVM,     -->
+<!-- or run any other web server such as Apache. If you do run another         -->
+<!-- web server instead, be sure and disable the Jetty 5 server for your       -->
+<!-- eepsite on http://127.0.0.1:7657/configclients.jsp .                      -->
+<!--                                                                           -->
+<!-- Jetty errors and warnings will appear in wrapper.log, check there         -->
+<!-- to diagnose problems.                                                     -->
+<!--                                                                           -->
+<!-- Note that the XML encoding for this file is UTF-8.                        -->
+<!--                                                                           -->
+<!-- If you have a 'split' directory installation, with configuration          -->
+<!-- files in ~/.i2p (Linux) or %APPDATA%\I2P (Windows), be sure to            -->
+<!-- edit the file in the configuration directory, NOT the install directory.  -->
+<!--                                                                           -->
+<!-- ========================================================================= -->
+
+<!-- =============================================================== -->
+<!-- Configure the Jetty Server                                      -->
+<!--                                                                 -->
+<!-- Documentation of this file format can be found at:              -->
+<!-- http://docs.codehaus.org/display/JETTY/jetty.xml                -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+
+
+<Configure id="Server" class="org.mortbay.jetty.Server">
+
+    <!-- =========================================================== -->
+    <!-- Server Thread Pool                                          -->
+    <!-- =========================================================== -->
+    <Set name="ThreadPool">
+
+      <!-- PICK ONE -->
+
+      <!-- If you don't have or want threadpool
+           Requests above the max will be queued
+       -->
+     <!--
+      <New class="org.mortbay.thread.QueuedThreadPool">
+        <Set name="minThreads">1</Set>
+        <Set name="maxThreads">16</Set>
+        <Set name="lowThreads">2</Set>
+      </New>
+     -->
+
+      <!-- Optional Java 5 bounded threadpool with job queue 
+           Requests above the max will be rejected
+           TODO: would be nice to use the 5-arg constructor but
+                 how do you use an Enum as the TimeUnit argument?
+           Alternatively, make a custom class where we can
+           set the thread name, set daemon, etc.
+           See RouterConsoleRunner.
+       -->
+      <New class="org.mortbay.thread.concurrent.ThreadPool">
+        <Arg type="int">0</Arg>
+        <Set name="corePoolSize">1</Set>
+        <Set name="maximumPoolSize">16</Set>
+      </New>
+    </Set>
+
+
+
+    <!-- =========================================================== -->
+    <!-- Set connectors                                              -->
+    <!-- =========================================================== -->
+    <!-- One of each type!                                           -->
+    <!-- =========================================================== -->
+
+    <!-- Use this connector for many frequently idle connections
+         and for threadless continuations.
+    -->    
+    <Call name="addConnector">
+      <Arg>
+          <New class="org.mortbay.jetty.nio.SelectChannelConnector">
+            <Set name="host">127.0.0.1</Set>
+            <Set name="port">7658</Set>
+            <Set name="maxIdleTime">60000</Set>
+            <Set name="Acceptors">1</Set>
+            <Set name="statsOn">false</Set>
+            <Set name="confidentialPort">8443</Set>
+	    <Set name="lowResourcesConnections">5000</Set>
+	    <Set name="lowResourcesMaxIdleTime">5000</Set>
+          </New>
+      </Arg>
+    </Call>
+
+    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+    <!-- To add a HTTPS SSL listener                                     -->
+    <!-- see jetty-ssl.xml to add an ssl connector. use                  -->
+    <!-- To enable this change clients.config args to be:                -->
+    <!--                                                                 -->
+    <!--   clientApp3.args=etc/jetty.xml etc/jetty-ssl.xml               -->
+    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+  <!-- Add a HTTPS SSL listener on port 8443                               -->
+  <!--                                                                     -->
+  <!-- In the unlikely event you would want SSL support for your eepsite.  -->
+  <!-- You would need to generate a selfsigned certificate in a keystore   -->
+  <!-- in ~/.i2p/eepsite/keystore.ks, for example with the command line:   -->
+  <!--
+       keytool -genkey -storetype JKS -keystore ~/.i2p/eepsite/etc/keystore.ks -storepass changeit -alias console -dname CN=xyz123.eepsite.i2p.net,OU=Eepsite,O=I2P Anonymous Network,L=XX,ST=XX,C=XX -validity 3650 -keyalg DSA -keysize 1024 -keypass myKeyPassword 
+   -->
+  <!-- Change the CN and key password in the example, of course.           -->
+  <!-- You wouldn't want to open this up to the regular internet,          -->
+  <!-- would you?? Untested and not recommended.                           -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+    <!-- =========================================================== -->
+    <!-- Set up global session ID manager                            -->
+    <!-- =========================================================== -->
+    <!--
+    <Set name="sessionIdManager">
+      <New class="org.mortbay.jetty.servlet.HashSessionIdManager">
+        <Set name="workerName">node1</Set>
+      </New>
+    </Set>
+    -->
+
+    <!-- =========================================================== -->
+    <!-- Set handler Collection Structure                            --> 
+    <!-- =========================================================== -->
+    <Set name="handler">
+      <New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection">
+        <Set name="handlers">
+         <Array type="org.mortbay.jetty.Handler">
+           <Item>
+             <New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/>
+           </Item>
+           <Item>
+             <New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/>
+           </Item>
+           <Item>
+             <New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/>
+           </Item>
+         </Array>
+        </Set>
+      </New>
+    </Set>
+    
+    <!-- =========================================================== -->
+    <!-- Configure the context deployer                              -->
+    <!-- A context deployer will deploy contexts described in        -->
+    <!-- configuration files discovered in a directory.              -->
+    <!-- The configuration directory can be scanned for hot          -->
+    <!-- deployments at the configured scanInterval.                 -->
+    <!--                                                             -->
+    <!-- This deployer is configured to deploy contexts configured   -->
+    <!-- in the $JETTY_HOME/contexts directory                       -->
+    <!--                                                             -->
+    <!-- =========================================================== -->
+    <Call name="addLifeCycle">
+      <Arg>
+        <New class="org.mortbay.jetty.deployer.ContextDeployer">
+          <Set name="contexts"><Ref id="Contexts"/></Set>
+          <Set name="configurationDir">./eepsite/contexts</Set>
+          <Set name="scanInterval">0</Set>
+        </New>
+      </Arg>
+    </Call>
+
+    <!-- =========================================================== -->
+    <!-- Configure the webapp deployer.                              -->
+    <!-- A webapp  deployer will deploy standard webapps discovered  -->
+    <!-- in a directory at startup, without the need for additional  -->
+    <!-- configuration files.    It does not support hot deploy or   -->
+    <!-- non standard contexts (see ContextDeployer above).          -->
+    <!--                                                             -->
+    <!-- This deployer is configured to deploy webapps from the      -->
+    <!-- $JETTY_HOME/webapps directory                               -->
+    <!--                                                             -->
+    <!-- Normally only one type of deployer need be used.            -->
+    <!--                                                             -->
+    <!-- =========================================================== -->
+    <Call name="addLifeCycle">
+      <Arg>
+        <New class="org.mortbay.jetty.deployer.WebAppDeployer">
+          <Set name="contexts"><Ref id="Contexts"/></Set>
+          <Set name="webAppDir">./eepsite/webapps</Set>
+	  <Set name="parentLoaderPriority">false</Set>
+	  <Set name="extract">true</Set>
+	  <Set name="allowDuplicates">false</Set>
+          <Set name="defaultsDescriptor">./eepsite/etc/webdefault.xml</Set>
+        </New>
+      </Arg>
+    </Call>
+
+    <!-- =========================================================== -->
+    <!-- Configure Authentication Realms                             -->
+    <!-- Realms may be configured for the entire server here, or     -->
+    <!-- they can be configured for a specific web app in a context  -->
+    <!-- configuration (see $(jetty.home)/contexts/test.xml for an   -->
+    <!-- example).                                                   -->
+    <!-- =========================================================== -->
+  <!-- UNCOMMENT TO ACTIVATE
+    <Set name="UserRealms">
+      <Array type="org.mortbay.jetty.security.UserRealm">
+        <Item>
+          <New class="org.mortbay.jetty.security.HashUserRealm">
+            <Set name="name">Test Realm</Set>
+            <Set name="config">./eepsite/etc/realm.properties</Set>
+            <Set name="refreshInterval">0</Set>
+          </New>
+        </Item>
+      </Array>
+    </Set>
+  -->
+
+    <!-- =========================================================== -->
+    <!-- Configure Request Log                                       -->
+    <!-- Request logs  may be configured for the entire server here, -->
+    <!-- or they can be configured for a specific web app in a       -->
+    <!-- contexts configuration (see $(jetty.home)/contexts/test.xml -->
+    <!-- for an example).                                            -->
+    <!-- =========================================================== -->
+    <Ref id="RequestLog">
+      <Set name="requestLog">
+        <New id="RequestLogImpl" class="net.i2p.jetty.I2PRequestLog">
+          <Set name="filename">./eepsite/logs/yyyy_mm_dd.request.log</Set>
+          <Set name="filenameDateFormat">yyyy_MM_dd</Set>
+          <Set name="retainDays">90</Set>
+          <Set name="append">true</Set>
+          <Set name="extended">false</Set>
+          <Set name="logCookies">false</Set>
+          <Set name="LogTimeZone">GMT</Set>
+        </New>
+      </Set>
+    </Ref>
+
+    <!-- =========================================================== -->
+    <!-- extra options                                               -->
+    <!-- =========================================================== -->
+    <Set name="stopAtShutdown">true</Set>
+    <Set name="sendServerVersion">false</Set>
+    <Set name="sendDateHeader">true</Set>
+    <Set name="gracefulShutdown">1000</Set>
+
+</Configure>
diff --git a/installer/resources/jetty.xml b/installer/resources/jetty.xml
deleted file mode 100644
index a5072d8d757d197a3a0891b827578cb0364ed67c..0000000000000000000000000000000000000000
--- a/installer/resources/jetty.xml
+++ /dev/null
@@ -1,238 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?> 
-<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure 1.2//EN" "http://jetty.mortbay.org/configure_1_2.dtd">
-
-<!-- ========================================================================= -->
-<!-- This file configures the Jetty server.                                    -->
-<!-- All changes require a restart of I2P.                                     -->
-<!--                                                                           -->
-<!-- Commonly changed settings:                                                -->
-<!--   * host: Change 127.0.0.1 to 0.0.0.0 in the addListener section          -->
-<!--           to access the server directly (bypassing i2p)                   -->
-<!--           from other computers. The included version of Jetty has         -->
-<!--           been patched to allow IPv6 addresses as well,                   -->
-<!--           enclosed in brackets e.g. [::1]                                 -->
-<!--   * port: Default 7658 in the addListener section                         -->
-<!--   * docroot: Change the ResourceBase in the addContext section            -->
-<!--           to serve files from a different location.                       -->
-<!--   * threads: Raise MinThreads and/or MaxThreads in the addListener section -->
-<!--           if you have a high-traffic site and get a lot of warnings.      -->
-<!--   * Uncomment the addWebApplications section to use to enable             -->
-<!--           war files placed in the webapps/ dir.                           -->
-<!--   * Uncomment the line to allow Jetty to follow symlinks                  -->
-<!--                                                                           -->
-<!-- I2P uses Jetty 5.1.15. We have no plans to upgrade to Jetty 6, due to     -->
-<!-- the significant changes in the API. If you need web server features not   -->
-<!-- found in Jetty 5, you may install and run Jetty 6 in a different JVM,     -->
-<!-- or run any other web server such as Apache. If you do run another         -->
-<!-- web server instead, be sure and disable the Jetty 5 server for your       -->
-<!-- eepsite on http://127.0.0.1:7657/configclients.jsp .                      -->
-<!--                                                                           -->
-<!-- Jetty errors and warnings will appear in wrapper.log, check there         -->
-<!-- to diagnose problems.                                                     -->
-<!--                                                                           -->
-<!-- Note that the XML encoding for this file is UTF-8.                        -->
-<!--                                                                           -->
-<!-- If you have a 'split' directory installation, with configuration          -->
-<!-- files in ~/.i2p (Linux) or %APPDATA%\I2P (Windows), be sure to            -->
-<!-- edit the file in the configuration directory, NOT the install directory.  -->
-<!--                                                                           -->
-<!-- ========================================================================= -->
-
-<!-- =============================================================== -->
-<!-- Configure the Jetty Server                                      -->
-<!-- =============================================================== -->
-<Configure class="org.mortbay.jetty.Server">
-
-  <!-- =============================================================== -->
-  <!-- Configure the Request Listeners                                 -->
-  <!-- =============================================================== -->
-
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <!-- Add and configure a HTTP listener to port 8080                  -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <Call name="addListener">
-    <Arg>
-      <New class="org.mortbay.http.SocketListener">
-        <Arg>
-          <New class="org.mortbay.util.InetAddrPort">
-            <Set name="host">127.0.0.1</Set>
-            <Set name="port">7658</Set>
-          </New>
-        </Arg>
-        <Set name="MinThreads">1</Set>
-        <Set name="MaxThreads">16</Set>
-        <Set name="MaxIdleTimeMs">60000</Set>
-        <Set name="LowResourcePersistTimeMs">1000</Set>
-        <Set name="ConfidentialPort">8443</Set>
-        <Set name="IntegralPort">8443</Set>
-      </New>
-    </Arg>
-  </Call>
-
-
-
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <!-- Add a HTTPS SSL listener on port 8443                               -->
-  <!--                                                                     -->
-  <!-- In the unlikely event you would want SSL support for your eepsite.  -->
-  <!-- You would need to generate a selfsigned certificate in a keystore   -->
-  <!-- in ~/.i2p/eepsite/keystore.ks, for example with the command line:   -->
-  <!--
-       keytool -genkey -storetype JKS -keystore ~/.i2p/eepsite/keystore.ks -storepass changeit -alias console -dname CN=xyz123.eepsite.i2p.net,OU=Eepsite,O=I2P Anonymous Network,L=XX,ST=XX,C=XX -validity 3650 -keyalg DSA -keysize 1024 -keypass myKeyPassword 
-   -->
-  <!-- Change the CN and key password in the example, of course.           -->
-  <!-- You wouldn't want to open this up to the regular internet,          -->
-  <!-- would you?? Untested and not recommended.                           -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <!-- UNCOMMENT TO ACTIVATE
-  <Call name="addListener">
-    <Arg>
-      <New class="org.mortbay.http.SslListener">
-        <Set name="Port">8443</Set>
-        <Set name="PoolName">main</Set>
-        <Set name="Keystore">./eepsite/keystore.ks</Set>
-	<Set name="Password">changeit</Set>
-	<Set name="KeyPassword">myKeyPassword</Set>
-        <Set name="NonPersistentUserAgent">MSIE 5</Set>
-      </New>
-    </Arg>
-  </Call>
-  -->
-
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <!-- Add a AJP13 listener on port 8009                               -->
-  <!-- This protocol can be used with mod_jk in apache, IIS etc.       -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <!-- UNCOMMENT TO ACTIVATE
-  <Call name="addListener">
-    <Arg>
-      <New class="org.mortbay.http.ajp.AJP13Listener">
-        <Set name="PoolName">ajp</Set>
-        <Set name="Port">8009</Set>
-        <Set name="MinThreads">3</Set>
-        <Set name="MaxThreads">20</Set>
-        <Set name="MaxIdleTimeMs">0</Set>
-        <Set name="confidentialPort">443</Set>
-      </New>
-    </Arg>
-  </Call>
-  -->
-
-
-  <!-- =============================================================== -->
-  <!-- Uncomment this to allow Jetty to follow symlinks                -->
-  <!-- Jetty declares this to be a security risk, use with care        -->
-  <!-- See also http://docs.codehaus.org/display/JETTY/How+to+enable+serving+aliased+files -->
-  <!-- =============================================================== -->
-  <!-- UNCOMMENT TO ACTIVATE
-  <Set name="checkAliases" class="org.mortbay.util.FileResource" type="boolean">false</Set>
-  -->
-
-
-  <!-- =============================================================== -->
-  <!-- Configure the Contexts                                          -->
-  <!-- =============================================================== -->
-
-
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <!-- Add a all web application within the webapps directory.         -->
-  <!-- + No virtual host specified                                     -->
-  <!-- + Look in the webapps directory relative to jetty.home or .     -->
-  <!-- + Use the default webdefault.xml in jetty's install             -->
-  <!-- + Upack the war file                                            -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <Set name="rootWebApp">root</Set>
-  <!-- UNCOMMENT TO ACTIVATE
-  <Call name="addWebApplications">
-    <Arg></Arg>
-    <Arg>./eepsite/webapps/</Arg>
-    <Arg></Arg>
-    <Arg type="boolean">true</Arg>
-  </Call>
-  -->
-
-
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <!-- Add and configure a specific web application                    -->
-  <!-- + Set Unpack WAR files                                          -->
-  <!-- + Set Default Descriptor.  Resource, file or URL                -->
-  <!-- + Set Virtual Hosts. A Null host or empty array means all hosts -->
-  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
-  <!-- UNCOMMENT TO ACTIVATE
-  <Call name="addWebApplication">
-    <Arg>/context</Arg>
-    <Arg>./webapps/root</Arg>
-
-    <Set name="extractWAR">false</Set> 
-
-    <Set name="defaultsDescriptor">org/mortbay/jetty/servlet/webdefault.xml</Set>
-
-    <Set name="virtualHosts">
-      <Array type="java.lang.String">
-        <Item></Item>
-        <Item>127.0.0.1</Item>
-        <Item>localhost</Item>
-        <Item>www.acme.com</Item>
-      </Array>
-    </Set>
-  </Call>
-  -->
-
-  <Call name="addContext">
-    <Arg>
-      <New class="org.mortbay.http.HttpContext">
-        <Set name="contextPath">/</Set>
-        <Set name="resourceBase">./eepsite/docroot</Set>
-        <Call name="addHandler">
-          <Arg>
-            <New class="org.mortbay.http.handler.ResourceHandler">
-              <Set name="redirectWelcome">FALSE</Set>
-              <!-- disable TRACE and OPTIONS ref: http://osdir.com/ml/java.jetty.support/2003-11/msg00014.html -->
-              <Set name="AllowedMethods">
-                <Array type="String">
-                  <Item>GET</Item>
-                  <Item>HEAD</Item>
-                  <Item>POST</Item>
-                </Array>
-              </Set>
-	    </New>
-          </Arg>
-        </Call>
-      </New>
-    </Arg>
-  </Call>
-  
-  <Call name="addContext">
-    <Arg>/cgi-bin/*</Arg>
-    <Set name="ResourceBase">./eepsite/cgi-bin</Set>
-    <Call name="addServlet">
-      <Arg>Common Gateway Interface</Arg>
-      <Arg>/</Arg>
-      <Arg>org.mortbay.servlet.CGI</Arg>
-     <Put name="Path">/usr/local/bin:/usr/ucb:/bin:/usr/bin</Put>
-    </Call>
-  </Call>
-
-  <!-- =============================================================== -->
-  <!-- Configure the Request Log                                       -->
-  <!-- =============================================================== -->
-  <Set name="RequestLog">
-    <New class="org.mortbay.http.I2PRequestLog">
-      <Arg>./eepsite/logs/yyyy_mm_dd.request.log</Arg>
-      <Set name="retainDays">90</Set>
-      <Set name="append">true</Set>
-      <Set name="extended">false</Set>
-      <Set name="buffered">false</Set>
-      <Set name="LogTimeZone">GMT</Set>
-    </New>
-  </Set>
-
-  <!-- =============================================================== -->
-  <!-- Configure the Other Server Options                              -->
-  <!-- =============================================================== -->
-  <Set name="requestsPerGC">2000</Set>
-<!--  defaults to false, requires access through jconsole?
-  <Set name="statsOn">false</Set>
--->
-
-</Configure>
diff --git a/licenses/NOTICE-Jetty.txt b/licenses/NOTICE-Jetty.txt
new file mode 100644
index 0000000000000000000000000000000000000000..21d4ed3d0ee3a1cbaf494b4017837e79ca84356d
--- /dev/null
+++ b/licenses/NOTICE-Jetty.txt
@@ -0,0 +1,36 @@
+==============================================================
+ Jetty Web Container 
+ Copyright 1995-2009 Mort Bay Consulting Pty Ltd
+==============================================================
+
+The Jetty Web Container is Copyright Mort Bay Consulting Pty Ltd
+unless otherwise noted. It is licensed under the apache 2.0
+license.
+
+The javax.servlet package used by Jetty is copyright 
+Sun Microsystems, Inc and Apache Software Foundation. It is 
+distributed under the Common Development and Distribution License.
+You can obtain a copy of the license at 
+https://glassfish.dev.java.net/public/CDDLv1.0.html.
+
+The UnixCrypt.java code ~Implements the one way cryptography used by
+Unix systems for simple password protection.  Copyright 1996 Aki Yoshida,
+modified April 2001  by Iris Van den Broeke, Daniel Deville.
+Permission to use, copy, modify and distribute UnixCrypt 
+for non-commercial or commercial purposes and without fee is
+granted provided that the copyright notice appears in all copies.
+
+The default JSP implementation is provided by the Glassfish JSP engine
+from project Glassfish http://glassfish.dev.java.net.  Copyright 2005
+Sun Microsystems, Inc. and portions Copyright Apache Software Foundation.
+
+Some portions of the code are Copyright:
+  2006 Tim Vernum 
+  1999 Jason Gilbert.
+
+The jboss integration module contains some LGPL code.
+
+The win32 Java Service Wrapper (v3.2.3) is Copyright (c) 1999, 2006 
+Tanuki Software, Inc.  and 2001 Silver Egg Technology.  It is 
+covered by an open license which is viewable at
+http://svn.codehaus.org/jetty/jetty/branches/jetty-6.1/extras/win32service/LICENSE.txt
diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java
index 473714c4ee53b0bf1e54e7e50dce723ca6d0cead..71d6b5fa261abeda1337f216cd798c5d06551b34 100644
--- a/router/java/src/net/i2p/router/Router.java
+++ b/router/java/src/net/i2p/router/Router.java
@@ -1420,11 +1420,13 @@ public class Router implements RouterClock.ClockShiftListener {
             // and we will die with NCDFE.
             // Ideally, do not use I2P classes at all, new or not.
             try {
-                // TODO move deleteListedFiles() here after a few releases
-                if (ok)
+                if (ok) {
+                    // We do this here so we may delete old jars before we restart
+                    deleteListedFiles();
                     System.out.println("INFO: Update installed");
-                else
+                } else {
                     System.out.println("ERROR: Update failed!");
+                }
                 if (!ok) {
                     // we can't leave the file in place or we'll continually restart, so rename it
                     File bad = new File(_context.getRouterDir(), "BAD-" + UPDATE_FILE);
@@ -1455,8 +1457,10 @@ public class Router implements RouterClock.ClockShiftListener {
             System.exit(EXIT_HARD_RESTART);
         } else {
             deleteJbigiFiles();
-            // Here so it may be used in the 0.8.12 update
-            // TODO move up in a few releases so it is only run after an update
+            // It was here starting in 0.8.12 so it could be used the very first time
+            // Now moved up so it is usually run only after an update
+            // But the first time before jetty 6 it will run here...
+            // Here we can't remove jars
             deleteListedFiles();
         }
     }
diff --git a/router/java/src/net/i2p/router/startup/ClientAppConfig.java b/router/java/src/net/i2p/router/startup/ClientAppConfig.java
index 44f1fa0950a8cf86c8514622393a466fe7aa7eee..7d81ebd06d44b40ad3e36333ec765d68987ff13b 100644
--- a/router/java/src/net/i2p/router/startup/ClientAppConfig.java
+++ b/router/java/src/net/i2p/router/startup/ClientAppConfig.java
@@ -131,14 +131,18 @@ public class ClientAppConfig {
     
     /*
      * Go through the properties, and return a List of ClientAppConfig structures
+     * This is for the router.
      */
     public static List<ClientAppConfig> getClientApps(RouterContext ctx) {
         Properties clientApps = getClientAppProps(ctx);
-        return getClientApps(clientApps);
+        List<ClientAppConfig> rv = getClientApps(clientApps);
+        MigrateJetty.migrate(ctx, rv);
+        return rv;
     }
 
     /*
      * Go through the properties, and return a List of ClientAppConfig structures
+     * This is for plugins.
      *
      * @since 0.7.12
      */
@@ -190,14 +194,14 @@ public class ClientAppConfig {
     }
 
     /** classpath and stopargs not supported */
-    public static void writeClientAppConfig(RouterContext ctx, List apps) {
+    public static void writeClientAppConfig(RouterContext ctx, List<ClientAppConfig> apps) {
         File cfgFile = configFile(ctx);
         FileOutputStream fos = null;
         try {
             fos = new SecureFileOutputStream(cfgFile);
             StringBuilder buf = new StringBuilder(2048);
             for(int i = 0; i < apps.size(); i++) {
-                ClientAppConfig app = (ClientAppConfig) apps.get(i);
+                ClientAppConfig app = apps.get(i);
                 buf.append(PREFIX).append(i).append(".main=").append(app.className).append("\n");
                 buf.append(PREFIX).append(i).append(".name=").append(app.clientName).append("\n");
                 if (app.args != null)
diff --git a/router/java/src/net/i2p/router/startup/MigrateJetty.java b/router/java/src/net/i2p/router/startup/MigrateJetty.java
new file mode 100644
index 0000000000000000000000000000000000000000..b78331284c1ca7839feb70ca31c11a7cf09aa0dc
--- /dev/null
+++ b/router/java/src/net/i2p/router/startup/MigrateJetty.java
@@ -0,0 +1,159 @@
+package net.i2p.router.startup;
+/*
+ * free (adj.): unencumbered; not under the control of others
+ * Released into the public domain
+ * with no warranty of any kind, either expressed or implied.
+ */
+
+import java.io.File;
+import java.util.List;
+
+import net.i2p.router.RouterContext;
+
+/**
+ *  Migrate the clients.config and jetty.xml files
+ *  from Jetty 5 to Jetty 6.
+ *
+ *  For each client for class org.mortbay.jetty.Server:
+ *<pre>
+ *  Let $D be the dir that jetty.xml is in (usually ~/.i2p/eepsite)
+ *  Saves $D/jetty.xml to $D/jetty5.xml
+ *  Copies $I2P/eepsite-jetty6/jetty.xml to $D/jetty.xml, edited for $D
+ *  Copies $I2P/eepsite-jetty6/jetty-ssl.xml to $D/jetty-ssl.xml, edited for $D
+ *  Copies $I2P/eepsite-jetty6/jetty-rewrite.xml to $D/jetty-rewrite.xml
+ *  Copies $I2P/eepsite-jetty6/context/base-context.xml to $D/jetty.xml, edited for $D
+ *  Copies $I2P/eepsite-jetty6/context/cgi-context.xml to $D/jetty.xml, edited for $D
+ *  Copies $I2P/eepsite-jetty6/etc/* to $D/etc
+ *  Changes main class in clients.config
+ *</pre>
+ *  Copies clients.config to clients.config.backup
+ *  Saves new clients.config
+ *
+ *  Does NOT preserve port number, thread counts, etc.
+ *
+ *  @since Jetty 6
+ */
+abstract class MigrateJetty {
+    private static boolean _wasChecked;
+    private static boolean _hasJetty6;
+
+    private static final String OLD_CLASS = "org.mortbay.jetty.Server";
+    private static final String NEW_CLASS = "org.mortbay.start.Main";
+    private static final String BACKUP = "jetty5.xml";
+    private static final String JETTY6_TEMPLATE_DIR = "eepsite-jetty6";
+    private static final String JETTY6_TEMPLATE_PKGDIR = "eepsite";
+    private static final String BASE_CONTEXT = "contexts/base-context.xml";
+    private static final String CGI_CONTEXT = "contexts/cgi-context.xml";
+    
+    public static void migrate(RouterContext ctx, List<ClientAppConfig> apps) {
+        boolean shouldSave = false;
+        for (int i = 0; i < apps.size(); i++) {
+            ClientAppConfig app = apps.get(i);
+            if (!app.className.equals(OLD_CLASS))
+                continue;
+            String client = "client application " + i + " [" + app.clientName +
+                            "] from Jetty 5 " + OLD_CLASS +
+                            " to Jetty 6 " + NEW_CLASS;
+            if (!hasJetty6()) {
+                System.err.println("WARNING: Jetty 6 unavailable, cannot migrate " + client);
+                continue;
+            }
+            if (app.args == null)
+                continue;
+            // remove quotes
+            String args[] = LoadClientAppsJob.parseArgs(app.args);
+            if (args.length == 0)
+                continue;
+            String xml = args[0];
+            File xmlFile = new File(xml);
+            if (!xmlFile.isAbsolute())
+                xmlFile = new File(ctx.getAppDir(), xml);
+            if (!xmlFile.exists()) {
+                System.err.println("WARNING: XML file " + xmlFile +
+                               " not found, cannot migrate " + client);
+                continue;
+            }
+            File eepsite = xmlFile.getParentFile();
+            File backup = new File(eepsite, BACKUP);
+            if (backup.exists())
+                backup = new File(eepsite, BACKUP + ctx.random().nextInt());
+            boolean ok = WorkingDir.copyFile(xmlFile, backup);
+            if (!ok) {
+                System.err.println("WARNING: Failed to copy XML file " + xmlFile + " to " + backup +
+                               ", cannot migrate " + client);
+                continue;
+            }
+            File baseEep = new File(ctx.getBaseDir(), JETTY6_TEMPLATE_DIR);
+            // in packages, or perhaps on an uninstall/reinstall, the files are in eepsite/
+            if (!baseEep.exists())
+                baseEep = new File(ctx.getBaseDir(), JETTY6_TEMPLATE_PKGDIR);
+            if (baseEep.equals(eepsite)) {
+                // non-split directory yet not an upgrade? shouldn't happen
+                System.err.println("Eepsite in non-split directory " + eepsite +
+                               ", cannot migrate " + client);
+                continue;
+            }
+            // jetty.xml existed before in jetty 5 version, so check this new file
+            // and if it doesn't exist we can't continue
+            File baseContext = new File(baseEep, BASE_CONTEXT);
+            if (!baseContext.exists()) {
+                System.err.println("WARNING: Cannot find new XML file template " + baseContext +
+                               ", cannot migrate " + client);
+                continue;
+            }
+            String newPath = eepsite.getAbsolutePath() + File.separatorChar;
+            ok = WorkingDir.migrateJettyXml(baseEep, eepsite, "jetty.xml", "./eepsite/", newPath);
+            if (!ok) {
+                System.err.println("WARNING: Failed to modify XML file " + xmlFile +
+                               ", cannot migrate " + client);
+                continue;
+            }
+            // now we're committed, so don't check any more failure codes
+            WorkingDir.migrateJettyXml(baseEep, eepsite, "jetty-ssl.xml", "./eepsite/", newPath);
+            (new File(eepsite, "contexts")).mkdir();
+            WorkingDir.migrateJettyXml(baseEep, eepsite, BASE_CONTEXT, "./eepsite/", newPath);
+            WorkingDir.migrateJettyXml(baseEep, eepsite, CGI_CONTEXT, "./eepsite/", newPath);
+            WorkingDir.copyFile(new File(baseEep, "jetty-rewrite.xml"), new File(eepsite, "jetty-rewrite.xml"));
+            (new File(eepsite, "etc")).mkdir();
+            File to = new File(eepsite, "etc/realm.properties");
+            if (!to.exists())
+                WorkingDir.copyFile(new File(baseEep, "etc/realm.properties"), to);
+            to = new File(eepsite, "etc/webdefault.xml");
+            if (!to.exists())
+                WorkingDir.copyFile(new File(baseEep, "etc/webdefault.xml"), to);
+            app.className = NEW_CLASS;
+            shouldSave = true;
+            System.err.println("WARNING: Migrated " + client + '\n' +
+                               "Check the following files in " + eepsite +
+                               ": jetty.xml, " + BASE_CONTEXT + ", and " + CGI_CONTEXT + "\n" +
+                               "Your old jetty.xml was saved as " + backup + '\n' +
+                               "If you modified your jetty.xml to change ports, thread limits, etc, you MUST\n" +
+                               "edit it to change them again. Your port was reset to 7658.");
+        }
+        if (shouldSave) {
+            File cfgFile = ClientAppConfig.configFile(ctx);
+            File backup = new File(cfgFile.getAbsolutePath() + ".jetty5");
+            if (backup.exists())
+                backup = new File(cfgFile.getAbsolutePath() + ctx.random().nextInt());
+            boolean ok = WorkingDir.copyFile(cfgFile, backup);
+            if (ok) {
+                ClientAppConfig.writeClientAppConfig(ctx, apps);
+                System.err.println("WARNING: Migrated clients config file " + cfgFile +
+                               " from Jetty 5 " + OLD_CLASS +
+                               " to Jetty 6 " + NEW_CLASS + "\n" +
+                               "Your old clients config file was saved as " + backup);
+            }
+        }
+    }
+
+    private static boolean hasJetty6() {
+        if (!_wasChecked) {
+            try {
+                LoadClientAppsJob.testClient(NEW_CLASS, null);
+                _hasJetty6 = true;
+            } catch (ClassNotFoundException cnfe) {}
+            _wasChecked = true;
+        }
+        return _hasJetty6;
+    }
+}
diff --git a/router/java/src/net/i2p/router/startup/WorkingDir.java b/router/java/src/net/i2p/router/startup/WorkingDir.java
index f5c2645cc2e66cab8bd55ffb9c53cd60353a9ab9..78b9aad7015feab8c7cd1195ff5e2be7d73ac174 100644
--- a/router/java/src/net/i2p/router/startup/WorkingDir.java
+++ b/router/java/src/net/i2p/router/startup/WorkingDir.java
@@ -163,7 +163,13 @@ public class WorkingDir {
             System.err.println("Setting up new user directory " + rv);
         boolean success = migrate(MIGRATE_BASE, oldDirf, dirf);
         // this one must be after MIGRATE_BASE
-        success &= migrateJettyXml(oldDirf, dirf);
+        File oldEep = new File(oldDirf, "eepsite");
+        File newEep = new File(dirf, "eepsite");
+        String newPath = newEep.getAbsolutePath() + File.separatorChar;
+        success &= migrateJettyXml(oldEep, newEep, "jetty.xml", "./eepsite/", newPath);
+        success &= migrateJettyXml(oldEep, newEep, "jetty-ssl.xml", "./eepsite/", newPath);
+        success &= migrateJettyXml(oldEep, newEep, "contexts/base-context.xml", "./eepsite/", newPath);
+        success &= migrateJettyXml(oldEep, newEep, "contexts/cgi-context.xml", "./eepsite/", newPath);
         success &= migrateClientsConfig(oldDirf, dirf);
         // for later news.xml updates (we don't copy initialNews.xml over anymore)
         success &= (new SecureDirectory(dirf, "docs")).mkdir();
@@ -298,11 +304,11 @@ public class WorkingDir {
                 }
                 out.println(s);
             }
-            System.err.println("Copied clients.config with modifications");
+            System.err.println("Copied " + oldFile + " with modifications");
             return true;
         } catch (IOException ioe) {
             if (in != null) {
-                System.err.println("FAILED copy clients.config");
+                System.err.println("FAILED copy " + oldFile + ": " + ioe);
                 return false;
             }
             return false;
@@ -317,11 +323,9 @@ public class WorkingDir {
      *  It was already copied over once in migrate(), throw that out and
      *  do it again with modifications.
      */
-    private static boolean migrateJettyXml(File olddir, File todir) {
-        File eepsite1 = new File(olddir, "eepsite");
-        File oldFile = new File(eepsite1, "jetty.xml");
-        File eepsite2 = new File(todir, "eepsite");
-        File newFile = new File(eepsite2, "jetty.xml");
+    static boolean migrateJettyXml(File olddir, File todir, String filename, String oldString, String newString) {
+        File oldFile = new File(olddir, filename);
+        File newFile = new File(todir, filename);
         FileInputStream in = null;
         PrintWriter out = null;
         try {
@@ -329,17 +333,17 @@ public class WorkingDir {
             out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(newFile), "UTF-8")));
             String s = null;
             while ((s = DataHelper.readLine(in)) != null) {
-                if (s.indexOf("./eepsite/") >= 0) {
-                    s = s.replace("./eepsite/", todir.getAbsolutePath() + File.separatorChar + "eepsite" + File.separatorChar);
+                if (s.indexOf(oldString) >= 0) {
+                    s = s.replace(oldString, newString);
                 }
                 out.println(s);
             }
             out.println("<!-- Modified by I2P User dir migration script -->");
-            System.err.println("Copied jetty.xml with modifications");
+            System.err.println("Copied " + oldFile + " with modifications");
             return true;
         } catch (IOException ioe) {
             if (in != null) {
-                System.err.println("FAILED copy jetty.xml");
+                System.err.println("FAILED copy " + oldFile + ": " + ioe);
                 return false;
             }
             return false;
@@ -395,7 +399,7 @@ public class WorkingDir {
      * @param dst not a directory, will be overwritten if existing, will be mode 600
      * @return true if it was copied successfully
      */
-    private static boolean copyFile(File src, File dst) {
+    static boolean copyFile(File src, File dst) {
         if (!src.exists()) return false;
         boolean rv = true;
 
@@ -412,7 +416,7 @@ public class WorkingDir {
             
             System.err.println("Copied " + src.getPath());
         } catch (IOException ioe) {
-            System.err.println("FAILED copy " + src.getPath());
+            System.err.println("FAILED copy " + src.getPath() + ": " + ioe);
             rv = false;
         } finally {
             if (in != null) try { in.close(); } catch (IOException ioe) {}