diff --git a/apps/i2psnark/java/build.xml b/apps/i2psnark/java/build.xml index edc92ed5b1..99fe0adc01 100644 --- a/apps/i2psnark/java/build.xml +++ b/apps/i2psnark/java/build.xml @@ -19,6 +19,7 @@ + @@ -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" > diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index 4898ddaf4a..a724fb8938 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -43,17 +43,16 @@ import org.klomp.snark.SnarkManager; import org.klomp.snark.Storage; import org.klomp.snark.TrackerClient; -import org.mortbay.http.HttpResponse; -import org.mortbay.jetty.servlet.Default; -import org.mortbay.util.Resource; -import org.mortbay.util.URI; +import org.mortbay.jetty.servlet.DefaultServlet; +import org.mortbay.resource.Resource; +import org.mortbay.util.URIUtil; /** * We extend Default instead of HTTPServlet so we can handle * i2psnark/ file requests with http:// instead of the flaky and * often-blocked-by-the-browser file:// */ -public class I2PSnarkServlet extends Default { +public class I2PSnarkServlet extends DefaultServlet { private I2PAppContext _context; private Log _log; private SnarkManager _manager; @@ -99,13 +98,17 @@ public class I2PSnarkServlet extends Default { * and we can't get any resources (like icons) out of the .war */ @Override - protected Resource getResource(String pathInContext) throws IOException + public Resource getResource(String pathInContext) { if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") || pathInContext.equals("/index.html") || pathInContext.startsWith("/_icons/")) return super.getResource(pathInContext); // files in the i2psnark/ directory - return _resourceBase.addPath(pathInContext); + try { + return _resourceBase.addPath(pathInContext); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } } /** @@ -113,10 +116,11 @@ public class I2PSnarkServlet extends Default { * @since 0.8.3 */ @Override - public void handleGet(HttpServletRequest request, HttpServletResponse response, String pathInContext, Resource resource, boolean endsWithSlash) throws ServletException, IOException { - if (resource.getName().startsWith("jar:file:")) - response.setHeader("Cache-Control", "max-age=86400"); // cache for a day - super.handleGet(request, response, pathInContext, resource, endsWithSlash); + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { +//////////////////////////////////// + //if (resource.getName().startsWith("jar:file:")) + // response.setHeader("Cache-Control", "max-age=86400"); // cache for a day + super.doGet(request, response); } /** @@ -144,7 +148,7 @@ public class I2PSnarkServlet extends Default { // since we are not overriding handle*(), do this here String method = req.getMethod(); if (!(method.equals("GET") || method.equals("HEAD") || method.equals("POST"))) { - resp.sendError(HttpResponse.__405_Method_Not_Allowed); + resp.sendError(405); return; } _themePath = "/themes/snark/" + _manager.getTheme() + '/'; @@ -157,20 +161,20 @@ public class I2PSnarkServlet extends Default { if (path.endsWith("/")) { // bypass the horrid Resource.getListHTML() String pathInfo = req.getPathInfo(); - String pathInContext = URI.addPaths(path, pathInfo); + String pathInContext = URIUtil.addPaths(path, pathInfo); req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html; charset=UTF-8"); Resource resource = getResource(pathInContext); if (resource == null || (!resource.exists())) { - resp.sendError(HttpResponse.__404_Not_Found); + resp.sendError(404); } else { - String base = URI.addPaths(req.getRequestURI(), "/"); + String base = URIUtil.addPaths(req.getRequestURI(), "/"); String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null); if (listing != null) resp.getWriter().write(listing); else // shouldn't happen - resp.sendError(HttpResponse.__404_Not_Found); + resp.sendError(404); } } else { super.service(req, resp); @@ -1680,7 +1684,7 @@ public class I2PSnarkServlet extends Default { StringBuilder buf=new StringBuilder(4096); buf.append(DOCTYPE + ""); - 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) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/RunStandalone.java b/apps/i2psnark/java/src/org/klomp/snark/web/RunStandalone.java index 2880676a25..2bf9124101 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/RunStandalone.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/RunStandalone.java @@ -31,6 +31,8 @@ public class RunStandalone { if (!workDirCreated) System.err.println("ERROR: Unable to create Jetty temporary work directory"); + throw new RuntimeException("unsupported"); +/**** try { _server = new Server("jetty-i2psnark.xml"); // just blow up NPE if we don't have a context @@ -39,13 +41,17 @@ public class RunStandalone { } catch (Exception e) { e.printStackTrace(); } +****/ } public void stop() { + throw new RuntimeException("unsupported"); +/**** try { _server.stop(); } catch (InterruptedException ie) { ie.printStackTrace(); } +****/ } } diff --git a/apps/i2ptunnel/java/build.xml b/apps/i2ptunnel/java/build.xml index 1778ffb872..e1c88bcce9 100644 --- a/apps/i2ptunnel/java/build.xml +++ b/apps/i2ptunnel/java/build.xml @@ -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> diff --git a/apps/jetty/build.xml b/apps/jetty/build.xml index e686e364a7..0b346bdee1 100644 --- a/apps/jetty/build.xml +++ b/apps/jetty/build.xml @@ -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}" /> diff --git a/apps/jetty/java/src/org/mortbay/http/HttpContext.java b/apps/jetty/java/src/org/mortbay/http/HttpContext.java deleted file mode 100644 index 1ae1a08b6e..0000000000 --- a/apps/jetty/java/src/org/mortbay/http/HttpContext.java +++ /dev/null @@ -1,2198 +0,0 @@ -// ======================================================================== -// $Id: HttpContext.java,v 1.136 2006/02/21 09:47:43 gregwilkins Exp $ -// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== - -package org.mortbay.http; - -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.Socket; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.UnknownHostException; -import java.security.Permission; -import java.security.PermissionCollection; -import java.security.Permissions; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.StringTokenizer; - -import org.apache.commons.logging.Log; -import org.mortbay.log.LogFactory; -import org.mortbay.http.ResourceCache.ResourceMetaData; -import org.mortbay.http.handler.ErrorPageHandler; -import org.mortbay.util.Container; -import org.mortbay.util.EventProvider; -import org.mortbay.util.IO; -import org.mortbay.util.LazyList; -import org.mortbay.util.LifeCycle; -import org.mortbay.util.LogSupport; -import org.mortbay.util.MultiException; -import org.mortbay.util.Resource; -import org.mortbay.util.URI; - - -/* ------------------------------------------------------------ */ -/** Context for a collection of HttpHandlers. - * HTTP Context provides an ordered container for HttpHandlers - * that share the same path prefix, filebase, resourcebase and/or - * classpath. - * <p> - * A HttpContext is analagous to a ServletContext in the - * Servlet API, except that it may contain other types of handler - * other than servlets. - * <p> - * A ClassLoader is created for the context and it uses - * Thread.currentThread().getContextClassLoader(); as it's parent loader. - * The class loader is initialized during start(), when a derived - * context calls initClassLoader() or on the first call to loadClass() - * <p> - * - * <B>Note. that order is important when configuring a HttpContext. - * For example, if resource serving is enabled before servlets, then resources - * take priority.</B> - * - * @see HttpServer - * @see HttpHandler - * @see org.mortbay.jetty.servlet.ServletHttpContext - * @version $Id: HttpContext.java,v 1.136 2006/02/21 09:47:43 gregwilkins Exp $ - * @author Greg Wilkins (gregw) - */ -public class HttpContext extends Container - implements LifeCycle, - HttpHandler, - EventProvider, - Serializable -{ - private static Log log = LogFactory.getLog(HttpContext.class); - - /* ------------------------------------------------------------ */ - /** File class path attribute. - * If this name is set as a context init parameter, then the attribute - * name given will be used to set the file classpath for the context as a - * context attribute. - */ - public final static String __fileClassPathAttr= - "org.mortbay.http.HttpContext.FileClassPathAttribute"; - - public final static String __ErrorHandler= - "org.mortbay.http.ErrorHandler"; - - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - // These attributes are serialized by WebApplicationContext, which needs - // to be updated if you add to these - private String _contextPath; - private List _vhosts=new ArrayList(2); - private List _hosts=new ArrayList(2); - private List _handlers=new ArrayList(3); - private Map _attributes = new HashMap(3); - private boolean _redirectNullPath=true; - private boolean _statsOn=false; - private PermissionCollection _permissions; - private boolean _classLoaderJava2Compliant=true; - private ResourceCache _resources; - private String[] _systemClasses=new String [] {"java.","javax.servlet.","javax.xml.","org.mortbay.","org.xml.","org.w3c.","org.apache.commons.logging."}; - private String[] _serverClasses = new String[] {"-org.mortbay.http.PathMap","-org.mortbay.jetty.servlet.Invoker","-org.mortbay.jetty.servlet.JSR154Filter","-org.mortbay.jetty.servlet.Default","org.mortbay.jetty.Server","org.mortbay.http.","org.mortbay.start.","org.mortbay.stop."}; - - /* ------------------------------------------------------------ */ - private String _contextName; - private String _classPath; - private Map _initParams = new HashMap(11); - private UserRealm _userRealm; - private String _realmName; - private PathMap _constraintMap=new PathMap(); - private Authenticator _authenticator; - private RequestLog _requestLog; - - - private String[] _welcomes= - { - "welcome.html", - "index.html", - "index.htm", - "index.jsp" - }; - - - /* ------------------------------------------------------------ */ - private transient boolean _gracefulStop; - private transient ClassLoader _parent; - private transient ClassLoader _loader; - private transient HttpServer _httpServer; - private transient File _tmpDir; - private transient HttpHandler[] _handlersArray; - private transient String[] _vhostsArray; - - - /* ------------------------------------------------------------ */ - transient Object _statsLock=new Object[0]; - transient long _statsStartedAt; - transient int _requests; - transient int _requestsActive; - transient int _requestsActiveMax; - transient int _responses1xx; // Informal - transient int _responses2xx; // Success - transient int _responses3xx; // Redirection - transient int _responses4xx; // Client Error - transient int _responses5xx; // Server Error - - - /* ------------------------------------------------------------ */ - /** Constructor. - */ - public HttpContext() - { - setAttribute(__ErrorHandler, new ErrorPageHandler()); - _resources=new ResourceCache(); - addComponent(_resources); - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param httpServer - * @param contextPathSpec - */ - public HttpContext(HttpServer httpServer,String contextPathSpec) - { - this(); - setHttpServer(httpServer); - setContextPath(contextPathSpec); - } - - /* ------------------------------------------------------------ */ - private void readObject(java.io.ObjectInputStream in) - throws IOException, ClassNotFoundException - { - in.defaultReadObject(); - _statsLock=new Object[0]; - getHandlers(); - for (int i=0;i<_handlersArray.length;i++) - _handlersArray[i].initialize(this); - } - - /* ------------------------------------------------------------ */ - /** Get the ThreadLocal HttpConnection. - * Get the HttpConnection for current thread, if any. This method is - * not static in order to control access. - * @return HttpConnection for this thread. - */ - public HttpConnection getHttpConnection() - { - return HttpConnection.getHttpConnection(); - } - - /* ------------------------------------------------------------ */ - void setHttpServer(HttpServer httpServer) - { - _httpServer=httpServer; - _contextName=null; - - } - - /* ------------------------------------------------------------ */ - public HttpServer getHttpServer() - { - return _httpServer; - } - - /* ------------------------------------------------------------ */ - public void setStopGracefully(boolean graceful) - { - _gracefulStop=graceful; - } - - /* ------------------------------------------------------------ */ - public boolean getStopGracefully() - { - return _gracefulStop; - } - - - /* ------------------------------------------------------------ */ - public static String canonicalContextPathSpec(String contextPathSpec) - { - // check context path - if (contextPathSpec==null || - contextPathSpec.indexOf(',')>=0 || - contextPathSpec.startsWith("*")) - throw new IllegalArgumentException ("Illegal context spec:"+contextPathSpec); - - if(!contextPathSpec.startsWith("/")) - contextPathSpec='/'+contextPathSpec; - - if (contextPathSpec.length()>1) - { - if (contextPathSpec.endsWith("/")) - contextPathSpec+="*"; - else if (!contextPathSpec.endsWith("/*")) - contextPathSpec+="/*"; - } - - return contextPathSpec; - } - - /* ------------------------------------------------------------ */ - public void setContextPath(String contextPathSpec) - { - if (_httpServer!=null) - _httpServer.removeMappings(this); - - contextPathSpec=canonicalContextPathSpec(contextPathSpec); - - if (contextPathSpec.length()>1) - _contextPath=contextPathSpec.substring(0,contextPathSpec.length()-2); - else - _contextPath="/"; - - _contextName=null; - - if (_httpServer!=null) - _httpServer.addMappings(this); - } - - - /* ------------------------------------------------------------ */ - /** - * @return The context prefix - */ - public String getContextPath() - { - return _contextPath; - } - - - /* ------------------------------------------------------------ */ - /** Add a virtual host alias to this context. - * @see #setVirtualHosts - * @param hostname A hostname. A null host name means any hostname is - * acceptable. Host names may String representation of IP addresses. - */ - public void addVirtualHost(String hostname) - { - // Note that null hosts are also added. - if (!_vhosts.contains(hostname)) - { - _vhosts.add(hostname); - _contextName=null; - - if (_httpServer!=null) - { - if (_vhosts.size()==1) - _httpServer.removeMapping(null,this); - _httpServer.addMapping(hostname,this); - } - _vhostsArray=null; - } - } - - /* ------------------------------------------------------------ */ - /** remove a virtual host alias to this context. - * @see #setVirtualHosts - * @param hostname A hostname. A null host name means any hostname is - * acceptable. Host names may String representation of IP addresses. - */ - public void removeVirtualHost(String hostname) - { - // Note that null hosts are also added. - if (_vhosts.remove(hostname)) - { - _contextName=null; - if (_httpServer!=null) - { - _httpServer.removeMapping(hostname,this); - if (_vhosts.size()==0) - _httpServer.addMapping(null,this); - } - _vhostsArray=null; - } - } - - /* ------------------------------------------------------------ */ - /** Set the virtual hosts for the context. - * Only requests that have a matching host header or fully qualified - * URL will be passed to that context with a virtual host name. - * A context with no virtual host names or a null virtual host name is - * available to all requests that are not served by a context with a - * matching virtual host name. - * @param hosts Array of virtual hosts that this context responds to. A - * null host name or null/empty array means any hostname is acceptable. - * Host names may String representation of IP addresses. - */ - public void setVirtualHosts(String[] hosts) - { - List old = new ArrayList(_vhosts); - - if (hosts!=null) - { - for (int i=0;i<hosts.length;i++) - { - boolean existing=old.remove(hosts[i]); - if (!existing) - addVirtualHost(hosts[i]); - } - } - - for (int i=0;i<old.size();i++) - removeVirtualHost((String)old.get(i)); - } - - /* ------------------------------------------------------------ */ - /** Get the virtual hosts for the context. - * Only requests that have a matching host header or fully qualified - * URL will be passed to that context with a virtual host name. - * A context with no virtual host names or a null virtual host name is - * available to all requests that are not served by a context with a - * matching virtual host name. - * @return Array of virtual hosts that this context responds to. A - * null host name or empty array means any hostname is acceptable. - * Host names may be String representation of IP addresses. - */ - public String[] getVirtualHosts() - { - if (_vhostsArray!=null) - return _vhostsArray; - if (_vhosts==null) - _vhostsArray=new String[0]; - else - { - _vhostsArray=new String[_vhosts.size()]; - _vhostsArray=(String[])_vhosts.toArray(_vhostsArray); - } - return _vhostsArray; - } - - - /* ------------------------------------------------------------ */ - /** Set the hosts for the context. - * Set the real hosts that this context will accept requests for. - * If not null or empty, then only requests from HttpListeners for hosts - * in this array are accepted by this context. - * Unlike virutal hosts, this value is not used by HttpServer for - * matching a request to a context. - */ - public void setHosts(String[] hosts) - throws UnknownHostException - { - if (hosts==null || hosts.length==0) - _hosts=null; - else - { - _hosts=new ArrayList(); - for (int i=0;i<hosts.length;i++) - if (hosts[i]!=null) - _hosts.add(InetAddress.getByName(hosts[i])); - } - - } - - /* ------------------------------------------------------------ */ - /** Get the hosts for the context. - */ - public String[] getHosts() - { - if (_hosts==null || _hosts.size()==0) - return null; - String[] hosts=new String[_hosts.size()]; - for (int i=0;i<hosts.length;i++) - { - InetAddress a = (InetAddress)_hosts.get(i); - if (a!=null) - hosts[i]=a.getHostName(); - } - return hosts; - } - - - /* ------------------------------------------------------------ */ - /** Set system classes. - * System classes cannot be overriden by context classloaders. - * @param classes array of classname Strings. Names ending with '.' are treated as package names. Names starting with '-' are treated as - * negative matches and must be listed before any enclosing packages. - */ - public void setSystemClasses(String[] classes) - { - _systemClasses=classes; - } - - /* ------------------------------------------------------------ */ - /** Get system classes. - * System classes cannot be overriden by context classloaders. - * @return array of classname Strings. Names ending with '.' are treated as package names. Names starting with '-' are treated as - * negative matches and must be listed before any enclosing packages. Null if not set. - */ - public String[] getSystemClasses() - { - return _systemClasses; - } - - - /* ------------------------------------------------------------ */ - /** Set system classes. - * Servers classes cannot be seen by context classloaders. - * @param classes array of classname Strings. Names ending with '.' are treated as package names. Names starting with '-' are treated as - * negative matches and must be listed before any enclosing packages. - */ - public void setServerClasses(String[] classes) - { - _serverClasses=classes; - } - - /* ------------------------------------------------------------ */ - /** Get system classes. - * System classes cannot be seen by context classloaders. - * @return array of classname Strings. Names ending with '.' are treated as package names. Names starting with '-' are treated as - * negative matches and must be listed before any enclosing packages. Null if not set. - */ - public String[] getServerClasses() - { - return _serverClasses; - } - - - /* ------------------------------------------------------------ */ - public void setHandlers(HttpHandler[] handlers) - { - List old = new ArrayList(_handlers); - - if (handlers!=null) - { - for (int i=0;i<handlers.length;i++) - { - boolean existing=old.remove(handlers[i]); - if (!existing) - addHandler(handlers[i]); - } - } - - for (int i=0;i<old.size();i++) - removeHandler((HttpHandler)old.get(i)); - } - - /* ------------------------------------------------------------ */ - /** Get all handlers. - * @return List of all HttpHandlers - */ - public HttpHandler[] getHandlers() - { - if (_handlersArray!=null) - return _handlersArray; - if (_handlers==null) - _handlersArray=new HttpHandler[0]; - else - { - _handlersArray=new HttpHandler[_handlers.size()]; - _handlersArray=(HttpHandler[])_handlers.toArray(_handlersArray); - } - return _handlersArray; - } - - - /* ------------------------------------------------------------ */ - /** Add a handler. - * @param i The position in the handler list - * @param handler The handler. - */ - public synchronized void addHandler(int i,HttpHandler handler) - { - _handlers.add(i,handler); - _handlersArray=null; - - HttpContext context = handler.getHttpContext(); - if (context==null) - handler.initialize(this); - else if (context!=this) - throw new IllegalArgumentException("Handler in another HttpContext"); - addComponent(handler); - } - - /* ------------------------------------------------------------ */ - /** Add a HttpHandler to the context. - * @param handler - */ - public synchronized void addHandler(HttpHandler handler) - { - addHandler(_handlers.size(),handler); - } - - /* ------------------------------------------------------------ */ - /** Get handler index. - * @param handler instance - * @return Index of handler in context or -1 if not found. - */ - public int getHandlerIndex(HttpHandler handler) - { - for (int h=0;h<_handlers.size();h++) - { - if ( handler == _handlers.get(h)) - return h; - } - return -1; - } - - /* ------------------------------------------------------------ */ - /** Get a handler by class. - * @param handlerClass - * @return The first handler that is an instance of the handlerClass - */ - public synchronized HttpHandler getHandler(Class handlerClass) - { - for (int h=0;h<_handlers.size();h++) - { - HttpHandler handler = (HttpHandler)_handlers.get(h); - if (handlerClass.isInstance(handler)) - return handler; - } - return null; - } - - /* ------------------------------------------------------------ */ - /** Remove a handler. - * The handler must be stopped before being removed. - * @param i index of handler - */ - public synchronized HttpHandler removeHandler(int i) - { - HttpHandler handler = _handlersArray[i]; - if (handler.isStarted()) - try{handler.stop();} catch (InterruptedException e){log.warn(LogSupport.EXCEPTION,e);} - _handlers.remove(i); - _handlersArray=null; - removeComponent(handler); - return handler; - } - - /* ------------------------------------------------------------ */ - /** Remove a handler. - * The handler must be stopped before being removed. - */ - public synchronized void removeHandler(HttpHandler handler) - { - if (handler.isStarted()) - try{handler.stop();} catch (InterruptedException e){log.warn(LogSupport.EXCEPTION,e);} - _handlers.remove(handler); - removeComponent(handler); - _handlersArray=null; - } - - - /* ------------------------------------------------------------ */ - /** Set context init parameter. - * Init Parameters differ from attributes as they can only - * have string values, servlets cannot set them and they do - * not have a package scoped name space. - * @param param param name - * @param value param value or null - */ - public void setInitParameter(String param, String value) - { - _initParams.put(param,value); - } - - /* ------------------------------------------------------------ */ - /** Get context init parameter. - * @param param param name - * @return param value or null - */ - public String getInitParameter(String param) - { - return (String)_initParams.get(param); - } - - /* ------------------------------------------------------------ */ - /** Get context init parameter. - * @return Enumeration of names - */ - public Enumeration getInitParameterNames() - { - return Collections.enumeration(_initParams.keySet()); - } - - /* ------------------------------------------------------------ */ - /** Set a context attribute. - * @param name attribute name - * @param value attribute value - */ - public synchronized void setAttribute(String name, Object value) - { - _attributes.put(name,value); - } - - /* ------------------------------------------------------------ */ - /** - * @param name attribute name - * @return attribute value or null - */ - public Object getAttribute(String name) - { - return _attributes.get(name); - } - - /* ------------------------------------------------------------ */ - /** - */ - public Map getAttributes() - { - return _attributes; - } - - /* ------------------------------------------------------------ */ - /** - */ - public void setAttributes(Map attributes) - { - _attributes=attributes; - } - - /* ------------------------------------------------------------ */ - /** - * @return enumaration of names. - */ - public Enumeration getAttributeNames() - { - return Collections.enumeration(_attributes.keySet()); - } - - /* ------------------------------------------------------------ */ - /** - * @param name attribute name - */ - public synchronized void removeAttribute(String name) - { - _attributes.remove(name); - } - - - /* ------------------------------------------------------------ */ - public void flushCache() - { - _resources.flushCache(); - } - - /* ------------------------------------------------------------ */ - public String[] getWelcomeFiles() - { - return _welcomes; - } - - /* ------------------------------------------------------------ */ - public void setWelcomeFiles(String[] welcomes) - { - if (welcomes==null) - _welcomes=new String[0]; - else - _welcomes=welcomes; - } - - /* ------------------------------------------------------------ */ - public void addWelcomeFile(String welcomeFile) - { - if (welcomeFile.startsWith("/") || - welcomeFile.startsWith(java.io.File.separator) || - welcomeFile.endsWith("/") || - welcomeFile.endsWith(java.io.File.separator)) - log.warn("Invalid welcome file: "+welcomeFile); - List list = new ArrayList(Arrays.asList(_welcomes)); - list.add(welcomeFile); - _welcomes=(String[])list.toArray(_welcomes); - } - - /* ------------------------------------------------------------ */ - public void removeWelcomeFile(String welcomeFile) - { - List list = new ArrayList(Arrays.asList(_welcomes)); - list.remove(welcomeFile); - _welcomes=(String[])list.toArray(_welcomes); - } - - /* ------------------------------------------------------------ */ - public String getWelcomeFile(Resource resource) - throws IOException - { - if (!resource.isDirectory()) - return null; - - for (int i=0;i<_welcomes.length;i++) - { - Resource welcome=resource.addPath(_welcomes[i]); - if (welcome.exists()) - return _welcomes[i]; - } - - return null; - } - - - /* ------------------------------------------------------------ */ - /** Get the context classpath. - * This method only returns the paths that have been set for this - * context and does not include any paths from a parent or the - * system classloader. - * Note that this may not be a legal javac classpath. - * @return a comma or ';' separated list of class - * resources. These may be jar files, directories or URLs to jars - * or directories. - * @see #getFileClassPath() - */ - public String getClassPath() - { - return _classPath; - } - - /* ------------------------------------------------------------ */ - /** Get the file classpath of the context. - * This method makes a best effort to return a complete file - * classpath for the context. - * It is obtained by walking the classloader hierarchy and looking for - * URLClassLoaders. The system property java.class.path is also checked for - * file elements not already found in the loader hierarchy. - * @return Path of files and directories for loading classes. - * @exception IllegalStateException HttpContext.initClassLoader - * has not been called. - */ - public String getFileClassPath() - throws IllegalStateException - { - - ClassLoader loader = getClassLoader(); - if (loader==null) - throw new IllegalStateException("Context classloader not initialized"); - - LinkedList paths =new LinkedList(); - LinkedList loaders=new LinkedList(); - - // Walk the loader hierarchy - while (loader !=null) - { - loaders.add(0,loader); - loader = loader.getParent(); - } - - // Try to handle java2compliant modes - loader=getClassLoader(); - if (loader instanceof ContextLoader && !((ContextLoader)loader).isJava2Compliant()) - { - loaders.remove(loader); - loaders.add(0,loader); - } - - for (int i=0;i<loaders.size();i++) - { - loader=(ClassLoader)loaders.get(i); - - if (log.isDebugEnabled()) log.debug("extract paths from "+loader); - if (loader instanceof URLClassLoader) - { - URL[] urls = ((URLClassLoader)loader).getURLs(); - for (int j=0;urls!=null && j<urls.length;j++) - { - try - { - Resource path = Resource.newResource(urls[j]); - if (log.isTraceEnabled()) log.trace("path "+path); - File file = path.getFile(); - if (file!=null) - paths.add(file.getAbsolutePath()); - } - catch(Exception e) - { - LogSupport.ignore(log,e); - } - } - } - } - - // Add the system classpath elements from property. - String jcp=System.getProperty("java.class.path"); - if (jcp!=null) - { - StringTokenizer tok=new StringTokenizer(jcp,File.pathSeparator); - while (tok.hasMoreTokens()) - { - String path=tok.nextToken(); - if (!paths.contains(path)) - { - if(log.isTraceEnabled())log.trace("PATH="+path); - paths.add(path); - } - else - if(log.isTraceEnabled())log.trace("done="+path); - } - } - - StringBuffer buf = new StringBuffer(); - Iterator iter = paths.iterator(); - while(iter.hasNext()) - { - if (buf.length()>0) - buf.append(File.pathSeparator); - buf.append(iter.next().toString()); - } - - if (log.isDebugEnabled()) log.debug("fileClassPath="+buf); - return buf.toString(); - } - - /* ------------------------------------------------------------ */ - /** Sets the class path for the context. - * A class path is only required for a context if it uses classes - * that are not in the system class path. - * @param classPath a comma or ';' separated list of class - * resources. These may be jar files, directories or URLs to jars - * or directories. - */ - public void setClassPath(String classPath) - { - _classPath=classPath; - if (isStarted()) - log.warn("classpath set while started"); - } - - /* ------------------------------------------------------------ */ - /** Add the class path element to the context. - * A class path is only required for a context if it uses classes - * that are not in the system class path. - * @param classPath a comma or ';' separated list of class - * resources. These may be jar files, directories or URLs to jars - * or directories. - */ - public void addClassPath(String classPath) - { - if (_classPath==null || _classPath.length()==0) - _classPath=classPath; - else - _classPath+=","+classPath; - - if (isStarted()) - log.warn("classpath set while started"); - } - - /* ------------------------------------------------------------ */ - /** Add elements to the class path for the context from the jar and zip files found - * in the specified resource. - * @param lib the resource that contains the jar and/or zip files. - * @param append true if the classpath entries are to be appended to any - * existing classpath, or false if they replace the existing classpath. - * @see #setClassPath(String) - */ - public void addClassPaths(Resource lib) - { - if (isStarted()) - log.warn("classpaths set while started"); - - if (lib.exists() && lib.isDirectory()) - { - String[] files=lib.list(); - for (int f=0;files!=null && f<files.length;f++) - { - try { - Resource fn=lib.addPath(files[f]); - String fnlc=fn.getName().toLowerCase(); - if (fnlc.endsWith(".jar") || fnlc.endsWith(".zip")) - { - addClassPath(fn.toString()); - } - } - catch (Exception ex) - { - log.warn(LogSupport.EXCEPTION,ex); - } - } - } - } - - /* ------------------------------------------------------------ */ - /** Get Java2 compliant classloading. - * @return If true, the class loader will conform to the java 2 - * specification and delegate all loads to the parent classloader. If - * false, the context classloader only delegate loads for system classes - * or classes that it can't find itself. - */ - public boolean isClassLoaderJava2Compliant() - { - return _classLoaderJava2Compliant; - } - - /* ------------------------------------------------------------ */ - /** Set Java2 compliant classloading. - * @param compliant If true, the class loader will conform to the java 2 - * specification and delegate all loads to the parent classloader. If - * false, the context classloader only delegate loads for system classes - * or classes that it can't find itself. - */ - public void setClassLoaderJava2Compliant(boolean compliant) - { - _classLoaderJava2Compliant = compliant; - if (_loader!=null && (_loader instanceof ContextLoader)) - ((ContextLoader)_loader).setJava2Compliant(compliant); - } - - /* ------------------------------------------------------------ */ - /** Set temporary directory for context. - * The javax.servlet.context.tempdir attribute is also set. - * @param dir Writable temporary directory. - */ - public void setTempDirectory(File dir) - { - if (isStarted()) - throw new IllegalStateException("Started"); - - if (dir!=null) - { - try{dir=new File(dir.getCanonicalPath());} - catch (IOException e){log.warn(LogSupport.EXCEPTION,e);} - } - - if (dir!=null && !dir.exists()) - { - dir.mkdir(); - dir.deleteOnExit(); - } - - if (dir!=null && ( !dir.exists() || !dir.isDirectory() || !dir.canWrite())) - throw new IllegalArgumentException("Bad temp directory: "+dir); - - _tmpDir=dir; - setAttribute("javax.servlet.context.tempdir",_tmpDir); - } - - /* ------------------------------------------------------------ */ - /** Get Context temporary directory. - * A tempory directory is generated if it has not been set. The - * "javax.servlet.context.tempdir" attribute is consulted and if - * not set, the host, port and context are used to generate a - * directory within the JVMs temporary directory. - * - * Patched for IPV6 support in I2P to replace ':' in the dir name which - * Windows can't handle. - * - * @return Temporary directory as a File. - */ - public File getTempDirectory() - { - if (_tmpDir!=null) - return _tmpDir; - - // Initialize temporary directory - // - // I'm afraid that this is very much black magic. - // but if you can think of better.... - Object t = getAttribute("javax.servlet.context.tempdir"); - - if (t!=null && (t instanceof File)) - { - _tmpDir=(File)t; - if (_tmpDir.isDirectory() && _tmpDir.canWrite()) - return _tmpDir; - } - - if (t!=null && (t instanceof String)) - { - try - { - _tmpDir=new File((String)t); - - if (_tmpDir.isDirectory() && _tmpDir.canWrite()) - { - if(log.isDebugEnabled())log.debug("Converted to File "+_tmpDir+" for "+this); - setAttribute("javax.servlet.context.tempdir",_tmpDir); - return _tmpDir; - } - } - catch(Exception e) - { - log.warn(LogSupport.EXCEPTION,e); - } - } - - // No tempdir so look for a WEB-INF/work directory to use as tempDir base - File work=null; - try - { - work=new File(System.getProperty("jetty.home"),"work"); - if (!work.exists() || !work.canWrite() || !work.isDirectory()) - work=null; - } - catch(Exception e) - { - LogSupport.ignore(log,e); - } - - // No tempdir set so make one! - try - { - HttpListener httpListener=_httpServer.getListeners()[0]; - - String vhost = null; - for (int h=0;vhost==null && _vhosts!=null && h<_vhosts.size();h++) - vhost=(String)_vhosts.get(h); - String host=httpListener.getHost(); - String temp="Jetty_"+ - (host==null?"":host)+ - "_"+ - httpListener.getPort()+ - "_"+ - (vhost==null?"":vhost)+ - getContextPath(); - - temp=temp.replace('/','_'); - temp=temp.replace('.','_'); - temp=temp.replace('\\','_'); - temp=temp.replace(':','_'); - - - if (work!=null) - _tmpDir=new File(work,temp); - else - { - _tmpDir=new File(System.getProperty("java.io.tmpdir"),temp); - - if (_tmpDir.exists()) - { - if(log.isDebugEnabled())log.debug("Delete existing temp dir "+_tmpDir+" for "+this); - if (!IO.delete(_tmpDir)) - { - if(log.isDebugEnabled())log.debug("Failed to delete temp dir "+_tmpDir); - } - - if (_tmpDir.exists()) - { - String old=_tmpDir.toString(); - _tmpDir=File.createTempFile(temp+"_",""); - if (_tmpDir.exists()) - _tmpDir.delete(); - log.warn("Can't reuse "+old+", using "+_tmpDir); - } - } - } - - if (!_tmpDir.exists()) - _tmpDir.mkdir(); - if (work==null) - _tmpDir.deleteOnExit(); - if(log.isDebugEnabled())log.debug("Created temp dir "+_tmpDir+" for "+this); - } - catch(Exception e) - { - _tmpDir=null; - LogSupport.ignore(log,e); - } - - if (_tmpDir==null) - { - try{ - // that didn't work, so try something simpler (ish) - _tmpDir=File.createTempFile("JettyContext",""); - if (_tmpDir.exists()) - _tmpDir.delete(); - _tmpDir.mkdir(); - _tmpDir.deleteOnExit(); - if(log.isDebugEnabled())log.debug("Created temp dir "+_tmpDir+" for "+this); - } - catch(IOException e) - { - log.fatal(e); System.exit(1); - } - } - - setAttribute("javax.servlet.context.tempdir",_tmpDir); - return _tmpDir; - } - - - - /* ------------------------------------------------------------ */ - /** Set ClassLoader. - * @param loader The loader to be used by this context. - */ - public synchronized void setClassLoader(ClassLoader loader) - { - if (isStarted()) - throw new IllegalStateException("Started"); - _loader=loader; - } - - - /* ------------------------------------------------------------ */ - /** Get the classloader. - * If no classloader has been set and the context has been loaded - * normally, then null is returned. - * If no classloader has been set and the context was loaded from - * a classloader, that loader is returned. - * If a classloader has been set and no classpath has been set then - * the set classloader is returned. - * If a classloader and a classpath has been set, then a new - * URLClassloader initialized on the classpath with the set loader as a - * partent is return. - * @return Classloader or null. - */ - public synchronized ClassLoader getClassLoader() - { - return _loader; - } - - /* ------------------------------------------------------------ */ - /** Set Parent ClassLoader. - * By default the parent loader is the thread context classloader - * of the thread that calls initClassLoader. If setClassLoader is - * called, then the parent is ignored. - * @param loader The class loader to use for the parent loader of - * the context classloader. - */ - public synchronized void setParentClassLoader(ClassLoader loader) - { - if (isStarted()) - throw new IllegalStateException("Started"); - _parent=loader; - } - - /* ------------------------------------------------------------ */ - public ClassLoader getParentClassLoader() - { - return _parent; - } - - /* ------------------------------------------------------------ */ - /** Initialize the context classloader. - * Initialize the context classloader with the current parameters. - * Any attempts to change the classpath after this call will - * result in a IllegalStateException - * @param forceContextLoader If true, a ContextLoader is always if - * no loader has been set. - */ - protected void initClassLoader(boolean forceContextLoader) - throws MalformedURLException, IOException - { - ClassLoader parent=_parent; - if (_loader==null) - { - // If no parent, then try this threads classes loader as parent - if (parent==null) - parent=Thread.currentThread().getContextClassLoader(); - - // If no parent, then try this classes loader as parent - if (parent==null) - parent=this.getClass().getClassLoader(); - - if(log.isDebugEnabled())log.debug("Init classloader from "+_classPath+ - ", "+parent+" for "+this); - - if (forceContextLoader || _classPath!=null || _permissions!=null) - { - ContextLoader loader=new ContextLoader(this,_classPath,parent,_permissions); - loader.setJava2Compliant(_classLoaderJava2Compliant); - _loader=loader; - } - else - _loader=parent; - } - } - - /* ------------------------------------------------------------ */ - public synchronized Class loadClass(String className) - throws ClassNotFoundException - { - if (_loader==null) - { - try{initClassLoader(false);} - catch(Exception e) - { - log.warn(LogSupport.EXCEPTION,e); - return null; - } - } - - if (className==null) - return null; - - if (_loader == null) - return Class.forName(className); - return _loader.loadClass(className); - } - - /* ------------------------------------------------------------ */ - /** Set the realm name. - * @param realmName The name to use to retrieve the actual realm - * from the HttpServer - */ - public void setRealmName(String realmName) - { - _realmName=realmName; - } - - /* ------------------------------------------------------------ */ - public String getRealmName() - { - return _realmName; - } - - /* ------------------------------------------------------------ */ - /** Set the realm. - */ - public void setRealm(UserRealm realm) - { - _userRealm=realm; - } - - /* ------------------------------------------------------------ */ - public UserRealm getRealm() - { - return _userRealm; - } - - /* ------------------------------------------------------------ */ - public Authenticator getAuthenticator() - { - return _authenticator; - } - - /* ------------------------------------------------------------ */ - public void setAuthenticator(Authenticator authenticator) - { - _authenticator=authenticator; - } - - /* ------------------------------------------------------------ */ - public void addSecurityConstraint(String pathSpec, SecurityConstraint sc) - { - Object scs = _constraintMap.get(pathSpec); - scs = LazyList.add(scs,sc); - _constraintMap.put(pathSpec,scs); - - if(log.isDebugEnabled())log.debug("added "+sc+" at "+pathSpec); - } - - /* ------------------------------------------------------------ */ - public void clearSecurityConstraints() - { - _constraintMap.clear(); - } - - /* ------------------------------------------------------------ */ - public boolean checkSecurityConstraints( - String pathInContext, - HttpRequest request, - HttpResponse response) - throws HttpException, IOException - { - UserRealm realm= getRealm(); - - List scss= _constraintMap.getMatches(pathInContext); - String pattern=null; - if (scss != null && !scss.isEmpty()) - { - Object constraints= null; - - // for each path match - // Add only constraints that have the correct method - // break if the matching pattern changes. This allows only - // constraints with matching pattern and method to be combined. - loop: - for (int m= 0; m < scss.size(); m++) - { - Map.Entry entry= (Map.Entry)scss.get(m); - Object scs= entry.getValue(); - String p=(String)entry.getKey(); - for (int c=0;c<LazyList.size(scs);c++) - { - SecurityConstraint sc=(SecurityConstraint)LazyList.get(scs,c); - if (!sc.forMethod(request.getMethod())) - continue; - - if (pattern!=null && !pattern.equals(p)) - break loop; - pattern=p; - constraints= LazyList.add(constraints, sc); - } - } - - return SecurityConstraint.check( - LazyList.getList(constraints), - _authenticator, - realm, - pathInContext, - request, - response); - } - request.setUserPrincipal(HttpRequest.__NOT_CHECKED); - return true; - } - - /* ------------------------------------------------------------ */ - /** Set null path redirection. - * @param b if true a /context request will be redirected to - * /context/ if there is not path in the context. - */ - public void setRedirectNullPath(boolean b) - { - _redirectNullPath=b; - } - - /* ------------------------------------------------------------ */ - /** - * @return True if a /context request is redirected to /context/ if - * there is not path in the context. - */ - public boolean isRedirectNullPath() - { - return _redirectNullPath; - } - - - - /* ------------------------------------------------------------ */ - /** Set the permissions to be used for this context. - * The collection of permissions set here are used for all classes - * loaded by this context. This is simpler that creating a - * security policy file, as not all code sources may be statically - * known. - * @param permissions - */ - public void setPermissions(PermissionCollection permissions) - { - _permissions=permissions; - } - - /* ------------------------------------------------------------ */ - /** Get the permissions to be used for this context. - */ - public PermissionCollection getPermissions() - { - return _permissions; - } - - /* ------------------------------------------------------------ */ - /** Add a permission to this context. - * The collection of permissions set here are used for all classes - * loaded by this context. This is simpler that creating a - * security policy file, as not all code sources may be statically - * known. - * @param permission - */ - public void addPermission(Permission permission) - { - if (_permissions==null) - _permissions=new Permissions(); - _permissions.add(permission); - } - - /* ------------------------------------------------------------ */ - /** Handler request. - * Determine the path within the context and then call - * handle(pathInContext,request,response). - * @param request - * @param response - * @return True if the request has been handled. - * @exception HttpException - * @exception IOException - */ - public void handle(HttpRequest request, - HttpResponse response) - throws HttpException, IOException - { - if (!isStarted() || _gracefulStop) - return; - - // reject requests by real host - if (_hosts!=null && _hosts.size()>0) - { - Object o = request.getHttpConnection().getConnection(); - if (o instanceof Socket) - { - Socket s=(Socket)o; - if (!_hosts.contains(s.getLocalAddress())) - { - if(log.isDebugEnabled())log.debug(s.getLocalAddress()+" not in "+_hosts); - return; - } - } - } - - // handle stats - if (_statsOn) - { - synchronized(_statsLock) - { - _requests++; - _requestsActive++; - if (_requestsActive>_requestsActiveMax) - _requestsActiveMax=_requestsActive; - } - } - - String pathInContext = URI.canonicalPath(request.getPath()); - if (pathInContext==null) - { - // Must be a bad request. - throw new HttpException(HttpResponse.__400_Bad_Request); - } - - if (_contextPath.length()>1) - pathInContext=pathInContext.substring(_contextPath.length()); - - if (_redirectNullPath && (pathInContext==null || - pathInContext.length()==0)) - { - StringBuffer buf=request.getRequestURL(); - buf.append("/"); - String q=request.getQuery(); - if (q!=null&&q.length()!=0) - buf.append("?"+q); - - response.sendRedirect(buf.toString()); - if (log.isDebugEnabled()) - log.debug(this+" consumed all of path "+ - request.getPath()+ - ", redirect to "+buf.toString()); - return; - } - - String pathParams=null; - int semi = pathInContext.lastIndexOf(';'); - if (semi>=0) - { - int pl = pathInContext.length()-semi; - String ep=request.getEncodedPath(); - if(';'==ep.charAt(ep.length()-pl)) - { - pathParams=pathInContext.substring(semi+1); - pathInContext=pathInContext.substring(0,semi); - } - } - - try - { - handle(pathInContext,pathParams,request,response); - } - finally - { - if (_userRealm!=null && request.hasUserPrincipal()) - _userRealm.disassociate(request.getUserPrincipal()); - } - } - - /* ------------------------------------------------------------ */ - /** Handler request. - * Call each HttpHandler until request is handled. - * @param pathInContext Path in context - * @param pathParams Path parameters such as encoded Session ID - * @param request - * @param response - * @return True if the request has been handled. - * @exception HttpException - * @exception IOException - */ - public void handle(String pathInContext, - String pathParams, - HttpRequest request, - HttpResponse response) - throws HttpException, IOException - { - Object old_scope= null; - try - { - old_scope= enterContextScope(request,response); - HttpHandler[] handlers= getHandlers(); - for (int k= 0; k < handlers.length; k++) - { - HttpHandler handler= handlers[k]; - if (handler == null) - { - handlers= getHandlers(); - k= -1; - continue; - } - if (!handler.isStarted()) - { - if (log.isDebugEnabled()) - log.debug(handler + " not started in " + this); - continue; - } - if (log.isDebugEnabled()) - log.debug("Handler " + handler); - handler.handle(pathInContext, pathParams, request, response); - if (request.isHandled()) - { - if (log.isDebugEnabled()) - log.debug("Handled by " + handler); - return; - } - } - return; - } - finally - { - leaveContextScope(request, response, old_scope); - } - } - - /* ------------------------------------------------------------ */ - /** Enter the context scope. - * This method is called (by handle or servlet dispatchers) to indicate that - * request handling is entering the scope of this context. The opaque scope object - * returned, should be passed to the leaveContextScope method. - */ - public Object enterContextScope(HttpRequest request, HttpResponse response) - { - // Save the thread context loader - Thread thread = Thread.currentThread(); - ClassLoader cl=thread.getContextClassLoader(); - HttpContext c=response.getHttpContext(); - - Scope scope=null; - if (cl!=HttpContext.class.getClassLoader() || c!=null) - { - scope=new Scope(); - scope._classLoader=cl; - scope._httpContext=c; - } - - if (_loader!=null) - thread.setContextClassLoader(_loader); - response.setHttpContext(this); - - return scope; - } - - /* ------------------------------------------------------------ */ - /** Leave the context scope. - * This method is called (by handle or servlet dispatchers) to indicate that - * request handling is leaveing the scope of this context. The opaque scope object - * returned by enterContextScope should be passed in. - */ - public void leaveContextScope(HttpRequest request, HttpResponse response,Object oldScope) - { - if (oldScope==null) - { - Thread.currentThread() - .setContextClassLoader(HttpContext.class.getClassLoader()); - response.setHttpContext(null); - } - else - { - Scope old = (Scope)oldScope; - Thread.currentThread().setContextClassLoader(old._classLoader); - response.setHttpContext(old._httpContext); - } - } - - - /* ------------------------------------------------------------ */ - public String getHttpContextName() - { - if (_contextName==null) - _contextName = (_vhosts.size()>1?(_vhosts.toString()+":"):"")+_contextPath; - return _contextName; - } - - /* ------------------------------------------------------------ */ - public void setHttpContextName(String s) - { - _contextName=s; - } - - /* ------------------------------------------------------------ */ - public String toString() - { - return "HttpContext["+getContextPath()+","+getHttpContextName()+"]"; - } - - /* ------------------------------------------------------------ */ - public String toString(boolean detail) - { - return "HttpContext["+getContextPath()+","+getHttpContextName()+"]" + - (detail?("="+_handlers):""); - } - - - /* ------------------------------------------------------------ */ - protected synchronized void doStart() - throws Exception - { - if (isStarted()) - return; - - if (_httpServer.getServerClasses()!=null) - _serverClasses=_httpServer.getServerClasses(); - if (_httpServer.getSystemClasses()!=null) - _systemClasses=_httpServer.getSystemClasses(); - - _resources.start(); - - statsReset(); - - if (_httpServer==null) - throw new IllegalStateException("No server for "+this); - - // start the context itself - _resources.getMimeMap(); - _resources.getEncodingMap(); - - // Setup realm - if (_userRealm==null && _authenticator!=null) - { - _userRealm=_httpServer.getRealm(_realmName); - if (_userRealm==null) - log.warn("No Realm: "+_realmName); - } - - // setup the context loader - initClassLoader(false); - - // Set attribute if needed - String attr = getInitParameter(__fileClassPathAttr); - if (attr!=null && attr.length()>0) - setAttribute(attr,getFileClassPath()); - - // Start the handlers - Thread thread = Thread.currentThread(); - ClassLoader lastContextLoader=thread.getContextClassLoader(); - try - { - if (_loader!=null) - thread.setContextClassLoader(_loader); - - if (_requestLog!=null) - _requestLog.start(); - - startHandlers(); - } - finally - { - thread.setContextClassLoader(lastContextLoader); - getHandlers(); - } - - } - - /* ------------------------------------------------------------ */ - /** Start the handlers. - * This is called by start after the classloader has been - * initialized and set as the thread context loader. - * It may be specialized to provide custom handling - * before any handlers are started. - * @exception Exception - */ - protected void startHandlers() - throws Exception - { - // Prepare a multi exception - MultiException mx = new MultiException(); - - Iterator handlers = _handlers.iterator(); - while(handlers.hasNext()) - { - HttpHandler handler=(HttpHandler)handlers.next(); - if (!handler.isStarted()) - try{handler.start();}catch(Exception e){mx.add(e);} - } - mx.ifExceptionThrow(); - } - - /* ------------------------------------------------------------ */ - /** Stop the context. - * @param graceful If true and statistics are on, then this method will wait - * for requestsActive to go to zero before calling stop() - */ - public void stop(boolean graceful) - throws InterruptedException - { - boolean gs=_gracefulStop; - try - { - _gracefulStop=true; - - // wait for all requests to complete. - while (graceful && _statsOn && _requestsActive>0 && _httpServer!=null) - try {Thread.sleep(100);} - catch (InterruptedException e){throw e;} - catch (Exception e){LogSupport.ignore(log,e);} - - stop(); - } - finally - { - _gracefulStop=gs; - } - } - - /* ------------------------------------------------------------ */ - /** Stop the context. - */ - protected void doStop() - throws Exception - { - if (_httpServer==null) - throw new InterruptedException("Destroy called"); - - synchronized(this) - { - // Notify the container for the stop - Thread thread = Thread.currentThread(); - ClassLoader lastContextLoader=thread.getContextClassLoader(); - try - { - if (_loader!=null) - thread.setContextClassLoader(_loader); - Iterator handlers = _handlers.iterator(); - while(handlers.hasNext()) - { - HttpHandler handler=(HttpHandler)handlers.next(); - if (handler.isStarted()) - { - try{handler.stop();} - catch(Exception e){log.warn(LogSupport.EXCEPTION,e);} - } - } - - if (_requestLog!=null) - _requestLog.stop(); - } - finally - { - thread.setContextClassLoader(lastContextLoader); - } - - // TODO this is a poor test - if (_loader instanceof ContextLoader) - { - ((ContextLoader)_loader).destroy(); - LogFactory.release(_loader); - } - - _loader=null; - } - _resources.flushCache(); - _resources.stop(); - } - - - /* ------------------------------------------------------------ */ - /** Destroy a context. - * Destroy a context and remove it from the HttpServer. The - * HttpContext must be stopped before it can be destroyed. - */ - public void destroy() - { - if (isStarted()) - throw new IllegalStateException("Started"); - - if (_httpServer!=null) - _httpServer.removeContext(this); - - _httpServer=null; - - if (_handlers!=null) - _handlers.clear(); - - _handlers=null; - _parent=null; - _loader=null; - if (_attributes!=null) - _attributes.clear(); - _attributes=null; - if (_initParams!=null) - _initParams.clear(); - _initParams=null; - if (_vhosts!=null) - _vhosts.clear(); - _vhosts=null; - _hosts=null; - _tmpDir=null; - - _permissions=null; - - removeComponent(_resources); - if (_resources!=null) - { - _resources.flushCache(); - if (_resources.isStarted()) - try{_resources.stop();}catch(Exception e){LogSupport.ignore(log,e);} - _resources.destroy(); - } - _resources=null; - - super.destroy(); - - } - - - /* ------------------------------------------------------------ */ - /** Set the request log. - * @param log RequestLog to use. - */ - public void setRequestLog(RequestLog log) - { - _requestLog=log; - } - - /* ------------------------------------------------------------ */ - public RequestLog getRequestLog() - { - return _requestLog; - } - - - /* ------------------------------------------------------------ */ - /** Send an error response. - * This method may be specialized to provide alternative error handling for - * errors generated by the container. The default implemenation calls HttpResponse.sendError - * @param response the response to send - * @param code The error code - * @param msg The message for the error or null for the default - * @throws IOException Problem sending response. - */ - public void sendError(HttpResponse response,int code,String msg) - throws IOException - { - response.sendError(code,msg); - } - - /* ------------------------------------------------------------ */ - /** Send an error response. - * This method obtains the responses context and call sendError for context specific - * error handling. - * @param response the response to send - * @param code The error code - * @param msg The message for the error or null for the default - * @throws IOException Problem sending response. - */ - public static void sendContextError(HttpResponse response,int code,String msg) - throws IOException - { - HttpContext context = response.getHttpContext(); - if (context!=null) - context.sendError(response,code,msg); - else - response.sendError(code,msg); - } - - /* ------------------------------------------------------------ */ - /** True set statistics recording on for this context. - * @param on If true, statistics will be recorded for this context. - */ - public void setStatsOn(boolean on) - { - log.info("setStatsOn "+on+" for "+this); - _statsOn=on; - statsReset(); - } - - /* ------------------------------------------------------------ */ - public boolean getStatsOn() {return _statsOn;} - - /* ------------------------------------------------------------ */ - public long getStatsOnMs() - {return _statsOn?(System.currentTimeMillis()-_statsStartedAt):0;} - - /* ------------------------------------------------------------ */ - public void statsReset() - { - synchronized(_statsLock) - { - if (_statsOn) - _statsStartedAt=System.currentTimeMillis(); - _requests=0; - _requestsActiveMax=_requestsActive; - _responses1xx=0; - _responses2xx=0; - _responses3xx=0; - _responses4xx=0; - _responses5xx=0; - } - } - - /* ------------------------------------------------------------ */ - /** - * @return Get the number of requests handled by this context - * since last call of statsReset(). If setStatsOn(false) then this - * is undefined. - */ - public int getRequests() {return _requests;} - - /* ------------------------------------------------------------ */ - /** - * @return Number of requests currently active. - * Undefined if setStatsOn(false). - */ - public int getRequestsActive() {return _requestsActive;} - - /* ------------------------------------------------------------ */ - /** - * @return Maximum number of active requests - * since statsReset() called. Undefined if setStatsOn(false). - */ - public int getRequestsActiveMax() {return _requestsActiveMax;} - - /* ------------------------------------------------------------ */ - /** - * @return Get the number of responses with a 2xx status returned - * by this context since last call of statsReset(). Undefined if - * if setStatsOn(false). - */ - public int getResponses1xx() {return _responses1xx;} - - /* ------------------------------------------------------------ */ - /** - * @return Get the number of responses with a 100 status returned - * by this context since last call of statsReset(). Undefined if - * if setStatsOn(false). - */ - public int getResponses2xx() {return _responses2xx;} - - /* ------------------------------------------------------------ */ - /** - * @return Get the number of responses with a 3xx status returned - * by this context since last call of statsReset(). Undefined if - * if setStatsOn(false). - */ - public int getResponses3xx() {return _responses3xx;} - - /* ------------------------------------------------------------ */ - /** - * @return Get the number of responses with a 4xx status returned - * by this context since last call of statsReset(). Undefined if - * if setStatsOn(false). - */ - public int getResponses4xx() {return _responses4xx;} - - /* ------------------------------------------------------------ */ - /** - * @return Get the number of responses with a 5xx status returned - * by this context since last call of statsReset(). Undefined if - * if setStatsOn(false). - */ - public int getResponses5xx() {return _responses5xx;} - - - /* ------------------------------------------------------------ */ - /** Log a request and response. - * Statistics are also collected by this method. - * @param request - * @param response - */ - public void log(HttpRequest request, - HttpResponse response, - int length) - { - if (_statsOn) - { - synchronized(_statsLock) - { - if (--_requestsActive<0) - _requestsActive=0; - - if (response!=null) - { - switch(response.getStatus()/100) - { - case 1: _responses1xx++;break; - case 2: _responses2xx++;break; - case 3: _responses3xx++;break; - case 4: _responses4xx++;break; - case 5: _responses5xx++;break; - } - } - } - } - - if (_requestLog!=null && - request!=null && - response!=null) - _requestLog.log(request,response,length); - else if (_httpServer!=null) - _httpServer.log(request,response,length); - } - - - - /* ------------------------------------------------------------ */ - /* Class to save scope of nested context calls - */ - private static class Scope - { - ClassLoader _classLoader; - HttpContext _httpContext; - } - - /* - * @see org.mortbay.http.HttpHandler#getName() - */ - public String getName() - { - return this.getContextPath(); - } - - /* - * @see org.mortbay.http.HttpHandler#getHttpContext() - */ - public HttpContext getHttpContext() - { - return this; - } - - /* - * @see org.mortbay.http.HttpHandler#initialize(org.mortbay.http.HttpContext) - */ - public void initialize(HttpContext context) - { - throw new UnsupportedOperationException(); - } - - - /** - * @return - */ - public Resource getBaseResource() - { - return _resources.getBaseResource(); - } - /** - * @param type - * @return - */ - public String getEncodingByMimeType(String type) - { - return _resources.getEncodingByMimeType(type); - } - /** - * @return - */ - public Map getEncodingMap() - { - return _resources.getEncodingMap(); - } - /** - * @return - */ - public int getMaxCachedFileSize() - { - return _resources.getMaxCachedFileSize(); - } - /** - * @return - */ - public int getMaxCacheSize() - { - return _resources.getMaxCacheSize(); - } - /** - * @param filename - * @return - */ - public String getMimeByExtension(String filename) - { - return _resources.getMimeByExtension(filename); - } - /** - * @return - */ - public Map getMimeMap() - { - return _resources.getMimeMap(); - } - /** - * @param pathInContext - * @return - * @throws IOException - */ - public Resource getResource(String pathInContext) throws IOException - { - return _resources.getResource(pathInContext); - } - /** - * @return - */ - public String getResourceBase() - { - return _resources.getResourceBase(); - } - /** - * @param resource - * @return - */ - public ResourceMetaData getResourceMetaData(Resource resource) - { - return _resources.getResourceMetaData(resource); - } - /** - * @param base - */ - public void setBaseResource(Resource base) - { - _resources.setBaseResource(base); - } - /** - * @param encodingMap - */ - public void setEncodingMap(Map encodingMap) - { - _resources.setEncodingMap(encodingMap); - } - /** - * @param maxCachedFileSize - */ - public void setMaxCachedFileSize(int maxCachedFileSize) - { - _resources.setMaxCachedFileSize(maxCachedFileSize); - } - /** - * @param maxCacheSize - */ - public void setMaxCacheSize(int maxCacheSize) - { - _resources.setMaxCacheSize(maxCacheSize); - } - /** - * @param mimeMap - */ - public void setMimeMap(Map mimeMap) - { - _resources.setMimeMap(mimeMap); - } - /** - * @param extension - * @param type - */ - public void setMimeMapping(String extension, String type) - { - _resources.setMimeMapping(extension, type); - } - /** - * @param resourceBase - */ - public void setResourceBase(String resourceBase) - { - _resources.setResourceBase(resourceBase); - } - /** - * @param mimeType - * @param encoding - */ - public void setTypeEncoding(String mimeType, String encoding) - { - _resources.setTypeEncoding(mimeType, encoding); - } -} diff --git a/apps/jetty/java/src/org/mortbay/http/NCSARequestLog.java b/apps/jetty/java/src/org/mortbay/http/NCSARequestLog.java deleted file mode 100644 index a898624eaa..0000000000 --- a/apps/jetty/java/src/org/mortbay/http/NCSARequestLog.java +++ /dev/null @@ -1,505 +0,0 @@ -// ======================================================================== -// $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $ -// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== - -package org.mortbay.http; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.Locale; -import java.util.TimeZone; - -import javax.servlet.http.Cookie; - -import org.apache.commons.logging.Log; -import org.mortbay.log.LogFactory; -import org.mortbay.util.DateCache; -import org.mortbay.util.LogSupport; -import org.mortbay.util.RolloverFileOutputStream; -import org.mortbay.util.StringUtil; - - -/* ------------------------------------------------------------ */ -/** NCSA HTTP Request Log. - * NCSA common or NCSA extended (combined) request log. - * - * Taken from 5.1.12 source and modded to change some private vars to protected - * so we can extend it for I2P. - * - * @version $Id: NCSARequestLog.java,v 1.35 2005/08/13 00:01:24 gregwilkins Exp $ - * @author Tony Thompson - * @author Greg Wilkins - */ -public class NCSARequestLog implements RequestLog -{ - protected static Log log = LogFactory.getLog(NCSARequestLog.class); - - private String _filename; - private boolean _extended; - private boolean _append; - private int _retainDays; - private boolean _closeOut; - private boolean _preferProxiedForAddress; - private String _logDateFormat="dd/MMM/yyyy:HH:mm:ss ZZZ"; - private Locale _logLocale=Locale.getDefault(); - private String _logTimeZone=TimeZone.getDefault().getID(); - private String[] _ignorePaths; - private boolean _logLatency=false; - private boolean _logCookies=false; - - protected transient OutputStream _out; - protected transient OutputStream _fileOut; - protected transient DateCache _logDateCache; - protected transient PathMap _ignorePathMap; - protected transient Writer _writer; - - /* ------------------------------------------------------------ */ - /** Constructor. - */ - public NCSARequestLog() - { - _extended=true; - _append=true; - _retainDays=31; - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param filename Filename, which can be in - * rolloverFileOutputStream format - * @see org.mortbay.util.RolloverFileOutputStream - * @exception IOException - */ - public NCSARequestLog(String filename) - throws IOException - { - _extended=true; - _append=true; - _retainDays=31; - setFilename(filename); - } - - /* ------------------------------------------------------------ */ - /** Set the log filename. - * @see NCSARequestLog#setRetainDays(int) - * @param filename The filename to use. If the filename contains the - * string "yyyy_mm_dd", then a RolloverFileOutputStream is used and the - * log is rolled over nightly and aged according setRetainDays. If no - * filename is set or a null filename - * passed, then requests are logged to System.err. - */ - public void setFilename(String filename) - { - if (filename!=null) - { - filename=filename.trim(); - if (filename.length()==0) - filename=null; - } - _filename=filename; - } - - /* ------------------------------------------------------------ */ - /** Get the log filename. - * @see NCSARequestLog#getDatedFilename() - * @return The log filename without any date expansion. - */ - public String getFilename() - { - return _filename; - } - - /* ------------------------------------------------------------ */ - /** Get the dated log filename. - * @see NCSARequestLog#getFilename() - * @return The log filename with any date encoding expanded. - */ - public String getDatedFilename() - { - if (_fileOut instanceof RolloverFileOutputStream) - return ((RolloverFileOutputStream)_fileOut).getDatedFilename(); - return null; - } - - - /* ------------------------------------------------------------ */ - /** - * @param format The date format to use within the log file. - */ - public void setLogDateFormat(String format) - { - _logDateFormat=format; - } - - /* ------------------------------------------------------------ */ - /** - * @return The date format to use within the log file. - */ - public String getLogDateFormat() - { - return _logDateFormat; - } - - /* ------------------------------------------------------------ */ - /** - * @param tz The date format timezone to use within the log file. - */ - public void setLogTimeZone(String tz) - { - _logTimeZone=tz; - } - - /* ------------------------------------------------------------ */ - /** - * @return The date format timezone to use within the log file. - */ - public String getLogTimeZone() - { - return _logTimeZone; - } - - /* ------------------------------------------------------------ */ - /** - * @return The number of days to retain rollovered log files. - */ - public int getRetainDays() - { - return _retainDays; - } - - /* ------------------------------------------------------------ */ - /** - * @param retainDays The number of days to retain rollovered log files. - */ - public void setRetainDays(int retainDays) - { - _retainDays = retainDays; - } - - /* ------------------------------------------------------------ */ - /** - * @return True if NCSA extended format is to be used. - */ - public boolean isExtended() - { - return _extended; - } - - /* ------------------------------------------------------------ */ - /** - * @param e True if NCSA extended format is to be used. - */ - public void setExtended(boolean e) - { - _extended=e; - } - - /* ------------------------------------------------------------ */ - /** - * @return True if logs are appended to existing log files. - */ - public boolean isAppend() - { - return _append; - } - - /* ------------------------------------------------------------ */ - /** - * @param a True if logs are appended to existing log files. - */ - public void setAppend(boolean a) - { - _append=a; - } - - /* ------------------------------------------------------------ */ - /** - * @deprecated ignored - */ - public void setBuffered(boolean b) - {} - - /* ------------------------------------------------------------ */ - /** Set which paths to ignore. - * - * @param ignorePaths Array of path specifications to ignore - */ - public void setIgnorePaths(String[] ignorePaths) - { - // Contributed by Martin Vilcans (martin@jadestone.se) - _ignorePaths = ignorePaths; - } - - /* ------------------------------------------------------------ */ - public String[] getIgnorePaths() - { - return _ignorePaths; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns the logCookies. - */ - public boolean getLogCookies() - { - return _logCookies; - } - /* ------------------------------------------------------------ */ - /** - * @param logCookies The logCookies to set. - */ - public void setLogCookies(boolean logCookies) - { - _logCookies = logCookies; - } - - /* ------------------------------------------------------------ */ - /** - * @return Returns true if logging latency - */ - public boolean getLogLatency() - { - return _logLatency; - } - - /* ------------------------------------------------------------ */ - /** - * @param logLatency If true, latency is logged at the end of the log line - */ - public void setLogLatency(boolean logLatency) - { - _logLatency = logLatency; - } - - /* ------------------------------------------------------------ */ - /** - * Prefer to log the proxied-for IP address (if present in - * the request header) over the native requester IP address. - * Useful in reverse-proxy situations when you'd rather see - * the IP address of the host before the most recent proxy - * server, as opposed to your own proxy server(s) every time. - * - * jlrobins@socialserve.com, March 2004. - **/ - public void setPreferProxiedForAddress(boolean value) - { - _preferProxiedForAddress = value; - } - - /* ------------------------------------------------------------ */ - public void start() - throws Exception - { - _logDateCache=new DateCache(_logDateFormat,_logLocale); - _logDateCache.setTimeZoneID(_logTimeZone); - - if (_filename != null) - { - _fileOut=new RolloverFileOutputStream(_filename,_append,_retainDays); - _closeOut=true; - } - else - _fileOut=System.err; - - _out=_fileOut; - - if (_ignorePaths!=null && _ignorePaths.length>0) - { - _ignorePathMap=new PathMap(); - for (int i=0;i<_ignorePaths.length;i++) - _ignorePathMap.put(_ignorePaths[i],_ignorePaths[i]); - } - else - _ignorePathMap=null; - - _writer=new OutputStreamWriter(_out); - } - - /* ------------------------------------------------------------ */ - public boolean isStarted() - { - return _fileOut!=null; - } - - /* ------------------------------------------------------------ */ - public void stop() - { - try{if (_writer!=null)_writer.flush();} catch (IOException e){LogSupport.ignore(log,e);} - if (_out!=null && _closeOut) - try{_out.close();}catch(IOException e){LogSupport.ignore(log,e);} - _out=null; - _fileOut=null; - _closeOut=false; - _logDateCache=null; - _writer=null; - } - - /* ------------------------------------------------------------ */ - /** Log a request. - * @param request The request - * @param response The response to this request. - * @param responseLength The bytes written to the response. - */ - public void log(HttpRequest request, - HttpResponse response, - int responseLength) - { - try{ - // ignore ignorables - if (_ignorePathMap != null && - _ignorePathMap.getMatch(request.getPath()) != null) - return; - - // log the rest - if (_fileOut==null) - return; - - StringBuffer buf = new StringBuffer(160); - - String addr = null; - if(_preferProxiedForAddress) - { - // If header is not present, addr will remain null ... - addr = request.getField(HttpFields.__XForwardedFor); - } - if(addr == null) - addr = request.getRemoteAddr(); - buf.append(addr); - - buf.append(" - "); - String user = request.getAuthUser(); - buf.append((user==null)?"-":user); - buf.append(" ["); - buf.append(_logDateCache.format(request.getTimeStamp())); - buf.append("] \""); - buf.append(request.getMethod()); - buf.append(' '); - buf.append(request.getURI()); - buf.append(' '); - buf.append(request.getVersion()); - buf.append("\" "); - int status=response.getStatus(); - buf.append((char)('0'+((status/100)%10))); - buf.append((char)('0'+((status/10)%10))); - buf.append((char)('0'+(status%10))); - if (responseLength>=0) - { - buf.append(' '); - if (responseLength>99999) - buf.append(Integer.toString(responseLength)); - else - { - if (responseLength>9999) - buf.append((char)('0'+((responseLength/10000)%10))); - if (responseLength>999) - buf.append((char)('0'+((responseLength/1000)%10))); - if (responseLength>99) - buf.append((char)('0'+((responseLength/100)%10))); - if (responseLength>9) - buf.append((char)('0'+((responseLength/10)%10))); - buf.append((char)('0'+(responseLength%10))); - } - buf.append(' '); - } - else - buf.append(" - "); - - String log =buf.toString(); - synchronized(_writer) - { - _writer.write(log); - if (_extended) - { - logExtended(request,response,_writer); - if (!_logCookies) - _writer.write(" -"); - } - - if (_logCookies) - { - Cookie[] cookies = request.getCookies(); - if (cookies==null || cookies.length==0) - _writer.write(" -"); - else - { - _writer.write(" \""); - for (int i=0;i<cookies.length;i++) - { - if (i!=0) - _writer.write(';'); - _writer.write(cookies[i].getName()); - _writer.write('='); - _writer.write(cookies[i].getValue()); - } - _writer.write("\""); - } - } - - if (_logLatency) - _writer.write(" "+(System.currentTimeMillis()-request.getTimeStamp())); - - _writer.write(StringUtil.__LINE_SEPARATOR); - _writer.flush(); - } - } - catch(IOException e) - { - log.warn(LogSupport.EXCEPTION,e); - } - } - - /* ------------------------------------------------------------ */ - /** Log Extended fields. - * This method can be extended by a derived class to add extened fields to - * each log entry. It is called by the log method after all standard - * fields have been added, but before the line terminator. - * Derived implementations should write extra fields to the Writer - * provided. - * The default implementation writes the referer and user agent. - * @param request The request to log. - * @param response The response to log. - * @param log The writer to write the extra fields to. - * @exception IOException Problem writing log - */ - protected void logExtended(HttpRequest request, - HttpResponse response, - Writer log) - throws IOException - { - String referer = request.getField(HttpFields.__Referer); - if(referer==null) - log.write("\"-\" "); - else - { - log.write('"'); - log.write(referer); - log.write("\" "); - } - - String agent = request.getField(HttpFields.__UserAgent); - if(agent==null) - log.write("\"-\""); - else - { - log.write('"'); - log.write(agent); - log.write('"'); - } - - - } -} - diff --git a/apps/jetty/java/src/org/mortbay/http/handler/ResourceHandler.java b/apps/jetty/java/src/org/mortbay/http/handler/ResourceHandler.java deleted file mode 100644 index d1a57159bf..0000000000 --- a/apps/jetty/java/src/org/mortbay/http/handler/ResourceHandler.java +++ /dev/null @@ -1,809 +0,0 @@ -// ======================================================================== -// $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $ -// Copyright 199-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== - -package org.mortbay.http.handler; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Enumeration; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.mortbay.log.LogFactory; -import org.mortbay.http.HttpException; -import org.mortbay.http.HttpFields; -import org.mortbay.http.HttpRequest; -import org.mortbay.http.HttpResponse; -import org.mortbay.http.InclusiveByteRange; -import org.mortbay.http.MultiPartResponse; -import org.mortbay.http.ResourceCache; -import org.mortbay.util.CachedResource; -import org.mortbay.util.IO; -import org.mortbay.util.LogSupport; -import org.mortbay.util.Resource; -import org.mortbay.util.StringMap; -import org.mortbay.util.TypeUtil; -import org.mortbay.util.URI; - -/* ------------------------------------------------------------ */ -/** Handler to serve files and resources. - * Serves files from a given resource URL base and implements - * the GET, HEAD, DELETE, OPTIONS, PUT, MOVE methods and the - * IfModifiedSince and IfUnmodifiedSince header fields. - * A simple memory cache is also provided to reduce file I/O. - * HTTP/1.1 ranges are supported. - * - * @version $Id: ResourceHandler.java,v 1.66 2005/08/24 08:18:17 gregwilkins Exp $ - * @author Nuno Pregui?a (sorry, wasn't UTF-8) - * @author Greg Wilkins - */ -public class ResourceHandler extends AbstractHttpHandler -{ - private static Log log = LogFactory.getLog(ResourceHandler.class); - - /* ----------------------------------------------------------------- */ - private boolean _acceptRanges=true; - private boolean _redirectWelcomeFiles ; - private String[] _methods=null; - private String _allowed; - private boolean _dirAllowed=true; - private int _minGzipLength =-1; - private StringMap _methodMap = new StringMap(); - { - setAllowedMethods(new String[] - { - HttpRequest.__GET, - HttpRequest.__POST, - HttpRequest.__HEAD, - HttpRequest.__OPTIONS, - HttpRequest.__TRACE - }); - } - - /* ----------------------------------------------------------------- */ - /** Construct a ResourceHandler. - */ - public ResourceHandler() - {} - - - /* ----------------------------------------------------------------- */ - public synchronized void start() - throws Exception - { - super.start(); - } - - /* ----------------------------------------------------------------- */ - public void stop() - throws InterruptedException - { - super.stop(); - } - - /* ------------------------------------------------------------ */ - public String[] getAllowedMethods() - { - return _methods; - } - - /* ------------------------------------------------------------ */ - public void setAllowedMethods(String[] methods) - { - StringBuffer b = new StringBuffer(); - _methods=methods; - _methodMap.clear(); - for (int i=0;i<methods.length;i++) - { - _methodMap.put(methods[i],methods[i]); - if (i>0) - b.append(','); - b.append(methods[i]); - } - _allowed=b.toString(); - } - - /* ------------------------------------------------------------ */ - public boolean isMethodAllowed(String method) - { - return _methodMap.get(method)!=null; - } - - /* ------------------------------------------------------------ */ - public String getAllowedString() - { - return _allowed; - } - - /* ------------------------------------------------------------ */ - public boolean isDirAllowed() - { - return _dirAllowed; - } - - /* ------------------------------------------------------------ */ - public void setDirAllowed(boolean dirAllowed) - { - _dirAllowed = dirAllowed; - } - - /* ------------------------------------------------------------ */ - public boolean isAcceptRanges() - { - return _acceptRanges; - } - - /* ------------------------------------------------------------ */ - /** - * @return True if welcome files are redirected to. False if forward is used. - */ - public boolean getRedirectWelcome() - { - return _redirectWelcomeFiles; - } - - /* ------------------------------------------------------------ */ - /** - * @param redirectWelcome True if welcome files are redirected to. False - * if forward is used. - */ - public void setRedirectWelcome(boolean redirectWelcome) - { - _redirectWelcomeFiles = redirectWelcome; - } - - /* ------------------------------------------------------------ */ - /** Set if the handler accepts range requests. - * Default is false; - * @param ar True if the handler should accept ranges - */ - public void setAcceptRanges(boolean ar) - { - _acceptRanges=ar; - } - - /* ------------------------------------------------------------ */ - /** Get minimum content length for GZIP encoding. - * @return Minimum length of content for gzip encoding or -1 if disabled. - */ - public int getMinGzipLength() - { - return _minGzipLength; - } - - /* ------------------------------------------------------------ */ - /** Set minimum content length for GZIP encoding. - * @param minGzipLength If set to a positive integer, then static content - * larger than this will be served as gzip content encoded - * if a matching resource is found ending with ".gz" - */ - public void setMinGzipLength(int minGzipLength) - { - _minGzipLength = minGzipLength; - } - - - /* ------------------------------------------------------------ */ - /** get Resource to serve. - * Map a path to a resource. The default implementation calls - * HttpContext.getResource but derived handers may provide - * their own mapping. - * @param pathInContext The path to find a resource for. - * @return The resource to serve. - */ - protected Resource getResource(String pathInContext) - throws IOException - { - return getHttpContext().getResource(pathInContext); - } - - /* ------------------------------------------------------------ */ - public void handle(String pathInContext, - String pathParams, - HttpRequest request, - HttpResponse response) - throws HttpException, IOException - { - Resource resource = getResource(pathInContext); - if (resource==null) - return; - - // Is the method allowed? - if (!isMethodAllowed(request.getMethod())) - { - if(log.isDebugEnabled())log.debug("Method not allowed: "+request.getMethod()); - if (resource.exists()) - { - setAllowHeader(response); - response.sendError(HttpResponse.__405_Method_Not_Allowed); - } - return; - } - - // Handle the request - try - { - if(log.isDebugEnabled())log.debug("PATH="+pathInContext+" RESOURCE="+resource); - - // check filename - String method=request.getMethod(); - if (method.equals(HttpRequest.__GET) || - method.equals(HttpRequest.__POST) || - method.equals(HttpRequest.__HEAD)) - handleGet(request, response, pathInContext, pathParams, resource); - else if (method.equals(HttpRequest.__PUT)) - handlePut(request, response, pathInContext, resource); - else if (method.equals(HttpRequest.__DELETE)) - handleDelete(request, response, pathInContext, resource); - else if (method.equals(HttpRequest.__OPTIONS)) - handleOptions(response, pathInContext); - else if (method.equals(HttpRequest.__MOVE)) - handleMove(request, response, pathInContext, resource); - else if (method.equals(HttpRequest.__TRACE)) - handleTrace(request, response); - else - { - if(log.isDebugEnabled())log.debug("Unknown action:"+method); - // anything else... - try{ - if (resource.exists()) - response.sendError(HttpResponse.__501_Not_Implemented); - } - catch(Exception e) {LogSupport.ignore(log,e);} - } - } - catch(IllegalArgumentException e) - { - LogSupport.ignore(log,e); - } - finally - { - if (resource!=null && !(resource instanceof CachedResource)) - resource.release(); - } - } - - /* ------------------------------------------------------------------- */ - public void handleGet(HttpRequest request, - HttpResponse response, - String pathInContext, - String pathParams, - Resource resource) - throws IOException - { - if(log.isDebugEnabled())log.debug("Looking for "+resource); - - if (resource!=null && resource.exists()) - { - // check if directory - if (resource.isDirectory()) - { - if (!pathInContext.endsWith("/") && !pathInContext.equals("/")) - { - log.debug("Redirect to directory/"); - - String q=request.getQuery(); - - // Properly fix URI - URI urifix = new URI(request.getRequestURL().toString()); - urifix.setPath(urifix.getPath()); - StringBuffer buf = new StringBuffer(urifix.toString()); - urifix = null; - - if (q!=null&&q.length()!=0) - { - buf.append('?'); - buf.append(q); - } - response.setField(HttpFields.__Location, URI.addPaths(buf.toString(),"/")); - response.setStatus(302); - request.setHandled(true); - return; - } - - // See if index file exists - String welcome=getHttpContext().getWelcomeFile(resource); - if (welcome!=null) - { - // Forward to the index - String ipath=URI.addPaths(pathInContext,welcome); - if (_redirectWelcomeFiles) - { - // Redirect to the index - ipath=URI.addPaths(getHttpContext().getContextPath(),ipath); - response.setContentLength(0); - response.sendRedirect(ipath); - } - else - { - URI uri=request.getURI(); - uri.setPath(URI.addPaths(uri.getPath(),welcome)); - getHttpContext().handle(ipath,pathParams,request,response); - } - return; - } - - // Check modified dates - if (!passConditionalHeaders(request,response,resource)) - return; - // If we got here, no forward to index took place - sendDirectory(request,response,resource,pathInContext.length()>1); - } - // check if it is a file - else if (resource.exists()) - { - // Check modified dates - if (!passConditionalHeaders(request,response,resource)) - return; - sendData(request,response,pathInContext,resource,true); - } - else - // don't know what it is - log.warn("Unknown file type"); - } - } - - - /* ------------------------------------------------------------ */ - /* Check modification date headers. - */ - private boolean passConditionalHeaders(HttpRequest request, - HttpResponse response, - Resource resource) - throws IOException - { - if (!request.getMethod().equals(HttpRequest.__HEAD)) - { - // If we have meta data for the file - // Try a direct match for most common requests. Avoids - // parsing the date. - ResourceCache.ResourceMetaData metaData = - (ResourceCache.ResourceMetaData)resource.getAssociate(); - if (metaData!=null) - { - String ifms=request.getField(HttpFields.__IfModifiedSince); - String mdlm=metaData.getLastModified(); - if (ifms!=null && mdlm!=null && ifms.equals(mdlm)) - { - response.setStatus(HttpResponse.__304_Not_Modified); - request.setHandled(true); - return false; - } - } - - - long date=0; - // Parse the if[un]modified dates and compare to resource - - if ((date=request.getDateField(HttpFields.__IfUnmodifiedSince))>0) - { - if (resource.lastModified()/1000 > date/1000) - { - response.sendError(HttpResponse.__412_Precondition_Failed); - return false; - } - } - - if ((date=request.getDateField(HttpFields.__IfModifiedSince))>0) - { - - if (resource.lastModified()/1000 <= date/1000) - { - response.setStatus(HttpResponse.__304_Not_Modified); - request.setHandled(true); - return false; - } - } - - } - return true; - } - - - /* ------------------------------------------------------------ */ - void handlePut(HttpRequest request, - HttpResponse response, - String pathInContext, - Resource resource) - throws IOException - { - if(log.isDebugEnabled())log.debug("PUT "+pathInContext+" in "+resource); - - boolean exists=resource!=null && resource.exists(); - if (exists && - !passConditionalHeaders(request,response,resource)) - return; - - if (pathInContext.endsWith("/")) - { - if (!exists) - { - if (!resource.getFile().mkdirs()) - response.sendError(HttpResponse.__403_Forbidden, "Directories could not be created"); - else - { - request.setHandled(true); - response.setStatus(HttpResponse.__201_Created); - response.commit(); - } - } - else - { - request.setHandled(true); - response.setStatus(HttpResponse.__200_OK); - response.commit(); - } - } - else - { - try - { - int toRead = request.getContentLength(); - InputStream in = request.getInputStream(); - OutputStream out = resource.getOutputStream(); - if (toRead>=0) - IO.copy(in,out,toRead); - else - IO.copy(in,out); - out.close(); - request.setHandled(true); - response.setStatus(exists - ?HttpResponse.__200_OK - :HttpResponse.__201_Created); - response.commit(); - } - catch (Exception ex) - { - log.warn(LogSupport.EXCEPTION,ex); - response.sendError(HttpResponse.__403_Forbidden, - ex.getMessage()); - } - } - } - - /* ------------------------------------------------------------ */ - void handleDelete(HttpRequest request, - HttpResponse response, - String pathInContext, - Resource resource) - throws IOException - { - if(log.isDebugEnabled())log.debug("DELETE "+pathInContext+" from "+resource); - - if (!resource.exists() || - !passConditionalHeaders(request,response,resource)) - return; - - try - { - // delete the file - if (resource.delete()) - response.setStatus(HttpResponse.__204_No_Content); - else - response.sendError(HttpResponse.__403_Forbidden); - - // Send response - request.setHandled(true); - } - catch (SecurityException sex) - { - log.warn(LogSupport.EXCEPTION,sex); - response.sendError(HttpResponse.__403_Forbidden, sex.getMessage()); - } - } - - - /* ------------------------------------------------------------ */ - void handleMove(HttpRequest request, - HttpResponse response, - String pathInContext, - Resource resource) - throws IOException - { - if (!resource.exists() || !passConditionalHeaders(request,response,resource)) - return; - - - String newPath = URI.canonicalPath(request.getField("New-uri")); - if (newPath==null) - { - response.sendError(HttpResponse.__405_Method_Not_Allowed, - "Bad new uri"); - return; - } - - String contextPath = getHttpContext().getContextPath(); - if (contextPath!=null && !newPath.startsWith(contextPath)) - { - response.sendError(HttpResponse.__405_Method_Not_Allowed, - "Not in context"); - return; - } - - - // Find path - try - { - // TODO - Check this - String newInfo=newPath; - if (contextPath!=null) - newInfo=newInfo.substring(contextPath.length()); - Resource newFile = getHttpContext().getBaseResource().addPath(newInfo); - - if(log.isDebugEnabled())log.debug("Moving "+resource+" to "+newFile); - resource.renameTo(newFile); - - response.setStatus(HttpResponse.__204_No_Content); - request.setHandled(true); - } - catch (Exception ex) - { - log.warn(LogSupport.EXCEPTION,ex); - setAllowHeader(response); - response.sendError(HttpResponse.__405_Method_Not_Allowed, - "Error:"+ex); - return; - } - } - - /* ------------------------------------------------------------ */ - void handleOptions(HttpResponse response, String pathInContext) - throws IOException - { - if ("*".equals(pathInContext)) - return; - setAllowHeader(response); - response.commit(); - } - - /* ------------------------------------------------------------ */ - void setAllowHeader(HttpResponse response) - { - response.setField(HttpFields.__Allow, getAllowedString()); - } - - /* ------------------------------------------------------------ */ - public void writeHeaders(HttpResponse response,Resource resource, long count) - throws IOException - { - ResourceCache.ResourceMetaData metaData = - (ResourceCache.ResourceMetaData)resource.getAssociate(); - - response.setContentType(metaData.getMimeType()); - if (count != -1) - { - if (count==resource.length()) - response.setField(HttpFields.__ContentLength,metaData.getLength()); - else - response.setContentLength((int)count); - } - - response.setField(HttpFields.__LastModified,metaData.getLastModified()); - - if (_acceptRanges && response.getHttpRequest().getDotVersion()>0) - response.setField(HttpFields.__AcceptRanges,"bytes"); - } - - /* ------------------------------------------------------------ */ - public void sendData(HttpRequest request, - HttpResponse response, - String pathInContext, - Resource resource, - boolean writeHeaders) - throws IOException - { - long resLength=resource.length(); - - // see if there are any range headers - Enumeration reqRanges = - request.getDotVersion()>0 - ?request.getFieldValues(HttpFields.__Range) - :null; - - if (!writeHeaders || reqRanges == null || !reqRanges.hasMoreElements()) - { - // look for a gziped content. - Resource data=resource; - if (_minGzipLength>0) - { - String accept=request.getField(HttpFields.__AcceptEncoding); - if (accept!=null && resLength>_minGzipLength && - !pathInContext.endsWith(".gz")) - { - Resource gz = getHttpContext().getResource(pathInContext+".gz"); - if (gz.exists() && accept.indexOf("gzip")>=0) - { - if(log.isDebugEnabled())log.debug("gzip="+gz); - response.setField(HttpFields.__ContentEncoding,"gzip"); - data=gz; - resLength=data.length(); - } - } - } - writeHeaders(response,resource,resLength); - - request.setHandled(true); - OutputStream out = response.getOutputStream(); - data.writeTo(out,0,resLength); - return; - } - - // Parse the satisfiable ranges - List ranges =InclusiveByteRange.satisfiableRanges(reqRanges,resLength); - if(log.isDebugEnabled())log.debug("ranges: " + reqRanges + " == " + ranges); - - // if there are no satisfiable ranges, send 416 response - if (ranges==null || ranges.size()==0) - { - log.debug("no satisfiable ranges"); - writeHeaders(response, resource, resLength); - response.setStatus(HttpResponse.__416_Requested_Range_Not_Satisfiable); - response.setReason((String)HttpResponse.__statusMsg - .get(TypeUtil.newInteger(HttpResponse.__416_Requested_Range_Not_Satisfiable))); - - response.setField(HttpFields.__ContentRange, - InclusiveByteRange.to416HeaderRangeString(resLength)); - - OutputStream out = response.getOutputStream(); - resource.writeTo(out,0,resLength); - request.setHandled(true); - return; - } - - - // if there is only a single valid range (must be satisfiable - // since were here now), send that range with a 216 response - if ( ranges.size()== 1) - { - InclusiveByteRange singleSatisfiableRange = - (InclusiveByteRange)ranges.get(0); - if(log.isDebugEnabled())log.debug("single satisfiable range: " + singleSatisfiableRange); - long singleLength = singleSatisfiableRange.getSize(resLength); - writeHeaders(response,resource,singleLength); - response.setStatus(HttpResponse.__206_Partial_Content); - response.setReason((String)HttpResponse.__statusMsg - .get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content))); - response.setField(HttpFields.__ContentRange, - singleSatisfiableRange.toHeaderRangeString(resLength)); - OutputStream out = response.getOutputStream(); - resource.writeTo(out, - singleSatisfiableRange.getFirst(resLength), - singleLength); - request.setHandled(true); - return; - } - - - // multiple non-overlapping valid ranges cause a multipart - // 216 response which does not require an overall - // content-length header - // - ResourceCache.ResourceMetaData metaData = - (ResourceCache.ResourceMetaData)resource.getAssociate(); - String encoding = metaData.getMimeType(); - MultiPartResponse multi = new MultiPartResponse(response); - response.setStatus(HttpResponse.__206_Partial_Content); - response.setReason((String)HttpResponse.__statusMsg - .get(TypeUtil.newInteger(HttpResponse.__206_Partial_Content))); - - // If the request has a "Request-Range" header then we need to - // send an old style multipart/x-byteranges Content-Type. This - // keeps Netscape and acrobat happy. This is what Apache does. - String ctp; - if (request.containsField(HttpFields.__RequestRange)) - ctp = "multipart/x-byteranges; boundary="; - else - ctp = "multipart/byteranges; boundary="; - response.setContentType(ctp+multi.getBoundary()); - - InputStream in=(resource instanceof CachedResource) - ?null:resource.getInputStream(); - OutputStream out = response.getOutputStream(); - long pos=0; - - for (int i=0;i<ranges.size();i++) - { - InclusiveByteRange ibr = (InclusiveByteRange) ranges.get(i); - String header=HttpFields.__ContentRange+": "+ - ibr.toHeaderRangeString(resLength); - if(log.isDebugEnabled())log.debug("multi range: "+encoding+" "+header); - multi.startPart(encoding,new String[]{header}); - - long start=ibr.getFirst(resLength); - long size=ibr.getSize(resLength); - if (in!=null) - { - // Handle non cached resource - if (start<pos) - { - in.close(); - in=resource.getInputStream(); - pos=0; - } - if (pos<start) - { - in.skip(start-pos); - pos=start; - } - IO.copy(in,out,size); - pos+=size; - } - else - // Handle cached resource - resource.writeTo(out,start,size); - - } - if (in!=null) - in.close(); - multi.close(); - - request.setHandled(true); - - return; - } - - - /* ------------------------------------------------------------------- */ - void sendDirectory(HttpRequest request, - HttpResponse response, - Resource resource, - boolean parent) - throws IOException - { - if (!_dirAllowed) - { - response.sendError(HttpResponse.__403_Forbidden); - return; - } - - request.setHandled(true); - - if(log.isDebugEnabled())log.debug("sendDirectory: "+resource); - byte[] data=null; - if (resource instanceof CachedResource) - data=((CachedResource)resource).getCachedData(); - - if (data==null) - { - String base = URI.addPaths(request.getPath(),"/"); - String dir = resource.getListHTML(URI.encodePath(base),parent); - if (dir==null) - { - response.sendError(HttpResponse.__403_Forbidden, - "No directory"); - return; - } - data=dir.getBytes("UTF8"); - if (resource instanceof CachedResource) - ((CachedResource)resource).setCachedData(data); - } - - response.setContentType("text/html; charset=UTF8"); - response.setContentLength(data.length); - - if (request.getMethod().equals(HttpRequest.__HEAD)) - { - response.commit(); - return; - } - - response.getOutputStream().write(data,0,data.length); - response.commit(); - } -} - - - diff --git a/apps/jetty/java/src/org/mortbay/jetty/Server.java b/apps/jetty/java/src/org/mortbay/jetty/Server.java deleted file mode 100644 index 409f8a529d..0000000000 --- a/apps/jetty/java/src/org/mortbay/jetty/Server.java +++ /dev/null @@ -1,617 +0,0 @@ -// ======================================================================== -// $Id: Server.java,v 1.40 2005/10/21 13:52:11 gregwilkins Exp $ -// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== - -package org.mortbay.jetty; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; - -import org.apache.commons.logging.Log; -import org.mortbay.log.LogFactory; -import org.mortbay.http.HttpContext; -import org.mortbay.http.HttpServer; -import org.mortbay.jetty.servlet.ServletHttpContext; -import org.mortbay.jetty.servlet.WebApplicationContext; -import org.mortbay.util.LogSupport; -import org.mortbay.util.Resource; -import org.mortbay.xml.XmlConfiguration; - - -/* ------------------------------------------------------------ */ -/** The Jetty HttpServer. - * - * This specialization of org.mortbay.http.HttpServer adds knowledge - * about servlets and their specialized contexts. It also included - * support for initialization from xml configuration files - * that follow the XmlConfiguration dtd. - * - * HttpContexts created by Server are of the type - * org.mortbay.jetty.servlet.ServletHttpContext unless otherwise - * specified. - * - * This class also provides a main() method which starts a server for - * each config file passed on the command line. If the system - * property JETTY_NO_SHUTDOWN_HOOK is not set to true, then a shutdown - * hook is thread is registered to stop these servers. - * - * @see org.mortbay.xml.XmlConfiguration - * @see org.mortbay.jetty.servlet.ServletHttpContext - * @version $Revision: 1.40 $ - * @author Greg Wilkins (gregw) - */ -public class Server extends HttpServer -{ - static Log log = LogFactory.getLog(Server.class); - private String[] _webAppConfigurationClassNames = - new String[]{"org.mortbay.jetty.servlet.XMLConfiguration", "org.mortbay.jetty.servlet.JettyWebConfiguration"}; - private String _configuration; - private String _rootWebApp; - private static ShutdownHookThread hookThread = new ShutdownHookThread(); - - /* ------------------------------------------------------------ */ - /** Constructor. - */ - public Server() - { - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param configuration The filename or URL of the XML - * configuration file. - */ - public Server(String configuration) - throws IOException - { - this(Resource.newResource(configuration).getURL()); - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param configuration The filename or URL of the XML - * configuration file. - */ - public Server(Resource configuration) - throws IOException - { - this(configuration.getURL()); - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param configuration The filename or URL of the XML - * configuration file. - */ - public Server(URL configuration) - throws IOException - { - _configuration=configuration.toString(); - Server.hookThread.add(this); - try - { - XmlConfiguration config=new XmlConfiguration(configuration); - config.configure(this); - } - catch(IOException e) - { - throw e; - } - catch(InvocationTargetException e) - { - log.warn(LogSupport.EXCEPTION,e.getTargetException()); - throw new IOException("Jetty configuration problem: "+e.getTargetException()); - } - catch(Exception e) - { - log.warn(LogSupport.EXCEPTION,e); - throw new IOException("Jetty configuration problem: "+e); - } - } - - /* ------------------------------------------------------------ */ - public boolean getStopAtShutdown() - { - return hookThread.contains(this); - } - - /* ------------------------------------------------------------ */ - public void setStopAtShutdown(boolean stop) - { - if (stop) - hookThread.add(this); - else - hookThread.remove(this); - } - - /* ------------------------------------------------------------ */ - /** Get the root webapp name. - * @return The name of the root webapp (eg. "root" for root.war). - */ - public String getRootWebApp() - { - return _rootWebApp; - } - - /* ------------------------------------------------------------ */ - /** Set the root webapp name. - * @param rootWebApp The name of the root webapp (eg. "root" for root.war). - */ - public void setRootWebApp(String rootWebApp) - { - _rootWebApp = rootWebApp; - } - - /* ------------------------------------------------------------ */ - /** Configure the server from an XML file. - * @param configuration The filename or URL of the XML - * configuration file. - */ - public void configure(String configuration) - throws IOException - { - - URL url=Resource.newResource(configuration).getURL(); - if (_configuration!=null && _configuration.equals(url.toString())) - return; - if (_configuration!=null) - throw new IllegalStateException("Already configured with "+_configuration); - try - { - XmlConfiguration config=new XmlConfiguration(url); - _configuration=url.toString(); - config.configure(this); - } - catch(IOException e) - { - throw e; - } - catch(Exception e) - { - log.warn(LogSupport.EXCEPTION,e); - throw new IOException("Jetty configuration problem: "+e); - } - } - - /* ------------------------------------------------------------ */ - public String getConfiguration() - { - return _configuration; - } - - /* ------------------------------------------------------------ */ - /** Create a new ServletHttpContext. - * Ths method is called by HttpServer to creat new contexts. Thus - * calls to addContext or getContext that result in a new Context - * being created will return an - * org.mortbay.jetty.servlet.ServletHttpContext instance. - * @return ServletHttpContext - */ - protected HttpContext newHttpContext() - { - return new ServletHttpContext(); - } - - /* ------------------------------------------------------------ */ - /** Create a new WebApplicationContext. - * Ths method is called by Server to creat new contexts for web - * applications. Thus calls to addWebApplication that result in - * a new Context being created will return an correct class instance. - * Derived class can override this method to create instance of its - * own class derived from WebApplicationContext in case it needs more - * functionality. - * @param webApp The Web application directory or WAR file. - * @return WebApplicationContext - */ - protected WebApplicationContext newWebApplicationContext( - String webApp - ) - { - return new WebApplicationContext(webApp); - } - - /* ------------------------------------------------------------ */ - /** Add Web Application. - * @param contextPathSpec The context path spec. Which must be of - * the form / or /path/* - * @param webApp The Web application directory or WAR file. - * @return The WebApplicationContext - * @exception IOException - */ - public WebApplicationContext addWebApplication(String contextPathSpec, - String webApp) - throws IOException - { - return addWebApplication(null,contextPathSpec,webApp); - } - - /* ------------------------------------------------------------ */ - /** Add Web Application. - * @param virtualHost Virtual host name or null - * @param contextPathSpec The context path spec. Which must be of - * the form / or /path/* - * @param webApp The Web application directory or WAR file. - * @return The WebApplicationContext - * @exception IOException - */ - public WebApplicationContext addWebApplication(String virtualHost, - String contextPathSpec, - String webApp) - throws IOException - { - WebApplicationContext appContext = - newWebApplicationContext(webApp); - appContext.setContextPath(contextPathSpec); - addContext(virtualHost,appContext); - if(log.isDebugEnabled())log.debug("Web Application "+appContext+" added"); - return appContext; - } - - - /* ------------------------------------------------------------ */ - /** Add Web Applications. - * Add auto webapplications to the server. The name of the - * webapp directory or war is used as the context name. If a - * webapp is called "root" it is added at "/". - * @param webapps Directory file name or URL to look for auto webapplication. - * @exception IOException - */ - public WebApplicationContext[] addWebApplications(String webapps) - throws IOException - { - return addWebApplications(null,webapps,null,false); - } - - /* ------------------------------------------------------------ */ - /** Add Web Applications. - * Add auto webapplications to the server. The name of the - * webapp directory or war is used as the context name. If the - * webapp matches the rootWebApp it is added as the "/" context. - * @param host Virtual host name or null - * @param webapps Directory file name or URL to look for auto webapplication. - * @exception IOException - */ - public WebApplicationContext[] addWebApplications(String host, - String webapps) - throws IOException - { - return addWebApplications(host,webapps,null,false); - } - - /* ------------------------------------------------------------ */ - /** Add Web Applications. - * Add auto webapplications to the server. The name of the - * webapp directory or war is used as the context name. If the - * webapp matches the rootWebApp it is added as the "/" context. - * @param host Virtual host name or null - * @param webapps Directory file name or URL to look for auto - * webapplication. - * @param extract If true, extract war files - * @exception IOException - */ - public WebApplicationContext[] addWebApplications(String host, - String webapps, - boolean extract) - throws IOException - { - return addWebApplications(host,webapps,null,extract); - } - - /* ------------------------------------------------------------ */ - /** Add Web Applications. - * Add auto webapplications to the server. The name of the - * webapp directory or war is used as the context name. If the - * webapp matches the rootWebApp it is added as the "/" context. - * @param host Virtual host name or null - * @param webapps Directory file name or URL to look for auto - * webapplication. - * @param defaults The defaults xml filename or URL which is - * loaded before any in the web app. Must respect the web.dtd. - * If null the default defaults file is used. If the empty string, then - * no defaults file is used. - * @param extract If true, extract war files - * @exception IOException - */ - public WebApplicationContext[] addWebApplications(String host, - String webapps, - String defaults, - boolean extract) - throws IOException - { - return addWebApplications(host,webapps,defaults,extract,true,null); - } - - /* ------------------------------------------------------------ */ - /** Add Web Applications. - * Add auto webapplications to the server. The name of the - * webapp directory or war is used as the context name. If the - * webapp matches the rootWebApp it is added as the "/" context. - * @param host Virtual host name or null - * @param webapps Directory file name or URL to look for auto - * webapplication. - * @param defaults The defaults xml filename or URL which is - * loaded before any in the web app. Must respect the web.dtd. - * If null the default defaults file is used. If the empty string, then - * no defaults file is used. - * @param extract If true, extract war files - * @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications - * @exception IOException - */ - public WebApplicationContext[] addWebApplications(String host, - String webapps, - String defaults, - boolean extract, - boolean java2CompliantClassLoader) - throws IOException - { - return addWebApplications(host,webapps,defaults,extract,java2CompliantClassLoader,null); - - } - /* ------------------------------------------------------------ */ - /** Add Web Applications. - * Add auto webapplications to the server. The name of the - * webapp directory or war is used as the context name. If the - * webapp matches the rootWebApp it is added as the "/" context. - * @param host Virtual host name or null - * @param webapps Directory file name or URL to look for auto - * webapplication. - * @param defaults The defaults xml filename or URL which is - * loaded before any in the web app. Must respect the web.dtd. - * If null the default defaults file is used. If the empty string, then - * no defaults file is used. - * @param extract If true, extract war files - * @param java2CompliantClassLoader True if java2 compliance is applied to all webapplications - * @param Attributes[] A set of attributes to pass to setAttribute, format is first item is the key, second item is the value. - * @exception IOException - */ - public WebApplicationContext[] addWebApplications(String host, - String webapps, - String defaults, - boolean extract, - boolean java2CompliantClassLoader, - String Attributes[]) - throws IOException - { - ArrayList wacs = new ArrayList(); - Resource r=Resource.newResource(webapps); - if (!r.exists()) - throw new IllegalArgumentException("No such webapps resource "+r); - - if (!r.isDirectory()) - throw new IllegalArgumentException("Not directory webapps resource "+r); - if(Attributes != null) { - if(((Attributes.length / 2) * 2) != Attributes.length) { - throw new IllegalArgumentException("Attributes must be in pairs of key,value."); - } - } - String[] files=r.list(); - - for (int f=0;files!=null && f<files.length;f++) - { - String context=files[f]; - - if (context.equalsIgnoreCase("CVS/") || - context.equalsIgnoreCase("CVS") || - context.startsWith(".")) - continue; - - - String app = r.addPath(r.encode(files[f])).toString(); - if (context.toLowerCase().endsWith(".war") || - context.toLowerCase().endsWith(".jar")) - { - context=context.substring(0,context.length()-4); - Resource unpacked=r.addPath(context); - if (unpacked!=null && unpacked.exists() && unpacked.isDirectory()) - continue; - } - - if (_rootWebApp!=null && (context.equals(_rootWebApp)||context.equals(_rootWebApp+"/"))) - context="/"; - else - context="/"+context; - - WebApplicationContext wac= addWebApplication(host, - context, - app); - wac.setExtractWAR(extract); - wac.setClassLoaderJava2Compliant(java2CompliantClassLoader); - if (defaults!=null) - { - if (defaults.length()==0) - wac.setDefaultsDescriptor(null); - else - wac.setDefaultsDescriptor(defaults); - } - if(Attributes != null) { - for(int i = 0; i < Attributes.length; i++, i++) { - wac.setAttribute(Attributes[i],Attributes[i + 1]); - } - } - wacs.add(wac); - } - - return (WebApplicationContext[])wacs.toArray(new WebApplicationContext[wacs.size()]); - } - - - /* ------------------------------------------------------------ */ - /** setWebApplicationConfigurationClasses - * Set up the list of classnames of WebApplicationContext.Configuration - * implementations that will be applied to configure every webapp. - * The list can be overridden by individual WebApplicationContexts. - * @param configurationClasses - */ - public void setWebApplicationConfigurationClassNames (String[] configurationClassNames) - { - if (configurationClassNames != null) - { - _webAppConfigurationClassNames = new String[configurationClassNames.length]; - System.arraycopy(configurationClassNames, 0, _webAppConfigurationClassNames, 0, configurationClassNames.length); - } - } - - public String[] getWebApplicationConfigurationClassNames () - { - return _webAppConfigurationClassNames; - } - - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - /* ------------------------------------------------------------ */ - public static void main(String[] arg) - { - String[] dftConfig={"etc/jetty.xml"}; - - if (arg.length==0) - { - log.info("Using default configuration: etc/jetty.xml"); - arg=dftConfig; - } - - final Server[] servers=new Server[arg.length]; - - // create and start the servers. - for (int i=0;i<arg.length;i++) - { - try - { - servers[i] = new Server(arg[i]); - servers[i].setStopAtShutdown(true); - servers[i].start(); - - } - catch(Exception e) - { - log.warn(LogSupport.EXCEPTION,e); - } - } - - // create and start the servers. - for (int i=0;i<arg.length;i++) - { - try{servers[i].join();} - catch (Exception e){LogSupport.ignore(log,e);} - } - } - - /** - * ShutdownHook thread for stopping all servers. - * - * Thread is hooked first time list of servers is changed. - */ - private static class ShutdownHookThread extends Thread { - private boolean hooked = false; - private ArrayList servers = new ArrayList(); - - /** - * Hooks this thread for shutdown. - * @see java.lang.Runtime#addShutdownHook(java.lang.Thread) - */ - private void createShutdownHook() { - if (!Boolean.getBoolean("JETTY_NO_SHUTDOWN_HOOK") && !hooked) { - try { - Method shutdownHook = java.lang.Runtime.class.getMethod("addShutdownHook", - new Class[] { java.lang.Thread.class }); - shutdownHook.invoke(Runtime.getRuntime(), new Object[] { this }); - this.hooked = true; - } catch (Exception e) { - if (log.isDebugEnabled()) log.debug("No shutdown hook in JVM ", e); - } - } - } - - /** - * Add Server to servers list. - */ - public boolean add(Server server) { - createShutdownHook(); - return this.servers.add(server); - } - - /** - * Contains Server in servers list? - */ - public boolean contains(Server server) { - return this.servers.contains(server); - } - - /** - * Append all Servers from Collection - */ - public boolean addAll(Collection c) { - createShutdownHook(); - return this.servers.addAll(c); - } - - /** - * Clear list of Servers. - */ - public void clear() { - createShutdownHook(); - this.servers.clear(); - } - - /** - * Remove Server from list. - */ - public boolean remove(Server server) { - createShutdownHook(); - return this.servers.remove(server); - } - - /** - * Remove all Servers in Collection from list. - */ - public boolean removeAll(Collection c) { - createShutdownHook(); - return this.servers.removeAll(c); - } - - /** - * Stop all Servers in list. - */ - public void run() { - setName("Shutdown"); - log.info("Shutdown hook executing"); - Iterator it = servers.iterator(); - while (it.hasNext()) { - Server svr = (Server) it.next(); - if (svr == null) continue; - try { - svr.stop(); - } catch (Exception e) { - log.warn(LogSupport.EXCEPTION, e); - } - log.info("Shutdown hook complete"); - - // Try to avoid JVM crash - try { - Thread.sleep(1000); - } catch (Exception e) { - log.warn(LogSupport.EXCEPTION, e); - } - } - } - } -} - - - - diff --git a/apps/jetty/java/src/org/mortbay/util/FileResource.java b/apps/jetty/java/src/org/mortbay/util/FileResource.java deleted file mode 100644 index 8788f14fdf..0000000000 --- a/apps/jetty/java/src/org/mortbay/util/FileResource.java +++ /dev/null @@ -1,352 +0,0 @@ -// ======================================================================== -// $Id: FileResource.java,v 1.31 2006/01/04 13:55:31 gregwilkins Exp $ -// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== -package org.mortbay.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLConnection; -import java.security.Permission; - -import org.apache.commons.logging.Log; -import org.mortbay.log.LogFactory; - - -/* ------------------------------------------------------------ */ -/** File Resource. - * - * Handle resources of implied or explicit file type. - * This class can check for aliasing in the filesystem (eg case - * insensitivity). By default this is turned on if the platform does - * not have the "/" path separator, or it can be controlled with the - * "org.mortbay.util.FileResource.checkAliases" system parameter. - * - * If alias checking is turned on, then aliased resources are - * treated as if they do not exist, nor can they be created. - * - * @version $Revision: 1.31 $ - * @author Greg Wilkins (gregw) - */ -public class FileResource extends URLResource -{ - private static Log log = LogFactory.getLog(Credential.class); - private static boolean __checkAliases; - static - { - __checkAliases= - "true".equalsIgnoreCase - (System.getProperty("org.mortbay.util.FileResource.checkAliases","true")); - - if (__checkAliases) - log.info("Checking Resource aliases"); - } - - /* ------------------------------------------------------------ */ - private File _file; - private transient URL _alias=null; - private transient boolean _aliasChecked=false; - - /* ------------------------------------------------------------------------------- */ - /** setCheckAliases. - * @param checkAliases True of resource aliases are to be checked for (eg case insensitivity or 8.3 short names) and treated as not found. - */ - public static void setCheckAliases(boolean checkAliases) - { - __checkAliases=checkAliases; - } - - /* ------------------------------------------------------------------------------- */ - /** getCheckAliases. - * @return True of resource aliases are to be checked for (eg case insensitivity or 8.3 short names) and treated as not found. - */ - public static boolean getCheckAliases() - { - return __checkAliases; - } - - /* -------------------------------------------------------- */ - FileResource(URL url) - throws IOException, URISyntaxException - { - super(url,null); - - try - { - // Try standard API to convert URL to file. - _file =new File(new URI(url.toString())); - } - catch (Exception e) - { - LogSupport.ignore(log,e); - try - { - // Assume that File.toURL produced unencoded chars. So try - // encoding them. - String urls= - "file:"+org.mortbay.util.URI.encodePath(url.toString().substring(5)); - _file =new File(new URI(urls)); - } - catch (Exception e2) - { - LogSupport.ignore(log,e2); - - // Still can't get the file. Doh! try good old hack! - checkConnection(); - Permission perm = _connection.getPermission(); - _file = new File(perm==null?url.getFile():perm.getName()); - } - } - - if (_file.isDirectory() && !_urlString.endsWith("/")) - _urlString=_urlString+"/"; - } - - /* -------------------------------------------------------- */ - FileResource(URL url, URLConnection connection, File file) - { - super(url,connection); - _file=file; - if (_file.isDirectory() && !_urlString.endsWith("/")) - _urlString=_urlString+"/"; - } - - /* -------------------------------------------------------- */ - public Resource addPath(String path) - throws IOException,MalformedURLException - { - FileResource r=null; - - if (!isDirectory()) - { - r=(FileResource)super.addPath(path); - } - else - { - path = org.mortbay.util.URI.canonicalPath(path); - - // treat all paths being added as relative - String rel=path; - if (path.startsWith("/")) - rel = path.substring(1); - - File newFile = new File(_file,rel.replace('/', File.separatorChar)); - r=new FileResource(newFile.toURI().toURL(),null,newFile); - } - - String encoded=org.mortbay.util.URI.encodePath(path); - int expected=r._urlString.length()-encoded.length(); - int index = r._urlString.lastIndexOf(encoded, expected); - - if (expected!=index && ((expected-1)!=index || path.endsWith("/") || !r.isDirectory())) - { - r._alias=r._url; - r._aliasChecked=true; - } - return r; - } - - - /* ------------------------------------------------------------ */ - public URL getAlias() - { - if (__checkAliases) { - if (!_aliasChecked) - { - try - { - String abs=_file.getAbsolutePath(); - String can=_file.getCanonicalPath(); - - if (abs.length()!=can.length() || !abs.equals(can)) - _alias=new File(can).toURI().toURL(); - - _aliasChecked=true; - - if (_alias!=null && log.isDebugEnabled()) - { - log.debug("ALIAS abs="+abs); - log.debug("ALIAS can="+can); - } - } - catch(Exception e) - { - log.warn(LogSupport.EXCEPTION,e); - return getURL(); - } - } - } else return null; - return _alias; - } - - /* -------------------------------------------------------- */ - /** - * Returns true if the resource exists. - */ - public boolean exists() - { - return _file.exists(); - } - - /* -------------------------------------------------------- */ - /** - * Returns the last modified time - */ - public long lastModified() - { - return _file.lastModified(); - } - - /* -------------------------------------------------------- */ - /** - * Returns true if the respresenetd resource is a container/directory. - */ - public boolean isDirectory() - { - return _file.isDirectory(); - } - - /* --------------------------------------------------------- */ - /** - * Return the length of the resource - */ - public long length() - { - return _file.length(); - } - - - /* --------------------------------------------------------- */ - /** - * Returns the name of the resource - */ - public String getName() - { - return _file.getAbsolutePath(); - } - - /* ------------------------------------------------------------ */ - /** - * Returns an File representing the given resource or NULL if this - * is not possible. - */ - public File getFile() - { - return _file; - } - - /* --------------------------------------------------------- */ - /** - * Returns an input stream to the resource - */ - public InputStream getInputStream() throws IOException - { - return new FileInputStream(_file); - } - - /* --------------------------------------------------------- */ - /** - * Returns an output stream to the resource - */ - public OutputStream getOutputStream() - throws java.io.IOException, SecurityException - { - return new FileOutputStream(_file); - } - - /* --------------------------------------------------------- */ - /** - * Deletes the given resource - */ - public boolean delete() - throws SecurityException - { - return _file.delete(); - } - - /* --------------------------------------------------------- */ - /** - * Rename the given resource - */ - public boolean renameTo( Resource dest) - throws SecurityException - { - if( dest instanceof FileResource) - return _file.renameTo( ((FileResource)dest)._file); - else - return false; - } - - /* --------------------------------------------------------- */ - /** - * Returns a list of resources contained in the given resource - */ - public String[] list() - { - String[] list =_file.list(); - if (list==null) - return null; - for (int i=list.length;i-->0;) - { - if (new File(_file,list[i]).isDirectory() && - !list[i].endsWith("/")) - list[i]+="/"; - } - return list; - } - - /* ------------------------------------------------------------ */ - /** Encode according to this resource type. - * File URIs are encoded. - * @param uri URI to encode. - * @return The uri unchanged. - */ - public String encode(String uri) - { - return uri; - } - - /* ------------------------------------------------------------ */ - /** - * @param o - * @return - */ - public boolean equals( Object o) - { - if (this == o) - return true; - - if (null == o || ! (o instanceof FileResource)) - return false; - - FileResource f=(FileResource)o; - return f._file == _file || (null != _file && _file.equals(f._file)); - } - - /* ------------------------------------------------------------ */ - /** - * @return the hashcode. - */ - public int hashCode() - { - return null == _file ? super.hashCode() : _file.hashCode(); - } -} diff --git a/apps/jetty/java/src/org/mortbay/util/InetAddrPort.java b/apps/jetty/java/src/org/mortbay/util/InetAddrPort.java deleted file mode 100644 index 7f0968798c..0000000000 --- a/apps/jetty/java/src/org/mortbay/util/InetAddrPort.java +++ /dev/null @@ -1,253 +0,0 @@ -// ======================================================================== -// $Id: InetAddrPort.java,v 1.7 2004/10/23 09:03:22 gregwilkins Exp $ -// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== - -package org.mortbay.util; - -import java.io.Serializable; -import java.net.InetAddress; - -/* ======================================================================== */ -/** InetAddress and Port. - */ -public class InetAddrPort implements Serializable -{ - /* ------------------------------------------------------------ */ - public final static String __0_0_0_0 = "0.0.0.0"; - - /* ------------------------------------------------------------ */ - private InetAddress _addr=null; - private boolean _addrIsHost=false; - private int _port=0; - - /* ------------------------------------------------------------------- */ - public InetAddrPort() - {} - - /* ------------------------------------------------------------ */ - /** Constructor for a port on all local host address. - * @param port - */ - public InetAddrPort(int port) - { - _port=port; - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param addr - * @param port - */ - public InetAddrPort(InetAddress addr, int port) - { - _addr=addr; - _port=port; - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param host - * @param port - */ - public InetAddrPort(String host, int port) - throws java.net.UnknownHostException - { - setHost(host); - setPort(port); - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * Patched to support [::1]:port for I2P - * - * @param inetAddrPort String of the form "addr:port" - */ - public InetAddrPort(String inetAddrPort) - throws java.net.UnknownHostException - { - int b = inetAddrPort.indexOf('['); - if (b>0) - throw new java.net.UnknownHostException("Bad [] syntax"); - if (b==0) // IPV6 - { - int b2 = inetAddrPort.indexOf(']'); - if (b2<2) - throw new java.net.UnknownHostException("Bad [] syntax"); - String addr=inetAddrPort.substring(1,b2); - if (addr.indexOf('/')>0) - addr=addr.substring(addr.indexOf('/')+1); - inetAddrPort=inetAddrPort.substring(b2+1); - int c = inetAddrPort.indexOf(':'); - if (c>0) - throw new java.net.UnknownHostException("Bad [] syntax"); - if (c==0) - inetAddrPort=inetAddrPort.substring(1); - - if (addr.length()>0 && ! __0_0_0_0.equals(addr)) - { - _addrIsHost=!Character.isDigit((addr.charAt(0))); - this._addr=InetAddress.getByName(addr); - } - } else { // IPV4 - int c = inetAddrPort.indexOf(':'); - if (c>=0) - { - String addr=inetAddrPort.substring(0,c); - if (addr.indexOf('/')>0) - addr=addr.substring(addr.indexOf('/')+1); - inetAddrPort=inetAddrPort.substring(c+1); - - if (addr.length()>0 && ! __0_0_0_0.equals(addr)) - { - _addrIsHost=!Character.isDigit((addr.charAt(0))); - this._addr=InetAddress.getByName(addr); - } - } - } - - _port = Integer.parseInt(inetAddrPort); - } - - /* ------------------------------------------------------------ */ - /** Constructor. - * @param address InetAddrPort top copy. - */ - public InetAddrPort(InetAddrPort address) - { - if (address!=null) - { - _addr=address._addr; - _port=address._port; - } - } - - /* ------------------------------------------------------------ */ - /** Get the Host. - * @return The IP address - */ - public String getHost() - { - if (_addr==null) - return __0_0_0_0; - - return _addrIsHost?_addr.getHostName():_addr.getHostAddress(); - } - - /* ------------------------------------------------------------ */ - /** Set the Host. - * @param host - * @exception java.net.UnknownHostException - */ - public void setHost(String host) - throws java.net.UnknownHostException - { - _addr=null; - if (host!=null) - { - if (host.indexOf('/')>0) - host=host.substring(0,host.indexOf('/')); - _addrIsHost=!Character.isDigit((host.charAt(0))); - _addr=InetAddress.getByName(host); - } - } - - /* ------------------------------------------------------------ */ - /** Get the IP address. - * @return The IP address - */ - public InetAddress getInetAddress() - { - return _addr; - } - - /* ------------------------------------------------------------ */ - /** Set the IP address. - * @param addr The IP address - */ - public void setInetAddress(InetAddress addr) - { - _addrIsHost=false; - _addr=addr; - } - - /* ------------------------------------------------------------ */ - /** Get the port. - * @return The port number - */ - public int getPort() - { - return _port; - } - - /* ------------------------------------------------------------ */ - /** Set the port. - * @param port The port number - */ - public void setPort(int port) - { - _port=port; - } - - - /* ------------------------------------------------------------------- */ - public String toString() - { - return getHost()+':'+_port; - } - - /* ------------------------------------------------------------ */ - /** Clone the InetAddrPort. - * @return A new instance. - */ - public Object clone() - { - return new InetAddrPort(this); - } - - /* ------------------------------------------------------------ */ - /** Hash Code. - * @return hash Code. - */ - public int hashCode() - { - return _port+((_addr==null)?0:_addr.hashCode()); - } - - /* ------------------------------------------------------------ */ - /** Equals. - * @param o - * @return True if is the same address and port. - */ - public boolean equals(Object o) - { - if (o==null) - return false; - if (o==this) - return true; - if (o instanceof InetAddrPort) - { - InetAddrPort addr=(InetAddrPort)o; - return addr._port==_port && - ( addr._addr==_addr || - addr._addr!=null && addr._addr.equals(_addr)); - } - return false; - } -} - - - - - - diff --git a/apps/jetty/java/src/org/mortbay/util/Resource.java b/apps/jetty/java/src/org/mortbay/util/Resource.java deleted file mode 100644 index ed992cfd55..0000000000 --- a/apps/jetty/java/src/org/mortbay/util/Resource.java +++ /dev/null @@ -1,431 +0,0 @@ -// ======================================================================== -// $Id: Resource.java,v 1.32 2009/05/16 01:53:36 gregwilkins Exp $ -// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== -package org.mortbay.util; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Serializable; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.text.DateFormat; -import java.util.Arrays; -import java.util.Date; - -import org.apache.commons.logging.Log; -import org.mortbay.log.LogFactory; - - -/* ------------------------------------------------------------ */ -/** Abstract resource class. - * - * @version $Id: Resource.java,v 1.32 2009/05/16 01:53:36 gregwilkins Exp $ - * @author Nuno Preguica - * @author Greg Wilkins (gregw) - */ -public abstract class Resource implements Serializable -{ - private static Log log = LogFactory.getLog(Resource.class); - - Object _associate; - - /* ------------------------------------------------------------ */ - /** Construct a resource from a url. - * @param url A URL. - * @return A Resource object. - */ - public static Resource newResource(URL url) - throws IOException - { - if (url==null) - return null; - - String urls=url.toExternalForm(); - if( urls.startsWith( "file:")) - { - try - { - FileResource fileResource= new FileResource(url); - return fileResource; - } - catch(Exception e) - { - log.debug(LogSupport.EXCEPTION,e); - return new BadResource(url,e.toString()); - } - } - else if( urls.startsWith( "jar:file:")) - { - return new JarFileResource(url); - } - else if( urls.startsWith( "jar:")) - { - return new JarResource(url); - } - - return new URLResource(url,null); - } - - /* ------------------------------------------------------------ */ - /** Construct a resource from a string. - * @param resource A URL or filename. - * @return A Resource object. - */ - public static Resource newResource(String resource) - throws MalformedURLException, IOException - { - URL url=null; - try - { - // Try to format as a URL? - url = new URL(resource); - } - catch(MalformedURLException e) - { - if(!resource.startsWith("ftp:") && - !resource.startsWith("file:") && - !resource.startsWith("jar:")) - { - try - { - // It's a file. - if (resource.startsWith("./")) - resource=resource.substring(2); - - File file=new File(resource).getCanonicalFile(); - url=file.toURI().toURL(); - - URLConnection connection=url.openConnection(); - FileResource fileResource= new FileResource(url,connection,file); - return fileResource; - } - catch(Exception e2) - { - log.debug(LogSupport.EXCEPTION,e2); - throw e; - } - } - else - { - log.warn("Bad Resource: "+resource); - throw e; - } - } - - String nurl=url.toString(); - if (nurl.length()>0 && - nurl.charAt(nurl.length()-1)!= - resource.charAt(resource.length()-1)) - { - if ((nurl.charAt(nurl.length()-1)!='/' || - nurl.charAt(nurl.length()-2)!=resource.charAt(resource.length()-1)) - && - (resource.charAt(resource.length()-1)!='/' || - resource.charAt(resource.length()-2)!=nurl.charAt(nurl.length()-1) - )) - { - return new BadResource(url,"Trailing special characters stripped by URL in "+resource); - } - } - return newResource(url); - } - - /* ------------------------------------------------------------ */ - /** Construct a system resource from a string. - * The resource is tried as classloader resource before being - * treated as a normal resource. - */ - public static Resource newSystemResource(String resource) - throws IOException - { - URL url=null; - // Try to format as a URL? - ClassLoader - loader=Thread.currentThread().getContextClassLoader(); - if (loader!=null) - { - url=loader.getResource(resource); - if (url==null && resource.startsWith("/")) - url=loader.getResource(resource.substring(1)); - } - if (url==null) - { - loader=Resource.class.getClassLoader(); - if (loader!=null) - { - url=loader.getResource(resource); - if (url==null && resource.startsWith("/")) - url=loader.getResource(resource.substring(1)); - } - } - - if (url==null) - { - url=ClassLoader.getSystemResource(resource); - if (url==null && resource.startsWith("/")) - url=loader.getResource(resource.substring(1)); - } - - if (url==null) - return null; - - return newResource(url); - } - - /* ------------------------------------------------------------ */ - protected void finalize() - { - release(); - } - - /* ------------------------------------------------------------ */ - /** Release any resources held by the resource. - */ - public abstract void release(); - - - /* ------------------------------------------------------------ */ - /** - * Returns true if the respresened resource exists. - */ - public abstract boolean exists(); - - - /* ------------------------------------------------------------ */ - /** - * Returns true if the respresenetd resource is a container/directory. - * If the resource is not a file, resources ending with "/" are - * considered directories. - */ - public abstract boolean isDirectory(); - - /* ------------------------------------------------------------ */ - /** - * Returns the last modified time - */ - public abstract long lastModified(); - - - /* ------------------------------------------------------------ */ - /** - * Return the length of the resource - */ - public abstract long length(); - - - /* ------------------------------------------------------------ */ - /** - * Returns an URL representing the given resource - */ - public abstract URL getURL(); - - - /* ------------------------------------------------------------ */ - /** - * Returns an File representing the given resource or NULL if this - * is not possible. - */ - public abstract File getFile() - throws IOException; - - - /* ------------------------------------------------------------ */ - /** - * Returns the name of the resource - */ - public abstract String getName(); - - - /* ------------------------------------------------------------ */ - /** - * Returns an input stream to the resource - */ - public abstract InputStream getInputStream() - throws java.io.IOException; - - /* ------------------------------------------------------------ */ - /** - * Returns an output stream to the resource - */ - public abstract OutputStream getOutputStream() - throws java.io.IOException, SecurityException; - - /* ------------------------------------------------------------ */ - /** - * Deletes the given resource - */ - public abstract boolean delete() - throws SecurityException; - - /* ------------------------------------------------------------ */ - /** - * Rename the given resource - */ - public abstract boolean renameTo( Resource dest) - throws SecurityException; - - /* ------------------------------------------------------------ */ - /** - * Returns a list of resource names contained in the given resource - * The resource names are not URL encoded. - */ - public abstract String[] list(); - - /* ------------------------------------------------------------ */ - /** - * Returns the resource contained inside the current resource with the - * given name. - * @param path The path segment to add, which should be encoded by the - * encode method. - */ - public abstract Resource addPath(String path) - throws IOException,MalformedURLException; - - - /* ------------------------------------------------------------ */ - /** Encode according to this resource type. - * The default implementation calls URI.encodePath(uri) - * @param uri - * @return String encoded for this resource type. - */ - public String encode(String uri) - { - return URI.encodePath(uri); - } - - - /* ------------------------------------------------------------ */ - public Object getAssociate() - { - return _associate; - } - - /* ------------------------------------------------------------ */ - public void setAssociate(Object o) - { - _associate=o; - } - - /* ------------------------------------------------------------ */ - /** - * @return The canonical Alias of this resource or null if none. - */ - public URL getAlias() - { - return null; - } - - - /* ------------------------------------------------------------ */ - public CachedResource cache() - throws IOException - { - return new CachedResource(this); - } - - /* ------------------------------------------------------------ */ - /** Get the resource list as a HTML directory listing. - * @param base The base URL - * @param parent True if the parent directory should be included - * @return String of HTML - */ - public String getListHTML(String base, - boolean parent) - throws IOException - { - if (!isDirectory()) - return null; - - - String[] ls = list(); - if (ls==null) - return null; - Arrays.sort(ls); - - String title = "Directory: "+URI.decodePath(base); - title=StringUtil.replace(StringUtil.replace(title,"<","<"),">",">"); - StringBuffer buf=new StringBuffer(4096); - buf.append("<HTML><HEAD><TITLE>"); - buf.append(title); - buf.append("\n

"); - buf.append(title); - buf.append("

"); - - if (parent) - { - buf.append("\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("\n"); - } - buf.append("
Parent Directory
"); - buf.append(StringUtil.replace(StringUtil.replace(ls[i],"<","<"),">",">")); - buf.append(" "); - buf.append(""); - buf.append(item.length()); - buf.append(" bytes "); - buf.append(dfmt.format(new Date(item.lastModified()))); - buf.append("
\n"); - buf.append("\n"); - - return buf.toString(); - } - - /* ------------------------------------------------------------ */ - /** - * @param out - * @param start First byte to write - * @param count Bytes to write or -1 for all of them. - */ - public void writeTo(OutputStream out,long start,long count) - throws IOException - { - InputStream in = getInputStream(); - try - { - in.skip(start); - if (count<0) - IO.copy(in,out); - else - IO.copy(in,out,(int)count); - } - finally - { - in.close(); - } - } -} diff --git a/apps/jetty/java/src/org/mortbay/util/URI.java b/apps/jetty/java/src/org/mortbay/util/URI.java deleted file mode 100644 index 867ef19f40..0000000000 --- a/apps/jetty/java/src/org/mortbay/util/URI.java +++ /dev/null @@ -1,1010 +0,0 @@ -// ======================================================================== -// $Id: URI.java,v 1.40 2009/05/16 02:02:00 gregwilkins Exp $ -// Copyright 199-2004 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// ======================================================================== -package org.mortbay.util; - -import java.io.UnsupportedEncodingException; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.mortbay.log.LogFactory; - -/* ------------------------------------------------------------ */ -/** URI Holder. - * This class assists with the decoding and encoding or HTTP URI's. - * It differs from the java.net.URL class as it does not provide - * communications ability, but it does assist with query string - * formatting. - *

ISO_8859_1 encoding is used by default for % encoded characters. This - * may be overridden with the org.mortbay.util.URI.charset system property. - * @see UrlEncoded - * @version $Id: URI.java,v 1.40 2009/05/16 02:02:00 gregwilkins Exp $ - * @author Greg Wilkins (gregw) - */ -public class URI - implements Cloneable -{ - private static Log log = LogFactory.getLog(URI.class); - - public static final String __CHARSET=System.getProperty("org.mortbay.util.URI.charset",StringUtil.__UTF_8); - public static final boolean __CHARSET_IS_DEFAULT=__CHARSET.equals(StringUtil.__UTF_8); - - /* ------------------------------------------------------------ */ - private String _uri; - private String _scheme; - private String _host; - private int _port; - private String _path; - private String _encodedPath; - private String _query; - private UrlEncoded _parameters; - private boolean _dirty; - private static String unreserved = "/0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.~"; - private static String reserved = "!*'();:@&=+$,?%#[]"; - private static String hexchars = "0123456789ABCDEF"; - - /* ------------------------------------------------------------ */ - /** Copy Constructor . - * @param uri - */ - public URI(URI uri) - throws IllegalArgumentException - { - _uri=uri.toString(); - _scheme=uri._scheme; - _host=uri._host; - _port=uri._port; - _path=uri._path; - _encodedPath=uri._encodedPath; - _query=uri._query; - if (uri._parameters!=null) - _parameters=(UrlEncoded)uri._parameters.clone(); - _dirty=false; - } - - /* ------------------------------------------------------------ */ - /** Construct from a String. - * The string must contain a URI path, but optionaly may contain a - * scheme, host, port and query string. - * - * @param uri [scheme://host[:port]]/path[?query] - */ - public URI(String uri) - throws IllegalArgumentException - { - setURI(uri); - } - - /* ------------------------------------------------------------ */ - public void setURI(String uri) - throws IllegalArgumentException - { - try - { - _uri=uri; - _scheme=null; - _host=null; - _port=0; - _path=null; - _encodedPath=null; - _query=null; - if (_parameters!=null) - _parameters.clear(); - - // Scan _uri for host, port, path & query - int maxi=uri.length()-1; - int mark=0; - int state=0; - int i=0; - - if (maxi==0 || uri.charAt(0)=='/' && uri.charAt(1)!='/') - { - state=3; - _scheme=null; - _host=null; - _port=0; - } - else - { - for (i=0;state<3 && i<=maxi;i++) - { - char c=uri.charAt(i); - switch(state) - { - case 0: // looking for scheme or path - if (c==':' && - uri.charAt(i+1)=='/' && - uri.charAt(i+2)=='/') - { - // found end of scheme & start of host - _scheme=uri.substring(mark,i); - i+=2; - mark=i+1; - state=1; - } - else if (i==0 && c=='/') - { - // Found path - state=3; - } - else if (i==0 && c=='*') - { - state=5; - _path="*"; - _encodedPath="*"; - } - continue; - - case 1: // Get host & look for port or path - if (c==':') - { - // found port - _host=uri.substring(mark,i); - mark=i+1; - state=2; - } - else if (c=='/') - { - // found path - _host=uri.substring(mark,i); - mark=i; - state=3; - } - continue; - - case 2: // Get port & look for path - if (c=='/') - { - _port=TypeUtil.parseInt(uri,mark,i-mark,10); - mark=i; - state=3; - } - continue; - } - } - } - - // State 3 - Get path & look for query - _query=null; - for (i++;i<=maxi;i++) - { - char c=uri.charAt(i); - if (c=='?') - { - // Found query - _encodedPath=uri.substring(mark,i); - _path=decodePath(_encodedPath); - - mark=i+1; - state=4; - break; - } - } - - // complete last state - switch(state) - { - case 0: - _dirty=false; - _encodedPath=_uri; - _path=decodePath(_encodedPath); - break; - - case 1: - _dirty=true; - _encodedPath="/"; - _path=_encodedPath; - _host=uri.substring(mark); - break; - - case 2: - _dirty=true; - _encodedPath="/"; - _path=_encodedPath; - _port=TypeUtil.parseInt(uri,mark,-1,10); - break; - case 3: - _dirty=(mark==maxi); - _encodedPath=uri.substring(mark); - _path=decodePath(_encodedPath); - break; - - case 4: - _dirty=false; - if (mark<=maxi) - _query=uri.substring(mark); - break; - - case 5: - _dirty=false; - } - - if (_query!=null && _query.length()>0) - { - if (_parameters==null) - _parameters= new UrlEncoded(); - else - _parameters.clear(); - _parameters.decode(_query,__CHARSET); - - } - else - _query=null; - } - catch (Exception e) - { - LogSupport.ignore(log,e); - throw new IllegalArgumentException("Malformed URI '"+uri+ - "' : "+e.toString()); - } - } - - /* ------------------------------------------------------------ */ - /** Is the URI an absolute URL? - * @return True if the URI has a scheme or host - */ - public boolean isAbsolute() - { - return _scheme!=null || _host!=null; - } - - /* ------------------------------------------------------------ */ - /** Get the uri scheme. - * @return the URI scheme - */ - public String getScheme() - { - return _scheme; - } - - /* ------------------------------------------------------------ */ - /** Set the uri scheme. - * @param scheme the uri scheme - */ - public void setScheme(String scheme) - { - _scheme=scheme; - _dirty=true; - } - - /* ------------------------------------------------------------ */ - /** Get the uri host. - * @return the URI host - */ - public String getHost() - { - return _host; - } - - /* ------------------------------------------------------------ */ - /** Set the uri host. - * @param host the uri host - */ - public void setHost(String host) - { - _host=host; - _dirty=true; - } - - /* ------------------------------------------------------------ */ - /** Get the uri port. - * @return the URI port - */ - public int getPort() - { - return _port; - } - - /* ------------------------------------------------------------ */ - /** Set the uri port. - * A port of 0 implies use the default port. - * @param port the uri port - */ - public void setPort(int port) - { - _port=port; - _dirty=true; - } - - /* ------------------------------------------------------------ */ - /** Get the uri path. - * @return the URI path - */ - public String getPath() - { - return _path; - } - - /* ------------------------------------------------------------ */ - /** Get the encoded uri path. - * @return the URI path - */ - public String getEncodedPath() - { - return _encodedPath; - } - - /* ------------------------------------------------------------ */ - /** Set the uri path. - * @param path the URI path - */ - public void setPath(String path) - { - _path=path; - _encodedPath=encodePath(_path); - _dirty=true; - } - - - /* ------------------------------------------------------------ */ - /** Get the uri query String. - * @return the URI query string - */ - public String getQuery() - { - if (_dirty && _parameters!=null) - { - _query = _parameters.encode(__CHARSET); - if (_query!=null && _query.length()==0) - _query=null; - } - return _query; - } - - /* ------------------------------------------------------------ */ - /** Set the uri query String. - * @param query the URI query string - */ - public void setQuery(String query) - { - _query=query; - - if (_parameters!=null) - _parameters.clear(); - else if (query!=null) - _parameters=new UrlEncoded(); - - if (query!=null) - _parameters.decode(query,__CHARSET); - - cleanURI(); - } - - /* ------------------------------------------------------------ */ - /** Get the uri query _parameters names. - * @return Unmodifiable set of URI query _parameters names - */ - public Set getParameterNames() - { - if (_parameters==null) - return Collections.EMPTY_SET; - return _parameters.keySet(); - } - - /* ------------------------------------------------------------ */ - /** Get the uri query _parameters. - * @return the URI query _parameters - */ - public MultiMap getParameters() - { - if (_parameters==null) - _parameters=new UrlEncoded(); - _dirty=true; - return _parameters; - } - - /* ------------------------------------------------------------ */ - /** Get the uri query _parameters. - * @return the URI query _parameters in an unmodifiable map. - */ - public Map getUnmodifiableParameters() - { - if (_parameters==null) - return Collections.EMPTY_MAP; - return Collections.unmodifiableMap(_parameters); - } - - /* ------------------------------------------------------------ */ - /** Add the uri query _parameters to a MultiMap - */ - public void putParametersTo(MultiMap map) - { - if (_parameters!=null && _parameters.size()>0) - map.putAll(_parameters); - } - - /* ------------------------------------------------------------ */ - /** Clear the URI _parameters. - */ - public void clearParameters() - { - if (_parameters!=null) - { - _dirty=true; - _parameters.clear(); - } - } - - /* ------------------------------------------------------------ */ - /** Add encoded _parameters. - * @param encoded A HTTP encoded string of _parameters: e.g.. "a=1&b=2" - */ - public void put(String encoded) - { - UrlEncoded params = new UrlEncoded(encoded); - put(params); - } - - /* ------------------------------------------------------------ */ - /** Add name value pair to the uri query _parameters. - * @param name name of value - * @param value The value, which may be a multi valued list or - * String array. - */ - public Object put(Object name, Object value) - { - return getParameters().put(name,value); - } - - /* ------------------------------------------------------------ */ - /** Add dictionary to the uri query _parameters. - */ - public void put(Map values) - { - getParameters().putAll(values); - } - - /* ------------------------------------------------------------ */ - /** Get named value - */ - public String get(String name) - { - if (_parameters==null) - return null; - return (String)_parameters.get(name); - } - - /* ------------------------------------------------------------ */ - /** Get named multiple values. - * @param name The parameter name - * @return Umodifiable list of values or null - */ - public List getValues(String name) - { - if (_parameters==null) - return null; - return _parameters.getValues(name); - } - - /* ------------------------------------------------------------ */ - /** Remove named value - */ - public void remove(String name) - { - if (_parameters!=null) - { - _dirty= - _parameters.remove(name)!=null; - } - } - - /* ------------------------------------------------------------ */ - /** @return the URI string encoded. - */ - public String toString() - { - if (_dirty) - { - getQuery(); - cleanURI(); - } - return _uri; - } - - /* ------------------------------------------------------------ */ - private void cleanURI() - { - StringBuffer buf = new StringBuffer(_uri.length()*2); - synchronized(buf) - { - if (_scheme!=null) - { - buf.append(_scheme); - buf.append("://"); - buf.append(_host); - if (_port>0) - { - buf.append(':'); - buf.append(_port); - } - } - - buf.append(_encodedPath); - - if (_query!=null && _query.length()>0) - { - buf.append('?'); - buf.append(_query); - } - _uri=buf.toString(); - _dirty=false; - } - } - - - /* ------------------------------------------------------------ */ - /** Encode a URI path. - * This is the same encoding offered by URLEncoder, except that - * the '/' character is not encoded. - * @param path The path the encode - * @return The encoded path - */ - public static String encodePath(String path) - { - if (path==null || path.length()==0) - return path; - - StringBuffer buf = encodePath(null,path); - return buf==null?path:buf.toString(); - } - - /* ------------------------------------------------------------ */ - /** Encode a URI path. - * @param path The path the encode - * @param buf StringBuffer to encode path into (or null) - * @return The StringBuffer or null if no substitutions required. - */ - public static StringBuffer encodePath(StringBuffer buf, String path) - { - /* Convert path to native character set not __CHARSET. - * This is important to do this way because the path - * contains *OS specific characters* and __CHARSET could - * be wrong and not encode/decode the path correctly. - */ - byte[] b = null; - /* - Keep commented out unless you can prove that this does the right thing. - try { - b = path.getBytes(__CHARSET); - } catch(UnsupportedEncodingException ex) { - return null; // Shouldn't be possible. - } - */ - b = path.getBytes(); - StringBuffer x = new StringBuffer(b.length); - for(int i=0; i> 8) & 0xff)); - buf.append(gethex(c & 0xff)); - } - */ - buf.append(gethex(c & 0xff)); - } else { - buf.append(c); - } - } - } - - return buf; - } - - /** - * - * @param decimal value not greater than 255. - * @return a percent sign followed by two hexadecimal digits. - */ - private static String gethex(int decimal) { - return new String("%" + hexchars.charAt(decimal >> 4) + hexchars.charAt(decimal & 0xF)); - } - /* ------------------------------------------------------------ */ - /** Encode a URI path. - * @param path The path the encode - * @param buf StringBuffer to encode path into (or null) - * @param encode String of characters to encode. % is always encoded. - * @return The StringBuffer or null if no substitutions required. - */ - public static StringBuffer encodeString(StringBuffer buf, - String path, - String encode) - { - if (buf==null) - { - loop: - for (int i=0;i=0) - { - buf=new StringBuffer(path.length()<<1); - break loop; - } - } - if (buf==null) - return null; - } - - synchronized(buf) - { - for (int i=0;i=0) - { - buf.append('%'); - StringUtil.append(buf,(byte)(0xff&c),16); - } - else - buf.append(c); - } - } - - return buf; - } - - /* ------------------------------------------------------------ */ - /* Decode a URI path. - * @param path The path the encode - * @param buf StringBuffer to encode path into - */ - public static String decodePath(String path) - { - int len=path.length(); - byte[] bytes=null; - int n=0; - boolean noDecode=true; - - for (int i=0;i=0) - return p.substring(0,slash+1); - return null; - } - - /* ------------------------------------------------------------ */ - /** Strip parameters from a path. - * Return path upto any semicolon parameters. - */ - public static String stripPath(String path) - { - if (path==null) - return null; - int semi=path.indexOf(';'); - if (semi<0) - return path; - return path.substring(0,semi); - } - - /* ------------------------------------------------------------ */ - /** Convert a path to a cananonical form. - * All instances of "." and ".." are factored out. Null is returned - * if the path tries to .. above it's root. - * @param path - * @return path or null. - */ - public static String canonicalPath(String path) - { - if (path==null || path.length()==0) - return path; - - int end=path.length(); - int start = path.lastIndexOf('/', end); - - search: - while (end>0) - { - switch(end-start) - { - case 2: // possible single dot - if (path.charAt(start+1)!='.') - break; - break search; - case 3: // possible double dot - if (path.charAt(start+1)!='.' || path.charAt(start+2)!='.') - break; - break search; - } - - end=start; - start=path.lastIndexOf('/',end-1); - } - - // If we have checked the entire string - if (start>=end) - return path; - - StringBuffer buf = new StringBuffer(path); - int delStart=-1; - int delEnd=-1; - int skip=0; - - while (end>0) - { - switch(end-start) - { - case 2: // possible single dot - if (buf.charAt(start+1)!='.') - { - if (skip>0 && --skip==0) - { - delStart=start>=0?start:0; - if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.') - delStart++; - } - break; - } - - if(start<0 && buf.length()>2 && buf.charAt(1)=='/' && buf.charAt(2)=='/') - break; - - if(delEnd<0) - delEnd=end; - delStart=start; - if (delStart<0 || delStart==0&&buf.charAt(delStart)=='/') - { - delStart++; - if (delEnd=0 && buf.charAt(start)!='/') - start--; - continue; - - case 3: // possible double dot - if (buf.charAt(start+1)!='.' || buf.charAt(start+2)!='.') - { - if (skip>0 && --skip==0) - { delStart=start>=0?start:0; - if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.') - delStart++; - } - break; - } - - delStart=start; - if (delEnd<0) - delEnd=end; - - skip++; - end=start--; - while (start>=0 && buf.charAt(start)!='/') - start--; - continue; - - default: - if (skip>0 && --skip==0) - { - delStart=start>=0?start:0; - if(delEnd==buf.length() && buf.charAt(delEnd-1)=='.') - delStart++; - } - } - - // Do the delete - if (skip<=0 && delStart>=0 && delStart>=0) - { - buf.delete(delStart,delEnd); - delStart=delEnd=-1; - if (skip>0) - delEnd=end; - } - - end=start--; - while (start>=0 && buf.charAt(start)!='/') - start--; - } - - // Too many .. - if (skip>0) - return null; - - // Do the delete - if (delEnd>=0) - buf.delete(delStart,delEnd); - - return buf.toString(); - } - - /* ------------------------------------------------------------ */ - /** - * @param uri URI - * @return True if the uri has a scheme - */ - public static boolean hasScheme(String uri) - { - for (int i=0;i='a'&&c<='z' || - c>='A'&&c<='Z' || - (i>0 &&(c>='0'&&c<='9' || - c=='.' || - c=='+' || - c=='-')) - )) - break; - } - return false; - } - -} - - - diff --git a/apps/routerconsole/java/build.xml b/apps/routerconsole/java/build.xml index f49153486c..0ce64a59d0 100644 --- a/apps/routerconsole/java/build.xml +++ b/apps/routerconsole/java/build.xml @@ -21,7 +21,11 @@ + + + + @@ -53,7 +57,11 @@ + + + + @@ -233,6 +241,7 @@ + @@ -266,6 +275,10 @@ + + + + diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java index eb28a4b90e..07e65d4d65 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java @@ -14,7 +14,7 @@ import net.i2p.router.client.ClientManagerFacadeImpl; import net.i2p.router.startup.ClientAppConfig; import net.i2p.router.startup.LoadClientAppsJob; -import org.mortbay.jetty.Server; +import org.mortbay.jetty.handler.ContextHandlerCollection; /** * Saves changes to clients.config or webapps.config @@ -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"); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java index b7a892587b..98050bce2f 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java @@ -4,11 +4,13 @@ import java.io.IOException; import java.util.Locale; import java.util.Map; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import net.i2p.I2PAppContext; -import org.mortbay.http.HttpRequest; -import org.mortbay.http.HttpResponse; -import org.mortbay.jetty.servlet.WebApplicationHandler; +import org.mortbay.jetty.webapp.WebAppContext; /** * Convert foo.jsp to foo_xx.jsp for language xx. @@ -19,12 +21,12 @@ import org.mortbay.jetty.servlet.WebApplicationHandler; * * @author zzz */ -public class LocaleWebAppHandler extends WebApplicationHandler +public class LocaleWebAppHandler extends WebAppContext { private final I2PAppContext _context; - public LocaleWebAppHandler(I2PAppContext ctx) { - super(); + public LocaleWebAppHandler(I2PAppContext ctx, String path, String warPath) { + super(warPath, path); _context = ctx; } @@ -36,13 +38,13 @@ public class LocaleWebAppHandler extends WebApplicationHandler */ @Override public void handle(String pathInContext, - String pathParams, - HttpRequest httpRequest, - HttpResponse httpResponse) - throws IOException + HttpServletRequest httpRequest, + HttpServletResponse httpResponse, + int dispatch) + throws IOException, ServletException { // Handle OPTIONS (nothing to override) - if (HttpRequest.__OPTIONS.equals(httpRequest.getMethod())) + if ("OPTIONS".equals(httpRequest.getMethod())) { handleOptions(httpRequest, httpResponse); return; @@ -74,7 +76,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); } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java index 959b8b7974..4ebf32f9df 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java @@ -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() { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java index d1835a3206..614f52c976 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java @@ -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 wars = pluginWars.get(appName).iterator(); while (wars.hasNext()) { String warName = wars.next(); - WebAppStarter.stopWebApp(server, warName); + WebAppStarter.stopWebApp(warName); } pluginWars.get(appName).clear(); } - } + //} // remove summary bar link Properties props = pluginProperties(ctx, appName); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java index 15c7f76f5f..93f549d5ea 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java @@ -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(); @@ -57,6 +72,10 @@ public class RouterConsoleRunner { private static final String DEFAULT_WEBAPPS_DIR = "./webapps/"; private static final String USAGE = "Bad RouterConsoleRunner arguments, check clientApp.0.args in your clients.config file! " + "Usage: [[port host[,host]] [-s sslPort [host[,host]]] [webAppsDir]]"; + + private static final int MIN_THREADS = 1; + private static final int MAX_THREADS = 24; + private static final int MAX_IDLE_TIME = 90*1000; 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 + * + *

+     *	Server
+     *		HandlerCollection
+     *			ContextHandlerCollection
+     *				WebAppContext (i.e. ContextHandler)
+     *					SessionHandler
+     *					SecurityHandler
+     *					ServletHandler
+     *				WebAppContext
+     *				...
+     *			DefaultHandler
+     *			RequestLogHandler (opt)
+     *
+ */ 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 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 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) {} } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java index 0943ea4177..249ae4582e 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppConfiguration.java @@ -6,7 +6,8 @@ import java.util.StringTokenizer; import net.i2p.I2PAppContext; -import org.mortbay.jetty.servlet.WebApplicationContext; +import org.mortbay.jetty.webapp.Configuration; +import org.mortbay.jetty.webapp.WebAppContext; /** @@ -31,16 +32,16 @@ import org.mortbay.jetty.servlet.WebApplicationContext; * @since 0.7.12 * @author zzz */ -public class WebAppConfiguration implements WebApplicationContext.Configuration { - private WebApplicationContext _wac; +public class WebAppConfiguration implements Configuration { + private WebAppContext _wac; private static final String CLASSPATH = ".classpath"; - public void setWebApplicationContext(WebApplicationContext context) { + public void setWebAppContext(WebAppContext context) { _wac = context; } - public WebApplicationContext getWebApplicationContext() { + public WebAppContext getWebAppContext() { return _wac; } @@ -87,10 +88,16 @@ public class WebAppConfiguration implements WebApplicationContext.Configuration else path = dir.getAbsolutePath() + '/' + elem; System.err.println("Adding " + path + " to classpath for " + appName); - _wac.addClassPath(path); + _wac.setExtraClasspath(path); } } public void configureDefaults() {} public void configureWebApp() {} + + /** @since Jetty 6 */ + public void deconfigureWebApp() {} + + /** @since Jetty 6 */ + public void configureClassLoader() {} } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java index 9c47190c14..0c4d7ac473 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/WebAppStarter.java @@ -14,10 +14,12 @@ import net.i2p.util.Log; import net.i2p.util.SecureDirectory; import net.i2p.util.PortMapper; -import org.mortbay.http.HttpContext; -import org.mortbay.http.HttpListener; +import org.mortbay.jetty.Connector; +import org.mortbay.jetty.Handler; import org.mortbay.jetty.Server; -import org.mortbay.jetty.servlet.WebApplicationContext; +import org.mortbay.jetty.webapp.WebAppContext; +import org.mortbay.jetty.handler.ContextHandler; +import org.mortbay.jetty.handler.ContextHandlerCollection; /** @@ -49,9 +51,10 @@ public class WebAppStarter { * adds and starts * @throws just about anything, caller would be wise to catch Throwable */ - static void startWebApp(I2PAppContext ctx, Server server, String appName, String warPath) throws Exception { + static void startWebApp(I2PAppContext ctx, ContextHandlerCollection server, + String appName, String warPath) throws Exception { File tmpdir = new SecureDirectory(ctx.getTempDir(), "jetty-work-" + appName + ctx.random().nextInt()); - WebApplicationContext wac = addWebApp(ctx, server, appName, warPath, tmpdir); + WebAppContext wac = addWebApp(ctx, server, appName, warPath, tmpdir); _log.debug("Loading war from: " + warPath); wac.start(); } @@ -61,12 +64,13 @@ public class WebAppStarter { * This is used only by RouterConsoleRunner, which adds all the webapps first * and then starts all at once. */ - static WebApplicationContext addWebApp(I2PAppContext ctx, Server server, String appName, String warPath, File tmpdir) throws IOException { + static WebAppContext addWebApp(I2PAppContext ctx, ContextHandlerCollection server, + String appName, String warPath, File tmpdir) throws IOException { // Jetty will happily load one context on top of another without stopping // the first one, so we remove any previous one here try { - stopWebApp(server, appName); + stopWebApp(appName); } catch (Throwable t) {} // To avoid ZipErrors from JarURLConnetion caching, @@ -91,7 +95,7 @@ public class WebAppStarter { warPath = tmpPath; } - WebApplicationContext wac = server.addWebApplication("/"+ appName, warPath); + WebAppContext wac = new WebAppContext(warPath, "/"+ appName); tmpdir.mkdir(); wac.setTempDirectory(tmpdir); @@ -101,12 +105,14 @@ public class WebAppStarter { // see WebAppConfiguration for info - String[] classNames = server.getWebApplicationConfigurationClassNames(); + String[] classNames = wac.getConfigurationClasses(); String[] newClassNames = new String[classNames.length + 1]; for (int j = 0; j < classNames.length; j++) newClassNames[j] = classNames[j]; newClassNames[classNames.length] = WebAppConfiguration.class.getName(); - wac.setConfigurationClassNames(newClassNames); + wac.setConfigurationClasses(newClassNames); + server.addHandler(wac); + server.mapContexts(); return wac; } @@ -114,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; + } } diff --git a/apps/susidns/src/build.xml b/apps/susidns/src/build.xml index d287e5a4d0..156492ea58 100644 --- a/apps/susidns/src/build.xml +++ b/apps/susidns/src/build.xml @@ -17,6 +17,7 @@ + diff --git a/apps/susimail/build.xml b/apps/susimail/build.xml index 8a8d33c4ad..b660be49e3 100644 --- a/apps/susimail/build.xml +++ b/apps/susimail/build.xml @@ -19,6 +19,7 @@ + diff --git a/apps/susimail/src/WEB-INF/web.xml b/apps/susimail/src/WEB-INF/web.xml index bab239ed07..e3f93d229f 100644 --- a/apps/susimail/src/WEB-INF/web.xml +++ b/apps/susimail/src/WEB-INF/web.xml @@ -15,4 +15,26 @@ 15 - + + + +- diff --git a/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java b/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java index 98350708ca..c02aae599f 100644 --- a/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java +++ b/apps/susimail/src/src/i2p/susi/webmail/RequestWrapper.java @@ -35,6 +35,19 @@ import javax.servlet.http.HttpSession; import org.mortbay.servlet.MultiPartRequest; /** + * Required major changes for Jetty 6 + * to support change from MultiPartRequest to MultiPartFilter. + * See http://docs.codehaus.org/display/JETTY/File+Upload+in+jetty6 + * Unfortunately, Content-type not available until Jetty 8 + * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=349110 + * + * So we could either extend and fix MultiPartFilter, and rewrite everything here, + * or copy MultiParRequest into our war and fix it so it compiles with Jetty 6. + * We do the latter. + * + * The filter would have been added in web.xml, + * see that file, where it's commented out. + * * @author user */ public class RequestWrapper { diff --git a/build.properties b/build.properties index 9ae4afb969..2f7920cba8 100644 --- a/build.properties +++ b/build.properties @@ -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/ diff --git a/build.xml b/build.xml index 51715be3fd..4efacca7a9 100644 --- a/build.xml +++ b/build.xml @@ -194,12 +194,9 @@ - - - - - - + + + @@ -391,9 +388,10 @@ + - + @@ -412,10 +410,16 @@ + + + + + + @@ -670,14 +674,12 @@ - - - - - + + + + - @@ -724,20 +726,13 @@ - - - - - - - - + + - @@ -931,14 +926,18 @@ + - - - - - - + + + + + diff --git a/installer/resources/clients.config b/installer/resources/clients.config index 08c6c62ba8..8d408cb17a 100644 --- a/installer/resources/clients.config +++ b/installer/resources/clients.config @@ -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 diff --git a/installer/resources/eepsite/contexts/base-context.xml b/installer/resources/eepsite/contexts/base-context.xml new file mode 100644 index 0000000000..1eac073303 --- /dev/null +++ b/installer/resources/eepsite/contexts/base-context.xml @@ -0,0 +1,25 @@ + + + + + + + / + ./eepsite/docroot/ + + + + + index.html + + + max-age=3600,public + + + + diff --git a/installer/resources/eepsite/contexts/cgi-context.xml b/installer/resources/eepsite/contexts/cgi-context.xml new file mode 100644 index 0000000000..68ffa38aad --- /dev/null +++ b/installer/resources/eepsite/contexts/cgi-context.xml @@ -0,0 +1,33 @@ + + + + + + + /cgi-bin + + + ./eepsite/cgi-bin/ + + + + diff --git a/installer/resources/eepsite.help/help/index.html b/installer/resources/eepsite/docroot/help/index.html similarity index 100% rename from installer/resources/eepsite.help/help/index.html rename to installer/resources/eepsite/docroot/help/index.html diff --git a/installer/resources/eepsite.help/help/index_de.html b/installer/resources/eepsite/docroot/help/index_de.html similarity index 100% rename from installer/resources/eepsite.help/help/index_de.html rename to installer/resources/eepsite/docroot/help/index_de.html diff --git a/installer/resources/eepsite.help/help/index_fr.html b/installer/resources/eepsite/docroot/help/index_fr.html similarity index 100% rename from installer/resources/eepsite.help/help/index_fr.html rename to installer/resources/eepsite/docroot/help/index_fr.html diff --git a/installer/resources/eepsite.help/help/index_na.html b/installer/resources/eepsite/docroot/help/index_na.html similarity index 100% rename from installer/resources/eepsite.help/help/index_na.html rename to installer/resources/eepsite/docroot/help/index_na.html diff --git a/installer/resources/eepsite.help/help/index_nl.html b/installer/resources/eepsite/docroot/help/index_nl.html similarity index 100% rename from installer/resources/eepsite.help/help/index_nl.html rename to installer/resources/eepsite/docroot/help/index_nl.html diff --git a/installer/resources/eepsite.help/help/index_ru.html b/installer/resources/eepsite/docroot/help/index_ru.html similarity index 100% rename from installer/resources/eepsite.help/help/index_ru.html rename to installer/resources/eepsite/docroot/help/index_ru.html diff --git a/installer/resources/eepsite.help/help/index_sv.html b/installer/resources/eepsite/docroot/help/index_sv.html similarity index 100% rename from installer/resources/eepsite.help/help/index_sv.html rename to installer/resources/eepsite/docroot/help/index_sv.html diff --git a/installer/resources/eepsite.help/help/lib/bg.png b/installer/resources/eepsite/docroot/help/lib/bg.png similarity index 100% rename from installer/resources/eepsite.help/help/lib/bg.png rename to installer/resources/eepsite/docroot/help/lib/bg.png diff --git a/installer/resources/eepsite.help/help/lib/brown.png b/installer/resources/eepsite/docroot/help/lib/brown.png similarity index 100% rename from installer/resources/eepsite.help/help/lib/brown.png rename to installer/resources/eepsite/docroot/help/lib/brown.png diff --git a/installer/resources/eepsite.help/help/lib/eepsite.css b/installer/resources/eepsite/docroot/help/lib/eepsite.css similarity index 100% rename from installer/resources/eepsite.help/help/lib/eepsite.css rename to installer/resources/eepsite/docroot/help/lib/eepsite.css diff --git a/installer/resources/eepsite.help/help/lib/h2bg.png b/installer/resources/eepsite/docroot/help/lib/h2bg.png similarity index 100% rename from installer/resources/eepsite.help/help/lib/h2bg.png rename to installer/resources/eepsite/docroot/help/lib/h2bg.png diff --git a/installer/resources/eepsite.help/help/lib/itoopie.png b/installer/resources/eepsite/docroot/help/lib/itoopie.png similarity index 100% rename from installer/resources/eepsite.help/help/lib/itoopie.png rename to installer/resources/eepsite/docroot/help/lib/itoopie.png diff --git a/installer/resources/eepsite.help/help/pagetemplate.html b/installer/resources/eepsite/docroot/help/pagetemplate.html similarity index 100% rename from installer/resources/eepsite.help/help/pagetemplate.html rename to installer/resources/eepsite/docroot/help/pagetemplate.html diff --git a/installer/resources/eepsite.help/index.html b/installer/resources/eepsite/docroot/index.html similarity index 100% rename from installer/resources/eepsite.help/index.html rename to installer/resources/eepsite/docroot/index.html diff --git a/installer/resources/eepsite.help/robots.txt b/installer/resources/eepsite/docroot/robots.txt similarity index 100% rename from installer/resources/eepsite.help/robots.txt rename to installer/resources/eepsite/docroot/robots.txt diff --git a/installer/resources/eepsite/etc/realm.properties b/installer/resources/eepsite/etc/realm.properties new file mode 100644 index 0000000000..f9e4e7fa3c --- /dev/null +++ b/installer/resources/eepsite/etc/realm.properties @@ -0,0 +1,21 @@ +# +# This file defines users passwords and roles for a HashUserRealm +# +# The format is +# : [, ...] +# +# Passwords may be clear text, obfuscated or checksummed. The class +# org.mortbay.util.Password should be used to generate obfuscated +# passwords or password checksums +# +# If DIGEST Authentication is used, the password must be in a recoverable +# format, either plain text or OBF:. +# +jetty: MD5:164c88b302622e17050af52c89945d44,user +admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin +other: OBF:1xmk1w261u9r1w1c1xmq +plain: plain +user: password + +# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password +digest: MD5:6e120743ad67abfbc385bc2bb754e297 diff --git a/installer/resources/eepsite/jetty.xml b/installer/resources/eepsite/jetty.xml new file mode 100644 index 0000000000..632c54afa0 --- /dev/null +++ b/installer/resources/eepsite/jetty.xml @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 127.0.0.1 + 7658 + 60000 + 2 + false + 8443 + 5000 + 5000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ./eepsite/contexts + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ./eepsite/logs/yyyy_mm_dd.request.log + yyyy_MM_dd + 90 + true + false + false + GMT + + + + + + + + true + false + true + 1000 + + diff --git a/installer/resources/jetty.xml b/installer/resources/jetty.xml deleted file mode 100644 index a5072d8d75..0000000000 --- a/installer/resources/jetty.xml +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 127.0.0.1 - 7658 - - - 1 - 16 - 60000 - 1000 - 8443 - 8443 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - root - - - - - - - - - - - - - - - / - ./eepsite/docroot - - - - FALSE - - - - GET - HEAD - POST - - - - - - - - - - - /cgi-bin/* - ./eepsite/cgi-bin - - Common Gateway Interface - / - org.mortbay.servlet.CGI - /usr/local/bin:/usr/ucb:/bin:/usr/bin - - - - - - - - - ./eepsite/logs/yyyy_mm_dd.request.log - 90 - true - false - false - GMT - - - - - - - 2000 - - - diff --git a/router/java/src/net/i2p/router/startup/WorkingDir.java b/router/java/src/net/i2p/router/startup/WorkingDir.java index a1f414ac29..648b2ff0c8 100644 --- a/router/java/src/net/i2p/router/startup/WorkingDir.java +++ b/router/java/src/net/i2p/router/startup/WorkingDir.java @@ -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(""); - 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;