First cut at migrating to Jetty 6 and prep for using an external
Jetty 6 package. - Add several jars from the Jetty 6 distribution - Update jetty.xml - Add context XML files - Update WorkingDir to migrate the content XML files - Update RouterConsoleRunner and LocaleWebAppHandler - Remove all old Jetty 5.1.15 local mods; this will break Seedless using a custom Server() constructor - Update I2PRequestLog to be a mod of NCSARequestLog from 6.1.26 - Put I2PRequestLog in its own jar - Copy MultiPartRequest and other required classes from Jetty 5.1.15 and add it to susimail, as the replacement MultiPartFilter in Jetty 6 is difficult to migrate to, and does not support content-type - Update i2psnark for Jetty 6 - Disable i2psnark RunStandalone, unused and instantiated Jetty 5 - Fix up all webapp build.xml to reference new jars Not yet working: Plugin/webapp run detection and stopping, eepsite CGI Not well tested: Plugins, classpaths, webapps
@ -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>
|
||||
|
@ -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
|
||||
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);
|
||||
@ -1680,7 +1684,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());
|
||||
|
||||
@ -1783,7 +1787,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");
|
||||
|
||||
@ -1793,7 +1797,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
|
||||
@ -1849,9 +1853,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) {
|
||||
|
@ -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();
|
||||
}
|
||||
****/
|
||||
}
|
||||
}
|
||||
|
@ -169,6 +169,7 @@
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../jetty/jettylib/ant.jar" />
|
||||
<pathelement location="build/i2ptunnel.jar" />
|
||||
</classpath>
|
||||
@ -190,6 +191,7 @@
|
||||
<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" />
|
||||
</classpath>
|
||||
</javac>
|
||||
|
@ -1,10 +1,11 @@
|
||||
<?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="" />
|
||||
|
||||
@ -64,26 +65,46 @@
|
||||
</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.
|
||||
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
|
||||
commons-logging.jar: JspC compiler
|
||||
TODO which of these are available in the Ubuntu packages?
|
||||
-->
|
||||
<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/servlet-api-2.5-20081211.jar" tofile="jettylib/javax.servlet.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/ext/jetty-java5-threadpool-${jetty.ver}.jar" tofile="jettylib/jetty-threadpool.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}/start.jar" tofile="jettylib/jetty-start.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/" />
|
||||
</target>
|
||||
|
||||
<target name="build" depends="jar" />
|
||||
|
||||
<target name="builddep" />
|
||||
<target name="compile" depends="builddep, ensureJettylib" >
|
||||
<mkdir dir="./build" />
|
||||
@ -93,7 +114,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="./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 +133,13 @@
|
||||
</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" >
|
||||
<jar destfile="./jettylib/jetty-i2p.jar" basedir="./build/obj" includes="**/*.class" >
|
||||
<manifest>
|
||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||
|
@ -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('"');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,11 @@
|
||||
<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-threadpool.jar" />
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../systray/java/build/obj" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
<pathelement location="../../desktopgui/build" />
|
||||
@ -53,7 +57,11 @@
|
||||
<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-threadpool.jar" />
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../systray/java/build/systray.jar" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
|
||||
@ -233,6 +241,7 @@
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../jetty/jettylib/ant.jar" />
|
||||
<pathelement location="../../systray/java/build/obj" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
@ -266,6 +275,10 @@
|
||||
<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-threadpool.jar" />
|
||||
<pathelement location="../../jetty/jettylib/jsp-api.jar" />
|
||||
<pathelement location="../../systray/java/build/obj" />
|
||||
<pathelement location="../../systray/java/lib/systray4j.jar" />
|
||||
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
|
||||
|
@ -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
|
||||
@ -286,7 +286,7 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
* requested and add the .war to that one
|
||||
*/
|
||||
private void startWebApp(String app) {
|
||||
Server s = WebAppStarter.getConsoleServer();
|
||||
ContextHandlerCollection s = WebAppStarter.getConsoleServer();
|
||||
if (s != null) {
|
||||
try {
|
||||
File path = new File(_context.getBaseDir(), "webapps");
|
||||
|
@ -4,11 +4,13 @@ import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
import org.mortbay.http.HttpRequest;
|
||||
import org.mortbay.http.HttpResponse;
|
||||
import org.mortbay.jetty.servlet.WebApplicationHandler;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
|
||||
/**
|
||||
* Convert foo.jsp to foo_xx.jsp for language xx.
|
||||
@ -19,12 +21,12 @@ import org.mortbay.jetty.servlet.WebApplicationHandler;
|
||||
*
|
||||
* @author zzz
|
||||
*/
|
||||
public class LocaleWebAppHandler extends WebApplicationHandler
|
||||
public class LocaleWebAppHandler extends WebAppContext
|
||||
{
|
||||
private final I2PAppContext _context;
|
||||
|
||||
public LocaleWebAppHandler(I2PAppContext ctx) {
|
||||
super();
|
||||
public LocaleWebAppHandler(I2PAppContext ctx, String path, String warPath) {
|
||||
super(warPath, path);
|
||||
_context = ctx;
|
||||
}
|
||||
|
||||
@ -36,13 +38,13 @@ public class LocaleWebAppHandler extends WebApplicationHandler
|
||||
*/
|
||||
@Override
|
||||
public void handle(String pathInContext,
|
||||
String pathParams,
|
||||
HttpRequest httpRequest,
|
||||
HttpResponse httpResponse)
|
||||
throws IOException
|
||||
HttpServletRequest httpRequest,
|
||||
HttpServletResponse httpResponse,
|
||||
int dispatch)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
// Handle OPTIONS (nothing to override)
|
||||
if (HttpRequest.__OPTIONS.equals(httpRequest.getMethod()))
|
||||
if ("OPTIONS".equals(httpRequest.getMethod()))
|
||||
{
|
||||
handleOptions(httpRequest, httpResponse);
|
||||
return;
|
||||
@ -74,7 +76,9 @@ 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 = getHolderEntry(testPath);
|
||||
///////////////////////////////
|
||||
Map.Entry servlet = null;
|
||||
if (servlet != null) {
|
||||
String servletPath = (String) servlet.getKey();
|
||||
if (servletPath != null && !servletPath.startsWith("*")) {
|
||||
@ -87,7 +91,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 +99,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);
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,14 @@ import java.util.List;
|
||||
|
||||
import net.i2p.util.FileUtil;
|
||||
|
||||
import org.mortbay.http.Version;
|
||||
import org.mortbay.jetty.Server;
|
||||
|
||||
public class LogsHelper extends HelperBase {
|
||||
public LogsHelper() {}
|
||||
|
||||
/** @since 0.8.11 */
|
||||
public String getJettyVersion() {
|
||||
return Version.getImplVersion();
|
||||
return Server.getVersion();
|
||||
}
|
||||
|
||||
public String getLogs() {
|
||||
|
@ -28,7 +28,7 @@ import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.Translate;
|
||||
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.handler.ContextHandlerCollection;
|
||||
|
||||
|
||||
/**
|
||||
@ -120,7 +120,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 props = RouterConsoleRunner.webAppProperties(consoleDir.getAbsolutePath());
|
||||
@ -221,8 +221,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());
|
||||
@ -242,11 +242,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);
|
||||
|
@ -9,6 +9,7 @@ import java.security.KeyStore;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.apps.systray.SysTray;
|
||||
@ -24,25 +25,39 @@ 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.SessionHandler;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
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();
|
||||
@ -58,6 +73,10 @@ public class RouterConsoleRunner {
|
||||
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;
|
||||
|
||||
static {
|
||||
System.setProperty("org.mortbay.http.Version.paranoid", "true");
|
||||
}
|
||||
@ -135,6 +154,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.
|
||||
@ -158,6 +186,23 @@ public class RouterConsoleRunner {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* http://irc.codehaus.org/display/JETTY/Porting+to+jetty6
|
||||
*
|
||||
*<pre>
|
||||
* Server
|
||||
* HandlerCollection
|
||||
* ContextHandlerCollection
|
||||
* WebAppContext (i.e. ContextHandler)
|
||||
* SessionHandler
|
||||
* SecurityHandler
|
||||
* ServletHandler
|
||||
* WebAppContext
|
||||
* ...
|
||||
* DefaultHandler
|
||||
* RequestLogHandler (opt)
|
||||
*</pre>
|
||||
*/
|
||||
public void startConsole() {
|
||||
File workDir = new SecureDirectory(I2PAppContext.getGlobalContext().getTempDir(), "jetty-work");
|
||||
boolean workDirRemoved = FileUtil.rmdir(workDir, false);
|
||||
@ -171,14 +216,34 @@ public class RouterConsoleRunner {
|
||||
System.setProperty("jetty.class.path", I2PAppContext.getGlobalContext().getBaseDir() + "/lib/routerconsole.jar");
|
||||
_server = new Server();
|
||||
|
||||
/**** this doesn't work with NIO maybe?
|
||||
try {
|
||||
_server.setThreadPool(new ThreadPool(MIN_THREADS, MAX_THREADS, MAX_IDLE_TIME, TimeUnit.MILLISECONDS));
|
||||
} 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) {
|
||||
File logFile = new File(log);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -202,7 +267,7 @@ public class RouterConsoleRunner {
|
||||
_webAppsDir += '/';
|
||||
|
||||
List<String> notStarted = new ArrayList();
|
||||
WebApplicationHandler baseHandler = null;
|
||||
WebAppContext baseHandler = null;
|
||||
try {
|
||||
int boundAddresses = 0;
|
||||
|
||||
@ -217,17 +282,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);
|
||||
}
|
||||
}
|
||||
@ -252,19 +317,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);
|
||||
@ -280,15 +346,18 @@ 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");
|
||||
|
||||
baseHandler = 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);
|
||||
baseHandler.setTempDirectory(tmpdir);
|
||||
baseHandler.setSessionHandler(new SessionHandler());
|
||||
baseHandler.setServletHandler(new ServletHandler());
|
||||
initialize(baseHandler);
|
||||
chColl.addHandler(baseHandler);
|
||||
|
||||
File dir = new File(_webAppsDir);
|
||||
String fileNames[] = dir.list(WarFilenameFilter.instance());
|
||||
if (fileNames != null) {
|
||||
@ -300,7 +369,7 @@ public class RouterConsoleRunner {
|
||||
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.addWebApp(I2PAppContext.getGlobalContext(), chColl, appName, path, tmpdir);
|
||||
|
||||
if (enabled == null) {
|
||||
// do this so configclients.jsp knows about all apps from reading the config
|
||||
@ -315,12 +384,14 @@ public class RouterConsoleRunner {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
} catch (Exception ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
|
||||
if (rewrite)
|
||||
storeWebAppProperties(props);
|
||||
try {
|
||||
// start does a mapContexts()
|
||||
_server.start();
|
||||
} catch (Throwable me) {
|
||||
// NoClassFoundDefError from a webapp is a throwable, not an exception
|
||||
@ -337,8 +408,9 @@ public class RouterConsoleRunner {
|
||||
// map each not-started webapp to the error page
|
||||
for (int i = 0; i < notStarted.size(); i++) {
|
||||
try {
|
||||
baseHandler.mapPathToServlet('/' + notStarted.get(i) + "/*",
|
||||
"net.i2p.router.web.jsp.nowebapp_jsp");
|
||||
/////////////////////////////////////////////////
|
||||
//baseHandler.mapPathToServlet('/' + notStarted.get(i) + "/*",
|
||||
// "net.i2p.router.web.jsp.nowebapp_jsp");
|
||||
} catch (Throwable me) {
|
||||
System.err.println(me);
|
||||
}
|
||||
@ -454,18 +526,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
|
||||
@ -477,12 +553,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() {
|
||||
@ -507,11 +598,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) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,8 @@ import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
import org.mortbay.jetty.servlet.WebApplicationContext;
|
||||
import org.mortbay.jetty.webapp.Configuration;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
|
||||
|
||||
/**
|
||||
@ -31,16 +32,16 @@ import org.mortbay.jetty.servlet.WebApplicationContext;
|
||||
* @since 0.7.12
|
||||
* @author zzz
|
||||
*/
|
||||
public class WebAppConfiguration implements WebApplicationContext.Configuration {
|
||||
private WebApplicationContext _wac;
|
||||
public class WebAppConfiguration implements Configuration {
|
||||
private WebAppContext _wac;
|
||||
|
||||
private static final String CLASSPATH = ".classpath";
|
||||
|
||||
public void setWebApplicationContext(WebApplicationContext context) {
|
||||
public void setWebAppContext(WebAppContext context) {
|
||||
_wac = context;
|
||||
}
|
||||
|
||||
public WebApplicationContext getWebApplicationContext() {
|
||||
public WebAppContext getWebAppContext() {
|
||||
return _wac;
|
||||
}
|
||||
|
||||
@ -87,10 +88,16 @@ public class WebAppConfiguration implements WebApplicationContext.Configuration
|
||||
else
|
||||
path = dir.getAbsolutePath() + '/' + elem;
|
||||
System.err.println("Adding " + path + " to classpath for " + appName);
|
||||
_wac.addClassPath(path);
|
||||
_wac.setExtraClasspath(path);
|
||||
}
|
||||
}
|
||||
|
||||
public void configureDefaults() {}
|
||||
public void configureWebApp() {}
|
||||
|
||||
/** @since Jetty 6 */
|
||||
public void deconfigureWebApp() {}
|
||||
|
||||
/** @since Jetty 6 */
|
||||
public void configureClassLoader() {}
|
||||
}
|
||||
|
@ -14,10 +14,12 @@ import net.i2p.util.Log;
|
||||
import net.i2p.util.SecureDirectory;
|
||||
import net.i2p.util.PortMapper;
|
||||
|
||||
import org.mortbay.http.HttpContext;
|
||||
import org.mortbay.http.HttpListener;
|
||||
import org.mortbay.jetty.Connector;
|
||||
import org.mortbay.jetty.Handler;
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.servlet.WebApplicationContext;
|
||||
import org.mortbay.jetty.webapp.WebAppContext;
|
||||
import org.mortbay.jetty.handler.ContextHandler;
|
||||
import org.mortbay.jetty.handler.ContextHandlerCollection;
|
||||
|
||||
|
||||
/**
|
||||
@ -49,9 +51,10 @@ public class WebAppStarter {
|
||||
* adds and starts
|
||||
* @throws just about anything, caller would be wise to catch Throwable
|
||||
*/
|
||||
static void startWebApp(I2PAppContext ctx, Server server, String appName, String warPath) throws Exception {
|
||||
static void startWebApp(I2PAppContext ctx, ContextHandlerCollection server,
|
||||
String appName, String warPath) throws Exception {
|
||||
File tmpdir = new SecureDirectory(ctx.getTempDir(), "jetty-work-" + appName + ctx.random().nextInt());
|
||||
WebApplicationContext wac = addWebApp(ctx, server, appName, warPath, tmpdir);
|
||||
WebAppContext wac = addWebApp(ctx, server, appName, warPath, tmpdir);
|
||||
_log.debug("Loading war from: " + warPath);
|
||||
wac.start();
|
||||
}
|
||||
@ -61,12 +64,13 @@ public class WebAppStarter {
|
||||
* This is used only by RouterConsoleRunner, which adds all the webapps first
|
||||
* and then starts all at once.
|
||||
*/
|
||||
static WebApplicationContext addWebApp(I2PAppContext ctx, Server server, String appName, String warPath, File tmpdir) throws IOException {
|
||||
static WebAppContext addWebApp(I2PAppContext ctx, ContextHandlerCollection server,
|
||||
String appName, String warPath, File tmpdir) throws IOException {
|
||||
|
||||
// Jetty will happily load one context on top of another without stopping
|
||||
// the first one, so we remove any previous one here
|
||||
try {
|
||||
stopWebApp(server, appName);
|
||||
stopWebApp(appName);
|
||||
} catch (Throwable t) {}
|
||||
|
||||
// To avoid ZipErrors from JarURLConnetion caching,
|
||||
@ -91,7 +95,7 @@ public class WebAppStarter {
|
||||
warPath = tmpPath;
|
||||
}
|
||||
|
||||
WebApplicationContext wac = server.addWebApplication("/"+ appName, warPath);
|
||||
WebAppContext wac = new WebAppContext(warPath, "/"+ appName);
|
||||
tmpdir.mkdir();
|
||||
wac.setTempDirectory(tmpdir);
|
||||
|
||||
@ -101,12 +105,14 @@ public class WebAppStarter {
|
||||
|
||||
|
||||
// see WebAppConfiguration for info
|
||||
String[] classNames = server.getWebApplicationConfigurationClassNames();
|
||||
String[] classNames = wac.getConfigurationClasses();
|
||||
String[] newClassNames = new String[classNames.length + 1];
|
||||
for (int j = 0; j < classNames.length; j++)
|
||||
newClassNames[j] = classNames[j];
|
||||
newClassNames[classNames.length] = WebAppConfiguration.class.getName();
|
||||
wac.setConfigurationClassNames(newClassNames);
|
||||
wac.setConfigurationClasses(newClassNames);
|
||||
server.addHandler(wac);
|
||||
server.mapContexts();
|
||||
return wac;
|
||||
}
|
||||
|
||||
@ -114,38 +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() {
|
||||
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++) {
|
||||
if (hl[j].getPort() == I2PAppContext.getGlobalContext().portMapper().getPort(PortMapper.SVC_CONSOLE))
|
||||
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 (appName.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;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
<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" />
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -10,6 +10,6 @@
|
||||
# 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/
|
||||
|
55
build.xml
@ -194,12 +194,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">
|
||||
@ -391,9 +388,10 @@
|
||||
<group title="Desktopgui Application" packages="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="org.mortbay.http" />
|
||||
<group title="SAM Bridge" packages="net.i2p.sam: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" />
|
||||
@ -412,10 +410,16 @@
|
||||
<pathelement location="apps/BOB/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-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" />
|
||||
@ -670,14 +674,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.jetty.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/" />
|
||||
@ -724,20 +726,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">
|
||||
@ -931,14 +926,18 @@
|
||||
</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" >
|
||||
<fileset dir="build/lib" includes="jasper*.jar javax*.jar jetty*.jar jsp*.jar org.mortbay.jetty.jar" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- just our jetty 5 fixes, not for jetty 6 -->
|
||||
<target name="prepjupdatefixes" depends="prepupdate, buildWEB">
|
||||
<copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" />
|
||||
</target>
|
||||
|
@ -40,7 +40,7 @@ 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)
|
||||
clientApp.3.args="eepsite/jetty.xml"
|
||||
clientApp.3.delay=30
|
||||
|
25
installer/resources/eepsite/contexts/base-context.xml
Normal file
@ -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>
|
||||
|
33
installer/resources/eepsite/contexts/cgi-context.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?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="handler">
|
||||
<New class="org.mortbay.servlet.CGI">
|
||||
<Set name="cgibinResourceBase">./eepsite/cgi-bin/</Set>
|
||||
</New>
|
||||
</Set>
|
||||
</Configure>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 237 B After Width: | Height: | Size: 237 B |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
21
installer/resources/eepsite/etc/realm.properties
Normal file
@ -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
|
269
installer/resources/eepsite/jetty.xml
Normal file
@ -0,0 +1,269 @@
|
||||
<?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">
|
||||
|
||||
<!-- If you don't have threadpool
|
||||
<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
|
||||
<New class="org.mortbay.thread.concurrent.ThreadPool">
|
||||
<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">2</Set>
|
||||
<Set name="statsOn">false</Set>
|
||||
<Set name="confidentialPort">8443</Set>
|
||||
<Set name="lowResourcesConnections">5000</Set>
|
||||
<Set name="lowResourcesMaxIdleTime">5000</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
<!-- Use this connector if NIO is not available.
|
||||
<Call name="addConnector">
|
||||
<Arg>
|
||||
<New class="org.mortbay.jetty.bio.SocketConnector">
|
||||
<Set name="port">7658</Set>
|
||||
<Set name="maxIdleTime">50000</Set>
|
||||
<Set name="lowResourceMaxIdleTime">1500</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
-->
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- To add a HTTPS SSL listener -->
|
||||
<!-- see jetty-ssl.xml to add an ssl connector. use -->
|
||||
<!-- java -jar start.jar 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/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. -->
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- To allow Jetty to be started from xinetd -->
|
||||
<!-- mixin jetty-xinetd.xml: -->
|
||||
<!-- java -jar start.jar etc/jetty.xml etc/jetty-xinetd.xml -->
|
||||
<!-- -->
|
||||
<!-- See jetty-xinetd.xml for further instructions. -->
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- 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. -->
|
||||
<!-- -->
|
||||
<!-- =========================================================== -->
|
||||
<!-- UNCOMMENT TO ACTIVATE
|
||||
<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="org.mortbay.http.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>
|
@ -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>
|
@ -147,7 +147,9 @@ 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);
|
||||
success &= migrateJettyXml(oldDirf, dirf, "jetty.xml");
|
||||
success &= migrateJettyXml(oldDirf, dirf, "contexts/base-context.xml");
|
||||
success &= migrateJettyXml(oldDirf, dirf, "contexts/cgi-context.xml");
|
||||
success &= migrateClientsConfig(oldDirf, dirf);
|
||||
// for later news.xml updates (we don't copy initialNews.xml over anymore)
|
||||
success &= (new SecureDirectory(dirf, "docs")).mkdir();
|
||||
@ -258,11 +260,11 @@ 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) {
|
||||
private static boolean migrateJettyXml(File olddir, File todir, String filename) {
|
||||
File eepsite1 = new File(olddir, "eepsite");
|
||||
File oldFile = new File(eepsite1, "jetty.xml");
|
||||
File oldFile = new File(eepsite1, filename);
|
||||
File eepsite2 = new File(todir, "eepsite");
|
||||
File newFile = new File(eepsite2, "jetty.xml");
|
||||
File newFile = new File(eepsite2, filename);
|
||||
FileInputStream in = null;
|
||||
PrintWriter out = null;
|
||||
try {
|
||||
@ -276,11 +278,11 @@ public class WorkingDir {
|
||||
out.println(s);
|
||||
}
|
||||
out.println("<!-- Modified by I2P User dir migration script -->");
|
||||
System.err.println("Copied jetty.xml with modifications");
|
||||
System.err.println("Copied " + filename + " with modifications");
|
||||
return true;
|
||||
} catch (IOException ioe) {
|
||||
if (in != null) {
|
||||
System.err.println("FAILED copy jetty.xml");
|
||||
System.err.println("FAILED copy " + filename);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|