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,"<","<"),">",">"); - 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],"<","<"),">",">")); - buf.append("</A> "); - buf.append("</TD><TD ALIGN=right>"); - buf.append(item.length()); - buf.append(" bytes </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 » 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 "ant debianhowto" for instructions" /> - <echo message=" debian-clean: rollback debian specific patches and run the "distclean" target (done automatically at the end of the "debian" target)" /> - <!-- <echo message=" debianrepo: build a Debian repository (reprepro required)" /> --> + <echo message=" debian: generate Debian packages in ../" /> + <echo message=" run "ant debianhowto" for instructions" /> + <echo message=" debian-clean: rollback debian specific patches and run the "distclean" target (done automatically at the end of the "debian" 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=""debian/control" in both the Build-Depends and Build-Depends-Indep fields."/> - <echo message="In addition to those packages, be sure to install "fakeroot","/> - <echo message=""quilt" and "build-essential"!" /> - <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 "ant debian""/> - <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=""debian/control" in the "Build-Depends" field."/> + <echo message="In addition to those packages, be sure to install "fakeroot","/> + <echo message=""quilt" and "build-essential"!" /> + <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 "ant debian""/> + <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 "libjetty-java-doc"" /> + </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) {}