[jboss-cvs] Repository SVN: r26738 - in apache-tomcat: 5.5.9.patch07-brew and 2 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Wed May 6 17:11:35 EDT 2009
Author: dknox at redhat.com
Date: 2009-05-06 17:11:34 -0400 (Wed, 06 May 2009)
New Revision: 26738
Added:
apache-tomcat/5.5.9.patch07-brew/
apache-tomcat/5.5.9.patch07-brew/component-info.xml
apache-tomcat/5.5.9.patch07-brew/lib/
apache-tomcat/5.5.9.patch07-brew/lib/catalina-manager.jar
apache-tomcat/5.5.9.patch07-brew/lib/catalina-optional.jar
apache-tomcat/5.5.9.patch07-brew/lib/catalina.jar
apache-tomcat/5.5.9.patch07-brew/lib/jasper-compiler-jdt.jar
apache-tomcat/5.5.9.patch07-brew/lib/jasper-compiler.jar
apache-tomcat/5.5.9.patch07-brew/lib/jasper-runtime.jar
apache-tomcat/5.5.9.patch07-brew/lib/naming-resources.jar
apache-tomcat/5.5.9.patch07-brew/lib/servlets-default.jar
apache-tomcat/5.5.9.patch07-brew/lib/servlets-invoker.jar
apache-tomcat/5.5.9.patch07-brew/lib/servlets-webdav.jar
apache-tomcat/5.5.9.patch07-brew/lib/tomcat-ajp.jar
apache-tomcat/5.5.9.patch07-brew/lib/tomcat-coyote.jar
apache-tomcat/5.5.9.patch07-brew/lib/tomcat-http.jar
apache-tomcat/5.5.9.patch07-brew/lib/tomcat-util.jar
apache-tomcat/5.5.9.patch07-brew/src/
apache-tomcat/5.5.9.patch07-brew/src/jakarta-tomcat-5.5.9-src.tar.gz
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5-CVE-2007-5461-webdav.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-Bug36863-backport.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2005-2090.5.0.x.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-3835.5.5.x.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-7195.5.0.x.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-7196.5.x.y.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-0450.5.5.9.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-1858.5.5.9.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-2449.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-2450_CVE-2007-3386.5.0.x.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-3382_CVE-2007-3385.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-5333.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-5342.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-0128.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-1232.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-1947.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-2370.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-2938.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-IT168408.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-jboss.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-removeJSSEfor13.patch
apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9.patch01-JspServlet-5.15.17-backport.patch
Log:
ASPATCH-360 JBossAS-4.0.2.GA_CP12, JBossAS-4.0.3.SP1_CP19 Security Update for Tomcat 5.5.9 (CVE-2007-5333) 5.5.9.patch07-brew
Added: apache-tomcat/5.5.9.patch07-brew/component-info.xml
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/component-info.xml (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/component-info.xml 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,54 @@
+<project name="apache-tomcat-component-info">
+
+ <component id="apache-tomcat"
+ licenseType="apache-2.0"
+ version="5.5.9.patch07-brew"
+ projectHome="http://jakarta.apache.org/tomcat/index.html"
+ description="Tomcat 5.5 servlet 2.4 web container with a fix for the JBAS-2866, as well as backported fixes for CVE-2005-2090, CVE-2006-3835, CVE-2006-7195, CVE-2007-0450, CVE-2007-1858, CVE-2005-3510, plus fixes for CVE-2007-2450 and CVE-2007-3386 and fixes for CVE-2007-5461, also CVE-2007-5342, CVE-2007-3382, CVE-2007-3385, CVE-2007-2449, CVE-2008-0128, CVE-2007-1355, CVE-2006-7196 and IT 168408, and CVE-2008-1947, CVE-2008-2938, CVE-2008-1232, CVE-2008-2370, CVE-2007-5333">
+ <!-- cvsroot=":ext:cvs.devel.redhat.com:/cvs/dist/tomcat5"
+ tag="tomcat5-5_5_9-3_patch07_1jpp_1jb"
+ -->
+ <artifact id="catalina-manager.jar"/>
+ <artifact id="catalina-optional.jar"/>
+ <artifact id="catalina.jar"/>
+ <artifact id="jasper-compiler-jdt.jar"/>
+ <artifact id="jasper-compiler.jar"/>
+ <artifact id="jasper-runtime.jar"/>
+ <artifact id="naming-resources.jar"/>
+ <artifact id="servlets-default.jar"/>
+ <artifact id="servlets-invoker.jar"/>
+ <artifact id="servlets-webdav.jar"/>
+ <artifact id="tomcat-ajp.jar"/>
+ <artifact id="tomcat-coyote.jar"/>
+ <artifact id="tomcat-http.jar"/>
+ <artifact id="tomcat-util.jar"/>
+
+ <import componentref="apache-logging">
+ <compatible version="1.0.3"/>
+ <compatible version="1.0.4jboss"/>
+ </import>
+ <import componentref="apache-modeler">
+ <compatible version="1.1"/>
+ </import>
+ <import componentref="commons-el">
+ <compatible version="1.0"/>
+ </import>
+ <export>
+ <include input="catalina-manager.jar"/>
+ <include input="catalina-optional.jar"/>
+ <include input="catalina.jar"/>
+ <include input="jasper-compiler-jdt.jar"/>
+ <include input="jasper-compiler.jar"/>
+ <include input="jasper-runtime.jar"/>
+ <include input="naming-resources.jar"/>
+ <include input="servlets-default.jar"/>
+ <include input="servlets-invoker.jar"/>
+ <include input="servlets-webdav.jar"/>
+ <include input="tomcat-ajp.jar"/>
+ <include input="tomcat-coyote.jar"/>
+ <include input="tomcat-http.jar"/>
+ <include input="tomcat-util.jar"/>
+ </export>
+ </component>
+</project>
+
Added: apache-tomcat/5.5.9.patch07-brew/lib/catalina-manager.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/catalina-manager.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/catalina-optional.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/catalina-optional.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/catalina.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/catalina.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/jasper-compiler-jdt.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/jasper-compiler-jdt.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/jasper-compiler.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/jasper-compiler.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/jasper-runtime.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/jasper-runtime.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/naming-resources.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/naming-resources.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/servlets-default.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/servlets-default.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/servlets-invoker.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/servlets-invoker.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/servlets-webdav.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/servlets-webdav.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/tomcat-ajp.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/tomcat-ajp.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/tomcat-coyote.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/tomcat-coyote.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/tomcat-http.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/tomcat-http.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/lib/tomcat-util.jar
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/lib/tomcat-util.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/src/jakarta-tomcat-5.5.9-src.tar.gz
===================================================================
(Binary files differ)
Property changes on: apache-tomcat/5.5.9.patch07-brew/src/jakarta-tomcat-5.5.9-src.tar.gz
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5-CVE-2007-5461-webdav.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5-CVE-2007-5461-webdav.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5-CVE-2007-5461-webdav.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,72 @@
+--- jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/servlets/LocalStrings.properties.orig 2007-03-05 10:27:45.000000000 -0500
++++ jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/servlets/LocalStrings.properties 2007-11-07 11:36:48.410682000 -0500
+@@ -10,6 +10,7 @@
+ invokerServlet.notNamed=Cannot call invoker servlet with a named dispatcher
+ invokerServlet.noWrapper=Container has not called setWrapper() for this servlet
+ webdavservlet.jaxpfailed=JAXP initialization failed
++webdavservlet.enternalEntityIgnored=The request included a reference to an external entity with PublicID {0} and SystemID {1} which was ignored
+ directory.filename=Filename
+ directory.lastModified=Last Modified
+ directory.parent=Up To {0}
+--- jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/servlets/WebdavServlet.java.orig 2005-03-26 14:24:01.000000000 -0500
++++ jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/servlets/WebdavServlet.java 2007-11-07 15:36:17.146510000 -0500
+@@ -19,6 +19,7 @@
+
+
+ import java.io.IOException;
++import java.io.StringReader;
+ import java.io.StringWriter;
+ import java.io.Writer;
+ import java.security.MessageDigest;
+@@ -35,6 +36,7 @@
+ import javax.naming.NamingEnumeration;
+ import javax.naming.NamingException;
+ import javax.naming.directory.DirContext;
++import javax.servlet.ServletContext;
+ import javax.servlet.ServletException;
+ import javax.servlet.UnavailableException;
+ import javax.servlet.http.HttpServletRequest;
+@@ -55,6 +57,7 @@
+ import org.w3c.dom.Element;
+ import org.w3c.dom.Node;
+ import org.w3c.dom.NodeList;
++import org.xml.sax.EntityResolver;
+ import org.xml.sax.InputSource;
+ import org.xml.sax.SAXException;
+
+@@ -247,6 +250,8 @@
+ documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ documentBuilder = documentBuilderFactory.newDocumentBuilder();
++ documentBuilder.setEntityResolver(
++ new WebdavResolver(this.getServletContext()));
+ } catch(ParserConfigurationException e) {
+ throw new ServletException
+ (sm.getString("webdavservlet.jaxpfailed"));
+@@ -2759,6 +2764,26 @@
+ }
+
+
++ // --------------------------------------------- WebdavResolver Inner Class
++ /**
++ * Work around for XML parsers that don't fully respect
++ * {@link DocumentBuilderFactory#setExpandEntityReferences(false)}. External
++ * references are filtered out for security reasons. See CVE-2007-5461.
++ */
++ private class WebdavResolver implements EntityResolver {
++ private ServletContext context;
++
++ public WebdavResolver(ServletContext theContext) {
++ context = theContext;
++ }
++
++ public InputSource resolveEntity (String publicId, String systemId) {
++ context.log(sm.getString("webdavservlet.enternalEntityIgnored",
++ publicId, systemId));
++ return new InputSource(
++ new StringReader("Ignored external entity"));
++ }
++ }
+ };
+
+
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-Bug36863-backport.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-Bug36863-backport.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-Bug36863-backport.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,13 @@
+--- jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java 2005/12/06 03:15:42 354266
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java 2005/12/06 03:15:59 354267
+@@ -247,9 +247,8 @@
+ int startValue=skipSpaces( bytes, pos, end);
+ int endValue=startValue;
+
+- // quote is valid only in version=1 cookies
+ cc=bytes[pos];
+- if( ( version == 1 || isSpecial ) && ( cc== '\'' || cc=='"' ) ) {
++ if( cc== '\'' || cc=='"' ) {
+ startValue++;
+ endValue=indexOf( bytes, startValue, end, cc );
+ pos=endValue+1; // to skip to next cookie
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2005-2090.5.0.x.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2005-2090.5.0.x.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2005-2090.5.0.x.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,39 @@
+--- jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/Request.java (revision 531784)
++++ jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/Request.java (working copy)
+@@ -308,7 +308,7 @@
+ public long getContentLengthLong() {
+ if( contentLength > -1 ) return contentLength;
+
+- MessageBytes clB = headers.getValue("content-length");
++ MessageBytes clB = headers.getUniqueValue("content-length");
+ contentLength = (clB == null || clB.isNull()) ? -1 : clB.getLong();
+
+ return contentLength;
+--- jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/MimeHeaders.java (revision 531784)
++++ jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/MimeHeaders.java (working copy)
+@@ -286,6 +286,25 @@
+ return null;
+ }
+
++ /**
++ * Finds and returns a unique header field with the given name. If no such
++ * field exists, null is returned. If the specified header field is not
++ * unique then an {@link IllegalArgumentException} is thrown.
++ */
++ public MessageBytes getUniqueValue(String name) {
++ MessageBytes result = null;
++ for (int i = 0; i < count; i++) {
++ if (headers[i].getName().equalsIgnoreCase(name)) {
++ if (result == null) {
++ result = headers[i].getValue();
++ } else {
++ throw new IllegalArgumentException();
++ }
++ }
++ }
++ return result;
++ }
++
+ // bad shortcut - it'll convert to string ( too early probably,
+ // encoding is guessed very late )
+ public String getHeader(String name) {
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-3835.5.5.x.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-3835.5.5.x.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-3835.5.5.x.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,34 @@
+--- jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/servlets/DefaultServlet.java 2005/11/09 19:43:12 332126
++++ jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/servlets/DefaultServlet.java 2005/11/09 19:50:47 332127
+@@ -94,7 +94,7 @@
+ /**
+ * Should we generate directory listings?
+ */
+- protected boolean listings = true;
++ protected boolean listings = false;
+
+
+ /**
+--- jakarta-tomcat-catalina/catalina/src/conf/web.xml 2005/11/09 19:43:12 332126
++++ jakarta-tomcat-catalina/catalina/src/conf/web.xml 2005/11/09 19:50:47 332127
+@@ -34,7 +34,10 @@
+ <!-- resources to be served. [2048] -->
+ <!-- -->
+ <!-- listings Should directory listings be produced if there -->
+- <!-- is no welcome file in this directory? [true] -->
++ <!-- is no welcome file in this directory? [false] -->
++ <!-- WARNING: Listings for directories with many -->
++ <!-- entries can be slow and may consume -->
++ <!-- significant proportions of server resources. -->
+ <!-- -->
+ <!-- output Output buffer size (in bytes) when writing -->
+ <!-- resources to be served. [2048] -->
+@@ -69,7 +72,7 @@
+ </init-param>
+ <init-param>
+ <param-name>listings</param-name>
+- <param-value>true</param-value>
++ <param-value>false</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-7195.5.0.x.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-7195.5.0.x.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-7195.5.0.x.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,49 @@
+--- jakarta-tomcat-catalina/webapps/docs/appdev/sample/src/mypackage/Hello.java (revision 467215)
++++ jakarta-tomcat-catalina/webapps/docs/appdev/sample/src/mypackage/Hello.java (working copy)
+@@ -69,24 +69,11 @@
+ writer.println("<td>");
+ writer.println("<h1>Sample Application Servlet</h1>");
+ writer.println("This is the output of a servlet that is part of");
+- writer.println("the Hello, World application. It displays the");
+- writer.println("request headers from the request we are currently");
+- writer.println("processing.");
++ writer.println("the Hello, World application.");
+ writer.println("</td>");
+ writer.println("</tr>");
+ writer.println("</table>");
+
+- writer.println("<table border=\"0\" width=\"100%\">");
+- Enumeration names = request.getHeaderNames();
+- while (names.hasMoreElements()) {
+- String name = (String) names.nextElement();
+- writer.println("<tr>");
+- writer.println(" <th align=\"right\">" + name + ":</th>");
+- writer.println(" <td>" + request.getHeader(name) + "</td>");
+- writer.println("</tr>");
+- }
+- writer.println("</table>");
+-
+ writer.println("</body>");
+ writer.println("</html>");
+
+--- jakarta-servletapi-5/jsr152/examples/jsp2/el/implicit-objects.jsp (revision 267240)
++++ jakarta-servletapi-5/jsr152/examples/jsp2/el/implicit-objects.jsp (revision 428048)
+@@ -71,15 +71,15 @@
+ </tr>
+ <tr>
+ <td>\${header["host"]}</td>
+- <td>${header["host"]}</td>
++ <td>${fn:escapeXml(header["host"])} </td>
+ </tr>
+ <tr>
+ <td>\${header["accept"]}</td>
+- <td>${header["accept"]}</td>
++ <td>${fn:escapeXml(header["accept"])} </td>
+ </tr>
+ <tr>
+ <td>\${header["user-agent"]}</td>
+- <td>${header["user-agent"]}</td>
++ <td>${fn:escapeXml(header["user-agent"])} </td>
+ </tr>
+ </table>
+ </code>
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-7196.5.x.y.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-7196.5.x.y.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2006-7196.5.x.y.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,17 @@
+--- jakarta-servletapi-5/jsr152/examples/cal/cal2.jsp (revision 267240)
++++ jakarta-servletapi-5/jsr152/examples/cal/cal2.jsp (revision 369933)
+@@ -29,12 +29,12 @@
+
+ <FONT SIZE=5> Please add the following event:
+ <BR> <h3> Date <%= table.getDate() %>
+-<BR> Time <%= time %> </h3>
++<BR> Time <%= util.HTMLFilter.filter(time) %> </h3>
+ </FONT>
+ <FORM METHOD=POST ACTION=cal1.jsp>
+ <BR>
+ <BR> <INPUT NAME="date" TYPE=HIDDEN VALUE="current">
+-<BR> <INPUT NAME="time" TYPE=HIDDEN VALUE=<%= time %>
++<BR> <INPUT NAME="time" TYPE=HIDDEN VALUE=<%= util.HTMLFilter.filter(time) %>
+ <BR> <h2> Description of the event <INPUT NAME="description" TYPE=TEXT SIZE=20> </h2>
+ <BR> <INPUT TYPE=SUBMIT VALUE="submit">
+ </FORM>
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-0450.5.5.9.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-0450.5.5.9.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-0450.5.5.9.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,132 @@
+--- jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteAdapter.java (revision 466585)
++++ jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/tomcat4/CoyoteAdapter.java (revision 519369)
+@@ -51,6 +51,10 @@
+ final class CoyoteAdapter
+ implements Adapter {
+
++ protected static final boolean ALLOW_BACKSLASH = Boolean.valueOf(
++ System.getProperty(
++ "org.apache.coyote.tomcat4.CoyoteAdapter.ALLOW_BACKSLASH",
++ "false")).booleanValue();
+
+ // -------------------------------------------------------------- Constants
+
+@@ -440,8 +444,12 @@
+ return "/";
+
+ // Normalize the slashes and add leading slash if necessary
+- if (normalized.indexOf('\\') >= 0)
+- normalized = normalized.replace('\\', '/');
++ if (normalized.indexOf('\\') >= 0) {
++ if ( ALLOW_BACKSLASH )
++ normalized = normalized.replace('\\', '/');
++ else
++ return null;
++ }
+ if (!normalized.startsWith("/"))
+ normalized = "/" + normalized;
+
+@@ -564,8 +572,12 @@
+ // Replace '\' with '/'
+ // Check for null byte
+ for (pos = start; pos < end; pos++) {
+- if (b[pos] == (byte) '\\')
+- b[pos] = (byte) '/';
++ if (b[pos] == (byte) '\\') {
++ if (ALLOW_BACKSLASH)
++ b[pos] = (byte) '/';
++ else
++ return false;
++ }
+ if (b[pos] == (byte) 0)
+ return false;
+ }
+--- jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/CoyoteAdapter.java (revision 466608)
++++ jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/CoyoteAdapter.java (revision 507117)
+@@ -50,6 +50,8 @@
+ {
+ private static Log log = LogFactory.getLog(CoyoteAdapter.class);
+
++ protected static final boolean ALLOW_BACKSLASH =
++ Boolean.valueOf(System.getProperty("org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH", "false")).booleanValue();
+ // -------------------------------------------------------------- Constants
+
+
+@@ -226,8 +228,8 @@
+ req.getURLDecoder().convert(decodedURI, false);
+ } catch (IOException ioe) {
+ res.setStatus(400);
+- res.setMessage("Invalid URI");
+- throw ioe;
++ res.setMessage("Invalid URI: " + ioe.getMessage());
++ return false;
+ }
+ // Normalization
+ if (!normalize(req.decodedURI())) {
+@@ -515,8 +517,13 @@
+ // Replace '\' with '/'
+ // Check for null byte
+ for (pos = start; pos < end; pos++) {
+- if (b[pos] == (byte) '\\')
+- b[pos] = (byte) '/';
++ if (b[pos] == (byte) '\\') {
++ if (ALLOW_BACKSLASH) {
++ b[pos] = (byte) '/';
++ } else {
++ return false;
++ }
++ }
+ if (b[pos] == (byte) 0)
+ return false;
+ }
+--- jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/buf/UDecoder.java (revision 481614)
++++ jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/buf/UDecoder.java (revision 507117)
+@@ -30,6 +30,9 @@
+ */
+ public final class UDecoder {
+
++ protected static final boolean ALLOW_ENCODED_SLASH =
++ Boolean.valueOf(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false")).booleanValue();
++
+ public UDecoder()
+ {
+ }
+@@ -63,6 +66,8 @@
+ // idx will be the smallest positive inxes ( first % or + )
+ if( idx2 >= 0 && idx2 < idx ) idx=idx2;
+ if( idx < 0 ) idx=idx2;
++
++ boolean noSlash = !(ALLOW_ENCODED_SLASH || query);
+
+ for( int j=idx; j<end; j++, idx++ ) {
+ if( buff[ j ] == '+' && query) {
+@@ -81,6 +86,9 @@
+
+ j+=2;
+ int res=x2c( b1, b2 );
++ if (noSlash && (res == '/')) {
++ throw new CharConversionException( "noSlash");
++ }
+ buff[idx]=(byte)res;
+ }
+ }
+@@ -122,7 +130,8 @@
+
+ if( idx2 >= 0 && idx2 < idx ) idx=idx2;
+ if( idx < 0 ) idx=idx2;
+-
++
++ boolean noSlash = !(ALLOW_ENCODED_SLASH || query);
+ for( int j=idx; j<cend; j++, idx++ ) {
+ if( buff[ j ] == '+' && query ) {
+ buff[idx]=( ' ' );
+@@ -141,6 +150,9 @@
+
+ j+=2;
+ int res=x2c( b1, b2 );
++ if (noSlash && (res == '/')) {
++ throw new CharConversionException( "noSlash");
++ }
+ buff[idx]=(char)res;
+ }
+ }
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-1858.5.5.9.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-1858.5.5.9.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-1858.5.5.9.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,11 @@
+--- jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java 2006/03/18 07:25:35 386818
++++ jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java 2006/03/18 07:26:00 386819
+@@ -188,7 +188,7 @@
+ vec.copyInto(enabledCiphers);
+ }
+ } else {
+- enabledCiphers = supportedCiphers;
++ enabledCiphers = sslProxy.getDefaultCipherSuites();
+ }
+
+ return enabledCiphers;
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-2449.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-2449.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-2449.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,104 @@
+Index: jakarta-servletapi-5/jsr152/examples/source.jsp
+===================================================================
+--- jakarta-servletapi-5/jsr152/examples/source.jsp (revision 547082)
++++ jakarta-servletapi-5/jsr152/examples/source.jsp (revision 547083)
+@@ -17,4 +17,4 @@
+ <%@ taglib uri="http://jakarta.apache.org/tomcat/examples-taglib"
+ prefix="eg" %>
+
+-<eg:ShowSource jspFile="<%= request.getQueryString() %>"/>
++<eg:ShowSource jspFile="<%= util.HTMLFilter.filter(request.getQueryString()) %>"/>
+Index: jakarta-servletapi-5/jsr152/examples/snp/snoop.html
+===================================================================
+--- jakarta-servletapi-5/jsr152/examples/snp/snoop.html (revision 547082)
++++ jakarta-servletapi-5/jsr152/examples/snp/snoop.html (revision 547083)
+@@ -24,8 +24,8 @@
+ <body bgcolor="#FFFFFF">
+ <p><font color="#0000FF"><a href="snoop.jsp"><img src="../images/execute.gif" align="right" border="0"></a><a href="../index.html"><img src="../images/return.gif" width="24" height="24" align="right" border="0"></a></font></p>
+
+-<h3><a href="snoop.jsp.html">Source Code for Request Parameters Example<font color="#0000FF"></a>
+- </font> </h3>
++<h3><a href="snoop.jsp.html">Source Code for Request Parameters Example<font color="#0000FF">
++ </font></a></h3>
+
+ </body>
+ </html>
+Index: jakarta-servletapi-5/jsr152/examples/snp/snoop.jsp
+===================================================================
+--- jakarta-servletapi-5/jsr152/examples/snp/snoop.jsp (revision 547082)
++++ jakarta-servletapi-5/jsr152/examples/snp/snoop.jsp (revision 547083)
+@@ -19,37 +19,38 @@
+ <body bgcolor="white">
+ <h1> Request Information </h1>
+ <font size="4">
+-JSP Request Method: <% out.print(util.HTMLFilter.filter(request.getMethod())); %>
++JSP Request Method: <%= util.HTMLFilter.filter(request.getMethod()) %>
+ <br>
+-Request URI: <%= request.getRequestURI() %>
++Request URI: <%= util.HTMLFilter.filter(request.getRequestURI()) %>
+ <br>
+-Request Protocol: <%= request.getProtocol() %>
++Request Protocol: <%= util.HTMLFilter.filter(request.getProtocol()) %>
+ <br>
+-Servlet path: <%= request.getServletPath() %>
++Servlet path: <%= util.HTMLFilter.filter(request.getServletPath()) %>
+ <br>
+-Path info: <% out.print(util.HTMLFilter.filter(request.getPathInfo())); %>
++Path info: <%= util.HTMLFilter.filter(request.getPathInfo()) %>
+ <br>
+-Query string: <% out.print(util.HTMLFilter.filter(request.getQueryString())); %>
++Query string: <%= util.HTMLFilter.filter(request.getQueryString()) %>
+ <br>
+ Content length: <%= request.getContentLength() %>
+ <br>
+-Content type: <% out.print(util.HTMLFilter.filter(request.getContentType())); %>
++Content type: <%= util.HTMLFilter.filter(request.getContentType()) %>
+ <br>
+-Server name: <%= request.getServerName() %>
++Server name: <%= util.HTMLFilter.filter(request.getServerName()) %>
+ <br>
+ Server port: <%= request.getServerPort() %>
+ <br>
+-Remote user: <%= request.getRemoteUser() %>
++Remote user: <%= util.HTMLFilter.filter(request.getRemoteUser()) %>
+ <br>
+-Remote address: <%= request.getRemoteAddr() %>
++Remote address: <%= util.HTMLFilter.filter(request.getRemoteAddr()) %>
+ <br>
+-Remote host: <%= request.getRemoteHost() %>
++Remote host: <%= util.HTMLFilter.filter(request.getRemoteHost()) %>
+ <br>
+-Authorization scheme: <%= request.getAuthType() %>
++Authorization scheme: <%= util.HTMLFilter.filter(request.getAuthType()) %>
+ <br>
+ Locale: <%= request.getLocale() %>
+ <hr>
+-The browser you are using is <% out.print(util.HTMLFilter.filter(request.getHeader("User-Agent"))); %>
++The browser you are using is
++<%= util.HTMLFilter.filter(request.getHeader("User-Agent")) %>
+ <hr>
+ </font>
+ </body>
+Index: jakarta-servletapi-5/jsr152/examples/security/protected/index.jsp
+===================================================================
+--- jakarta-servletapi-5/jsr152/examples/security/protected/index.jsp (revision 547082)
++++ jakarta-servletapi-5/jsr152/examples/security/protected/index.jsp (revision 547083)
+@@ -27,14 +27,16 @@
+ </head>
+ <body bgcolor="white">
+
+-You are logged in as remote user <b><%= request.getRemoteUser() %></b>
++You are logged in as remote user
++<b><%= util.HTMLFilter.filter(request.getRemoteUser()) %></b>
+ in session <b><%= session.getId() %></b><br><br>
+
+ <%
+ if (request.getUserPrincipal() != null) {
+ %>
+ Your user principal name is
+- <b><%= request.getUserPrincipal().getName() %></b><br><br>
++ <b><%= util.HTMLFilter.filter(request.getUserPrincipal().getName()) %></b>
++ <br><br>
+ <%
+ } else {
+ %>
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-2450_CVE-2007-3386.5.0.x.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-2450_CVE-2007-3386.5.0.x.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-2450_CVE-2007-3386.5.0.x.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,71 @@
+--- ./jakarta-tomcat-catalina/webapps/host-manager/WEB-INF/classes/org/apache/catalina/hostmanager/HTMLHostManagerServlet.java.org 2005-03-26 20:24:09.000000000 +0100
++++ ./jakarta-tomcat-catalina/webapps/host-manager/WEB-INF/classes/org/apache/catalina/hostmanager/HTMLHostManagerServlet.java 2007-08-27 16:58:55.000000000 +0200
+@@ -31,6 +31,7 @@
+
+ import org.apache.catalina.Container;
+ import org.apache.catalina.Host;
++import org.apache.catalina.util.RequestUtil;
+ import org.apache.catalina.util.ServerInfo;
+
+ /**
+@@ -194,7 +195,11 @@
+ // Message Section
+ args = new Object[3];
+ args[0] = sm.getString("htmlHostManagerServlet.messageLabel");
+- args[1] = (message == null || message.length() == 0) ? "OK" : message;
++ if (message == null || message.length() == 0) {
++ args[1] = "OK";
++ } else {
++ args[1] = RequestUtil.filter(message);
++ }
+ writer.print(MessageFormat.format(Constants.MESSAGE_SECTION, args));
+
+ // Manager Section
+@@ -247,7 +252,7 @@
+
+ if (host != null ) {
+ args = new Object[2];
+- args[0] = hostName;
++ args[0] = RequestUtil.filter(hostName);
+ String[] aliases = host.findAliases();
+ StringBuffer buf = new StringBuffer();
+ if (aliases.length > 0) {
+@@ -256,7 +261,12 @@
+ buf.append(", ").append(aliases[j]);
+ }
+ }
+- args[1] = buf.toString();
++ if (buf.length() == 0) {
++ buf.append(" ");
++ args[1] = buf.toString();
++ } else {
++ args[1] = RequestUtil.filter(buf.toString());
++ }
+ writer.print
+ (MessageFormat.format(HOSTS_ROW_DETAILS_SECTION, args));
+
+--- ./jakarta-tomcat-catalina/webapps/manager/WEB-INF/classes/org/apache/catalina/manager/HTMLManagerServlet.java.org 2007-08-27 16:52:04.000000000 +0200
++++ ./jakarta-tomcat-catalina/webapps/manager/WEB-INF/classes/org/apache/catalina/manager/HTMLManagerServlet.java 2007-08-27 16:53:58.000000000 +0200
+@@ -106,8 +106,7 @@
+ message = stop(path);
+ } else {
+ message =
+- sm.getString("managerServlet.unknownCommand",
+- RequestUtil.filter(command));
++ sm.getString("managerServlet.unknownCommand", command);
+ }
+
+ list(request, response, message);
+@@ -281,7 +280,11 @@
+ // Message Section
+ args = new Object[3];
+ args[0] = sm.getString("htmlManagerServlet.messageLabel");
+- args[1] = (message == null || message.length() == 0) ? "OK" : message;
++ if (message == null || message.length() == 0) {
++ args[1] = "OK";
++ } else {
++ args[1] = RequestUtil.filter(message);
++ }
+ writer.print(MessageFormat.format(Constants.MESSAGE_SECTION, args));
+
+ // Manager Section
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-3382_CVE-2007-3385.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-3382_CVE-2007-3385.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-3382_CVE-2007-3385.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,135 @@
+--- jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/ServerCookie.java 2007-03-05 16:27:39.000000000 +0100
++++ jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/ServerCookie.java 2007-08-24 14:40:51.000000000 +0200
+@@ -129,6 +129,7 @@
+ //
+ // private static final String tspecials = "()<>@,;:\\\"/[]?={} \t";
+ private static final String tspecials = ",; ";
++ private static final String tspecials2 = ",; \"";
+
+ /*
+ * Tests a string and returns true if the string counts as a
+@@ -153,6 +154,20 @@
+ return true;
+ }
+
++ public static boolean isToken2(String value) {
++ if( value==null) return true;
++ int len = value.length();
++
++ for (int i = 0; i < len; i++) {
++ char c = value.charAt(i);
++
++ if (c < 0x20 || c >= 0x7f || tspecials2.indexOf(c) != -1)
++ return false;
++ }
++ return true;
++ }
++
++
+ public static boolean checkName( String name ) {
+ if (!isToken(name)
+ || name.equalsIgnoreCase("Comment") // rfc2019
+@@ -212,7 +227,7 @@
+ // this part is the same for all cookies
+ buf.append( name );
+ buf.append("=");
+- maybeQuote(version, buf, value);
++ maybeQuote2(version, buf, value);
+
+ // XXX Netscape cookie: "; "
+ // add version 1 specific information
+@@ -283,6 +298,20 @@
+ }
+ }
+
++
++ public static void maybeQuote2 (int version, StringBuffer buf,
++ String value) {
++ // special case - a \n or \r shouldn't happen in any case
++ if (isToken2(value)) {
++ buf.append(value);
++ } else {
++ buf.append('"');
++ buf.append(escapeDoubleQuotes(value));
++ buf.append('"');
++ }
++ }
++
++
+ // log
+ static final int dbg=1;
+ public static void log(String s ) {
+@@ -305,12 +334,14 @@
+ }
+
+ StringBuffer b = new StringBuffer();
++ char p = s.charAt(0);
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+- if (c == '"')
++ if (c == '"' && p != '\\')
+ b.append('\\').append('"');
+ else
+ b.append(c);
++ p = c;
+ }
+
+ return b.toString();
+--- ./jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java 2007-08-24 14:15:10.000000000 +0200
++++ ./jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java 2007-08-24 14:50:26.000000000 +0200
+@@ -249,9 +249,11 @@
+ int endValue=startValue;
+
+ cc=bytes[pos];
+- if( cc== '\'' || cc=='"' ) {
+- startValue++;
+- endValue=indexOf( bytes, startValue, end, cc );
++ if( cc=='"' ) {
++ endValue=findDelim3( bytes, startValue+1, end, cc );
++ if (endValue == -1) {
++ endValue = findDelim2(bytes, startValue+1, end);
++ } else startValue++;
+ pos=endValue+1; // to skip to next cookie
+ } else {
+ endValue=findDelim2( bytes, startValue, end );
+@@ -335,28 +337,26 @@
+ return off;
+ }
+
+- public static int indexOf( byte bytes[], int off, int end, byte qq )
++ /*
++ * search for cc but skip \cc as required by rfc2616
++ * (according to rfc2616 cc should be ")
++ */
++ public static int findDelim3( byte bytes[], int off, int end, byte cc )
+ {
+ while( off < end ) {
+ byte b=bytes[off];
+- if( b==qq )
++ if (b=='\\') {
++ off++;
++ off++;
++ continue;
++ }
++ if( b==cc )
+ return off;
+ off++;
+ }
+- return off;
++ return -1;
+ }
+
+- public static int indexOf( byte bytes[], int off, int end, char qq )
+- {
+- while( off < end ) {
+- byte b=bytes[off];
+- if( b==qq )
+- return off;
+- off++;
+- }
+- return off;
+- }
+-
+ // XXX will be refactored soon!
+ public static boolean equals( String s, byte b[], int start, int end) {
+ int blen = end-start;
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-5333.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-5333.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-5333.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,1034 @@
+--- jakarta-tomcat-5.5.9-src.org/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/Request.java 2005-03-26 20:23:59.000000000 +0100
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/Request.java 2009-04-20 16:55:49.000000000 +0200
+@@ -2245,6 +2245,22 @@
+ }
+ }
+
++ protected String unescape(String s) {
++ if (s==null) return null;
++ if (s.indexOf('\\') == -1) return s;
++ StringBuffer buf = new StringBuffer();
++ for (int i=0; i<s.length(); i++) {
++ char c = s.charAt(i);
++ if (c!='\\') buf.append(c);
++ else {
++ if (++i >= s.length()) throw new IllegalArgumentException();//invalid escape, hence invalid cookie
++ c = s.charAt(i);
++ buf.append(c);
++ }
++ }
++ return buf.toString();
++ }
++
+ /**
+ * Parse cookies.
+ */
+@@ -2263,14 +2279,18 @@
+ for (int i = 0; i < count; i++) {
+ ServerCookie scookie = serverCookies.getCookie(i);
+ try {
+- Cookie cookie = new Cookie(scookie.getName().toString(),
+- scookie.getValue().toString());
+- cookie.setPath(scookie.getPath().toString());
+- cookie.setVersion(scookie.getVersion());
++ /*
++ we must unescape the '\\' escape character
++ */
++ Cookie cookie = new Cookie(scookie.getName().toString(),null);
++ int version = scookie.getVersion();
++ cookie.setVersion(version);
++ cookie.setValue(unescape(scookie.getValue().toString()));
++ cookie.setPath(unescape(scookie.getPath().toString()));
+ String domain = scookie.getDomain().toString();
+- if (domain != null) {
+- cookie.setDomain(scookie.getDomain().toString());
+- }
++ if (domain!=null) cookie.setDomain(unescape(domain));//avoid NPE
++ String comment = scookie.getComment().toString();
++ cookie.setComment(version==1?unescape(comment):null);
+ cookies[idx++] = cookie;
+ } catch(IllegalArgumentException e) {
+ // Ignore bad cookie
+--- jakarta-tomcat-5.5.9-src.org/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/Response.java 2005-03-26 20:23:59.000000000 +0100
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/Response.java 2009-04-20 16:55:49.000000000 +0200
+@@ -928,9 +928,9 @@
+ if (included)
+ return;
+
+- cookies.add(cookie);
+-
+ final StringBuffer sb = new StringBuffer();
++ //web application code can receive a IllegalArgumentException
++ //from the appendCookieValue invokation
+ if (SecurityUtil.isPackageProtectionEnabled()) {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run(){
+@@ -949,11 +949,13 @@
+ cookie.getMaxAge(), cookie.getSecure());
+ }
+
++ // if we reached here, no exception, cookie is valid
+ // the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
+ // RFC2965 is not supported by browsers and the Servlet spec
+ // asks for 2109.
+ addHeader("Set-Cookie", sb.toString());
+
++ cookies.add(cookie);
+ }
+
+
+--- jakarta-tomcat-5.5.9-src.org/jakarta-tomcat-catalina/webapps/docs/changelog.xml 2005-03-26 20:24:08.000000000 +0100
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/webapps/docs/changelog.xml 2009-04-20 16:55:49.000000000 +0200
+@@ -141,6 +141,18 @@
+ <fix>
+ <bug>34161</bug>: Harmonize StandardContext.stop with ContainerBase.stop (remm)
+ </fix>
++ <fix>
++ Cookie handling/parsing changes!
++ The following behavior has been changed with regards to Tomcat's cookie
++ handling:<br/>
++ a) Cookies containing control characters, except 0x09(HT), are rejected
++ using an InvalidArgumentException.<br/>
++ b) If cookies are not quoted, they will be quoted if they contain
++ <code>tspecials(ver0)</code> or <code>tspecials2(ver1)</code>
++ characters.<br/>
++ c) Escape character '\\' is allowed and respected as a escape character,
++ and will be unescaped during parsing.
++ </fix>
+ </changelog>
+ </subsection>
+
+--- jakarta-tomcat-5.5.9-src.org/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java 2009-04-20 16:46:03.000000000 +0200
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java 2009-04-20 16:55:49.000000000 +0200
+@@ -44,6 +44,27 @@
+ boolean unprocessed=true;
+
+ MimeHeaders headers;
++
++ /*
++ List of Separator Characters (see isSeparator())
++ Excluding the '/' char violates the RFC, but
++ it looks like a lot of people put '/'
++ in unquoted values: '/': ; //47
++ '\t':9 ' ':32 '\"':34 '\'':39 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60
++ '=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125
++ */
++ public static final char SEPARATORS[] = { '\t', ' ', '\"', '\'', '(', ')', ',',
++ ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
++
++ protected static final boolean separators[] = new boolean[128];
++ static {
++ for (int i = 0; i < 128; i++) {
++ separators[i] = false;
++ }
++ for (int i = 0; i < SEPARATORS.length; i++) {
++ separators[SEPARATORS[i]] = true;
++ }
++ }
+
+ /**
+ * Construct a new cookie collection, that will extract
+@@ -181,181 +202,6 @@
+ }
+ }
+
+- /** Process a byte[] header - allowing fast processing of the
+- * raw data
+- */
+- void processCookieHeader( byte bytes[], int off, int len )
+- {
+- if( len<=0 || bytes==null ) return;
+- int end=off+len;
+- int pos=off;
+-
+- int version=0; //sticky
+- ServerCookie sc=null;
+-
+-
+- while( pos<end ) {
+- byte cc;
+- // [ skip_spaces name skip_spaces "=" skip_spaces value EXTRA ; ] *
+- if( dbg>0 ) log( "Start: " + pos + " " + end );
+-
+- pos=skipSpaces(bytes, pos, end);
+- if( pos>=end )
+- return; // only spaces
+- int startName=pos;
+- if( dbg>0 ) log( "SN: " + pos );
+-
+- // Version should be the first token
+- boolean isSpecial=false;
+- if(bytes[pos]=='$') { pos++; isSpecial=true; }
+-
+- pos= findDelim1( bytes, startName, end); // " =;,"
+- int endName=pos;
+- // current = "=" or " " or DELIM
+- pos= skipSpaces( bytes, endName, end );
+- if( dbg>0 ) log( "DELIM: " + endName + " " + (char)bytes[pos]);
+-
+- if(pos >= end ) {
+- // it's a name-only cookie ( valid in RFC2109 )
+- if( ! isSpecial ) {
+- sc=addCookie();
+- sc.getName().setBytes( bytes, startName,
+- endName-startName );
+- sc.getValue().setString("");
+- sc.setVersion( version );
+- if( dbg>0 ) log( "Name only, end: " + startName + " " +
+- endName);
+- }
+- return;
+- }
+-
+- cc=bytes[pos];
+- pos++;
+- if( cc==';' || cc==',' || pos>=end ) {
+- if( ! isSpecial && startName!= endName ) {
+- sc=addCookie();
+- sc.getName().setBytes( bytes, startName,
+- endName-startName );
+- sc.getValue().setString("");
+- sc.setVersion( version );
+- if( dbg>0 ) log( "Name only: " + startName + " " + endName);
+- }
+- continue;
+- }
+-
+- // we should have "=" ( tested all other alternatives )
+- int startValue=skipSpaces( bytes, pos, end);
+- int endValue=startValue;
+-
+- cc=bytes[pos];
+- if( cc=='"' ) {
+- endValue=findDelim3( bytes, startValue+1, end, cc );
+- if (endValue == -1) {
+- endValue = findDelim2(bytes, startValue+1, end);
+- } else startValue++;
+- pos=endValue+1; // to skip to next cookie
+- } else {
+- endValue=findDelim2( bytes, startValue, end );
+- pos=endValue+1;
+- }
+-
+- // if not $Version, etc
+- if( ! isSpecial ) {
+- sc=addCookie();
+- sc.getName().setBytes( bytes, startName, endName-startName );
+- sc.getValue().setBytes( bytes, startValue, endValue-startValue);
+- sc.setVersion( version );
+- if( dbg>0 ) {
+- log( "New: " + sc.getName() + "X=X" + sc.getValue());
+- }
+- continue;
+- }
+-
+- // special - Path, Version, Domain, Port
+- if( dbg>0 ) log( "Special: " + startName + " " + endName);
+- // XXX TODO
+- if( equals( "$Version", bytes, startName, endName ) ) {
+- if(dbg>0 ) log( "Found version " );
+- if( bytes[startValue]=='1' && endValue==startValue+1 ) {
+- version=1;
+- if(dbg>0 ) log( "Found version=1" );
+- }
+- continue;
+- }
+- if( sc==null ) {
+- // Path, etc without a previous cookie
+- continue;
+- }
+- if( equals( "$Path", bytes, startName, endName ) ) {
+- sc.getPath().setBytes( bytes,
+- startValue,
+- endValue-startValue );
+- }
+- if( equals( "$Domain", bytes, startName, endName ) ) {
+- sc.getDomain().setBytes( bytes,
+- startValue,
+- endValue-startValue );
+- }
+- if( equals( "$Port", bytes, startName, endName ) ) {
+- // sc.getPort().setBytes( bytes,
+- // startValue,
+- // endValue-startValue );
+- }
+- }
+- }
+-
+- // -------------------- Utils --------------------
+- public static int skipSpaces( byte bytes[], int off, int end ) {
+- while( off < end ) {
+- byte b=bytes[off];
+- if( b!= ' ' ) return off;
+- off ++;
+- }
+- return off;
+- }
+-
+- public static int findDelim1( byte bytes[], int off, int end )
+- {
+- while( off < end ) {
+- byte b=bytes[off];
+- if( b==' ' || b=='=' || b==';' || b==',' )
+- return off;
+- off++;
+- }
+- return off;
+- }
+-
+- public static int findDelim2( byte bytes[], int off, int end )
+- {
+- while( off < end ) {
+- byte b=bytes[off];
+- if( b==';' || b==',' )
+- return off;
+- off++;
+- }
+- return off;
+- }
+-
+- /*
+- * search for cc but skip \cc as required by rfc2616
+- * (according to rfc2616 cc should be ")
+- */
+- public static int findDelim3( byte bytes[], int off, int end, byte cc )
+- {
+- while( off < end ) {
+- byte b=bytes[off];
+- if (b=='\\') {
+- off++;
+- off++;
+- continue;
+- }
+- if( b==cc )
+- return off;
+- off++;
+- }
+- return -1;
+- }
+-
+ // XXX will be refactored soon!
+ public static boolean equals( String s, byte b[], int start, int end) {
+ int blen = end-start;
+@@ -411,7 +257,7 @@
+ /**
+ *
+ * Strips quotes from the start and end of the cookie string
+- * This conforms to RFC 2109
++ * This conforms to RFC 2965
+ *
+ * @param value a <code>String</code> specifying the cookie
+ * value (possibly quoted).
+@@ -422,8 +268,7 @@
+ private static String stripQuote( String value )
+ {
+ // log("Strip quote from " + value );
+- if (((value.startsWith("\"")) && (value.endsWith("\""))) ||
+- ((value.startsWith("'") && (value.endsWith("'"))))) {
++ if (value.startsWith("\"") && value.endsWith("\"")) {
+ try {
+ return value.substring(1,value.length()-1);
+ } catch (Exception ex) {
+@@ -440,42 +285,298 @@
+ log.debug("Cookies: " + s);
+ }
+
+- /*
+- public static void main( String args[] ) {
+- test("foo=bar; a=b");
+- test("foo=bar;a=b");
+- test("foo=bar;a=b;");
+- test("foo=bar;a=b; ");
+- test("foo=bar;a=b; ;");
+- test("foo=;a=b; ;");
+- test("foo;a=b; ;");
+- // v1
+- test("$Version=1; foo=bar;a=b");
+- test("$Version=\"1\"; foo='bar'; $Path=/path; $Domain=\"localhost\"");
+- test("$Version=1;foo=bar;a=b; ; ");
+- test("$Version=1;foo=;a=b; ; ");
+- test("$Version=1;foo= ;a=b; ; ");
+- test("$Version=1;foo;a=b; ; ");
+- test("$Version=1;foo=\"bar\";a=b; ; ");
+- test("$Version=1;foo=\"bar\";$Path=/examples;a=b; ; ");
+- test("$Version=1;foo=\"bar\";$Domain=apache.org;a=b");
+- test("$Version=1;foo=\"bar\";$Domain=apache.org;a=b;$Domain=yahoo.com");
+- // rfc2965
+- test("$Version=1;foo=\"bar\";$Domain=apache.org;$Port=8080;a=b");
+-
+- // wrong
+- test("$Version=1;foo=\"bar\";$Domain=apache.org;$Port=8080;a=b");
+- }
+-
+- public static void test( String s ) {
+- System.out.println("Processing " + s );
+- Cookies cs=new Cookies(null);
+- cs.processCookieHeader( s.getBytes(), 0, s.length());
+- for( int i=0; i< cs.getCookieCount() ; i++ ) {
+- System.out.println("Cookie: " + cs.getCookie( i ));
++ /**
++ * Returns true if the byte is a separator character as
++ * defined in RFC2619. Since this is called often, this
++ * function should be organized with the most probable
++ * outcomes first.
++ */
++ public static final boolean isSeparator(final byte c) {
++ if (c > 0 && c < 126)
++ return separators[c];
++ else
++ return false;
++ }
++
++ /**
++ * Returns true if the byte is a whitespace character as
++ * defined in RFC2619.
++ */
++ public static final boolean isWhiteSpace(final byte c) {
++ // This switch statement is slightly slower
++ // for my vm than the if statement.
++ // Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164)
++ /*
++ switch (c) {
++ case ' ':;
++ case '\t':;
++ case '\n':;
++ case '\r':;
++ case '\f':;
++ return true;
++ default:;
++ return false;
++ }
++ */
++ if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f')
++ return true;
++ else
++ return false;
++ }
++
++ /**
++ * Parses a cookie header after the initial "Cookie:"
++ * [WS][$]token[WS]=[WS](token|QV)[;|,]
++ * RFC 2965
++ * JVK
++ */
++ public final void processCookieHeader(byte bytes[], int off, int len){
++ if( len<=0 || bytes==null ) return;
++ int end=off+len;
++ int pos=off;
++ int nameStart=0;
++ int nameEnd=0;
++ int valueStart=0;
++ int valueEnd=0;
++ int version = 0;
++ ServerCookie sc=null;
++ boolean isSpecial;
++ boolean isQuoted;
++
++ while (pos < end) {
++ isSpecial = false;
++ isQuoted = false;
++
++ // Skip whitespace and non-token characters (separators)
++ while (pos < end &&
++ (isSeparator(bytes[pos]) || isWhiteSpace(bytes[pos])))
++ {pos++; }
++
++ if (pos >= end)
++ return;
++
++ // Detect Special cookies
++ if (bytes[pos] == '$') {
++ isSpecial = true;
++ pos++;
++ }
++
++ // Get the cookie name. This must be a token
++ valueEnd = valueStart = nameStart = pos;
++ pos = nameEnd = getTokenEndPosition(bytes,pos,end);
++
++ // Skip whitespace
++ while (pos < end && isWhiteSpace(bytes[pos])) {pos++; };
++
++
++ // Check for an '=' -- This could also be a name-only
++ // cookie at the end of the cookie header, so if we
++ // are past the end of the header, but we have a name
++ // skip to the name-only part.
++ if (pos < end && bytes[pos] == '=') {
++
++ // Skip whitespace
++ do {
++ pos++;
++ } while (pos < end && isWhiteSpace(bytes[pos]));
++
++ if (pos >= end)
++ return;
++
++ // Determine what type of value this is, quoted value,
++ // token, name-only with an '=', or other (bad)
++ switch (bytes[pos]) {
++ case '"':; // Quoted Value
++ isQuoted = true;
++ valueStart=pos + 1; // strip "
++ // getQuotedValue returns the position before
++ // at the last qoute. This must be dealt with
++ // when the bytes are copied into the cookie
++ valueEnd=getQuotedValueEndPosition(bytes,
++ valueStart, end);
++ // We need pos to advance
++ pos = valueEnd;
++ // Handles cases where the quoted value is
++ // unterminated and at the end of the header,
++ // e.g. [myname="value]
++ if (pos >= end)
++ return;
++ break;
++ case ';':
++ case ',':
++ // Name-only cookie with an '=' after the name token
++ // This may not be RFC compliant
++ valueStart = valueEnd = -1;
++ // The position is OK (On a delimiter)
++ break;
++ default:;
++ if (!isSeparator(bytes[pos])) {
++ // Token
++ valueStart=pos;
++ // getToken returns the position at the delimeter
++ // or other non-token character
++ valueEnd=getTokenEndPosition(bytes, valueStart, end);
++ // We need pos to advance
++ pos = valueEnd;
++ } else {
++ // INVALID COOKIE, advance to next delimiter
++ // The starting character of the cookie value was
++ // not valid.
++ log("Invalid cookie. Value not a token or quoted value");
++ while (pos < end && bytes[pos] != ';' &&
++ bytes[pos] != ',')
++ {pos++; };
++ pos++;
++ // Make sure no special avpairs can be attributed to
++ // the previous cookie by setting the current cookie
++ // to null
++ sc = null;
++ continue;
++ }
++ }
++ } else {
++ // Name only cookie
++ valueStart = valueEnd = -1;
++ pos = nameEnd;
++
++ }
++
++ // We should have an avpair or name-only cookie at this
++ // point. Perform some basic checks to make sure we are
++ // in a good state.
++
++ // Skip whitespace
++ while (pos < end && isWhiteSpace(bytes[pos])) {pos++; };
++
++
++ // Make sure that after the cookie we have a separator. This
++ // is only important if this is not the last cookie pair
++ while (pos < end && bytes[pos] != ';' && bytes[pos] != ',') {
++ pos++;
++ }
++
++ pos++;
++
++ /*
++ if (nameEnd <= nameStart || valueEnd < valueStart ) {
++ // Something is wrong, but this may be a case
++ // of having two ';' characters in a row.
++ // log("Cookie name/value does not conform to RFC 2965");
++ // Advance to next delimiter (ignoring everything else)
++ while (pos < end && bytes[pos] != ';' && bytes[pos] != ',')
++ { pos++; };
++ pos++;
++ // Make sure no special cookies can be attributed to
++ // the previous cookie by setting the current cookie
++ // to null
++ sc = null;
++ continue;
++ }
++ */
++
++ // All checks passed. Add the cookie, start with the
++ // special avpairs first
++ if (isSpecial) {
++ isSpecial = false;
++ // $Version must be the first avpair in the cookie header
++ // (sc must be null)
++ if (equals( "Version", bytes, nameStart, nameEnd) &&
++ sc == null) {
++ // Set version
++ if( bytes[valueStart] =='1' && valueEnd == (valueStart+1)) {
++ version=1;
++ } else {
++ // unknown version (Versioning is not very strict)
++ }
++ continue;
++ }
++
++ // We need an active cookie for Path/Port/etc.
++ if (sc == null) {
++ continue;
++ }
++
++ // Domain is more common, so it goes first
++ if (equals( "Domain", bytes, nameStart, nameEnd)) {
++ sc.getDomain().setBytes( bytes,
++ valueStart,
++ valueEnd-valueStart);
++ continue;
++ }
++
++ if (equals( "Path", bytes, nameStart, nameEnd)) {
++ sc.getPath().setBytes( bytes,
++ valueStart,
++ valueEnd-valueStart);
++ continue;
++ }
++
++
++ if (equals( "Port", bytes, nameStart, nameEnd)) {
++ // sc.getPort is not currently implemented.
++ // sc.getPort().setBytes( bytes,
++ // valueStart,
++ // valueEnd-valueStart );
++ continue;
++ }
++
++ // Unknown cookie, complain
++ log("Unknown Special Cookie");
++
++ } else { // Normal Cookie
++ sc = addCookie();
++ sc.setVersion( version );
++ sc.getName().setBytes( bytes, nameStart,
++ nameEnd-nameStart);
++
++ if (valueStart != -1) { // Normal AVPair
++ sc.getValue().setBytes( bytes, valueStart,
++ valueEnd-valueStart);
++ if (isQuoted) {
++ // We know this is a byte value so this is safe
++ ServerCookie.unescapeDoubleQuotes(
++ sc.getValue().getByteChunk());
++ }
++ } else {
++ // Name Only
++ sc.getValue().setString("");
++ }
++ continue;
++ }
+ }
+-
+ }
+- */
+
++ /**
++ * Given the starting position of a token, this gets the end of the
++ * token, with no separator characters in between.
++ * JVK
++ */
++ public static final int getTokenEndPosition(byte bytes[], int off, int end){
++ int pos = off;
++ while (pos < end && !isSeparator(bytes[pos])) {pos++; };
++
++ if (pos > end)
++ return end;
++ return pos;
++ }
++
++ /**
++ * Given a starting position after an initial quote chracter, this gets
++ * the position of the end quote. This escapes anything after a '\' char
++ * JVK RFC 2616
++ */
++ public static final int getQuotedValueEndPosition(byte bytes[], int off, int end){
++ int pos = off;
++ while (pos < end) {
++ if (bytes[pos] == '"') {
++ return pos;
++ } else if (bytes[pos] == '\\' && pos < (end - 1)) {
++ pos+=2;
++ } else {
++ pos++;
++ }
++ }
++ // Error, we have reached the end of the header w/o a end quote
++ return end;
++ }
+ }
+diff -ru jakarta-tomcat-5.5.9-src.org/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java.orig jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java.orig
+--- jakarta-tomcat-5.5.9-src.org/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java.orig 2009-04-20 16:46:02.000000000 +0200
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Cookies.java.orig 2009-04-20 16:46:03.000000000 +0200
+@@ -248,9 +248,11 @@
+ int endValue=startValue;
+
+ cc=bytes[pos];
+- if( cc== '\'' || cc=='"' ) {
+- startValue++;
+- endValue=indexOf( bytes, startValue, end, cc );
++ if( cc=='"' ) {
++ endValue=findDelim3( bytes, startValue+1, end, cc );
++ if (endValue == -1) {
++ endValue = findDelim2(bytes, startValue+1, end);
++ } else startValue++;
+ pos=endValue+1; // to skip to next cookie
+ } else {
+ endValue=findDelim2( bytes, startValue, end );
+@@ -334,28 +336,26 @@
+ return off;
+ }
+
+- public static int indexOf( byte bytes[], int off, int end, byte qq )
++ /*
++ * search for cc but skip \cc as required by rfc2616
++ * (according to rfc2616 cc should be ")
++ */
++ public static int findDelim3( byte bytes[], int off, int end, byte cc )
+ {
+ while( off < end ) {
+ byte b=bytes[off];
+- if( b==qq )
++ if (b=='\\') {
++ off++;
++ off++;
++ continue;
++ }
++ if( b==cc )
+ return off;
+ off++;
+ }
+- return off;
++ return -1;
+ }
+
+- public static int indexOf( byte bytes[], int off, int end, char qq )
+- {
+- while( off < end ) {
+- byte b=bytes[off];
+- if( b==qq )
+- return off;
+- off++;
+- }
+- return off;
+- }
+-
+ // XXX will be refactored soon!
+ public static boolean equals( String s, byte b[], int start, int end) {
+ int blen = end-start;
+--- jakarta-tomcat-5.5.9-src.org/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/ServerCookie.java 2009-04-20 16:46:03.000000000 +0200
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/ServerCookie.java 2009-04-20 16:55:49.000000000 +0200
+@@ -20,13 +20,14 @@
+ import java.text.FieldPosition;
+ import java.util.Date;
+
++import org.apache.tomcat.util.buf.ByteChunk;
+ import org.apache.tomcat.util.buf.DateTool;
+ import org.apache.tomcat.util.buf.MessageBytes;
+
+
+ /**
+ * Server-side cookie representation.
+- * Allows recycling and uses MessageBytes as low-level
++ * Allows recycling and uses MessageBytes as low-level
+ * representation ( and thus the byte-> char conversion can be delayed
+ * until we know the charset ).
+ *
+@@ -53,6 +54,9 @@
+ private int version = 0; // ;Version=1
+
+ //XXX CommentURL, Port -> use notes ?
++
++ public static final boolean VERSION_SWITCH =
++ Boolean.valueOf(System.getProperty("org.apache.tomcat.util.http.ServerCookie.VERSION_SWITCH", "true")).booleanValue();
+
+ public ServerCookie() {
+
+@@ -86,7 +90,6 @@
+ return maxAge;
+ }
+
+-
+ public MessageBytes getPath() {
+ return path;
+ }
+@@ -111,7 +114,6 @@
+ return version;
+ }
+
+-
+ public void setVersion(int v) {
+ version = v;
+ }
+@@ -129,7 +131,8 @@
+ //
+ // private static final String tspecials = "()<>@,;:\\\"/[]?={} \t";
+ private static final String tspecials = ",; ";
+- private static final String tspecials2 = ",; \"";
++ private static final String tspecials2 = "()<>@,;:\\\"/[]?={} \t";
++ private static final String tspecials2NoSlash = "()<>@,;:\\\"[]?={} \t";
+
+ /*
+ * Tests a string and returns true if the string counts as a
+@@ -142,26 +145,52 @@
+ * if it is not
+ */
+ public static boolean isToken(String value) {
++ return isToken(value,null);
++ }
++
++ public static boolean isToken(String value, String literals) {
++ String tspecials = (literals==null?ServerCookie.tspecials:literals);
++
+ if( value==null) return true;
+ int len = value.length();
+
+ for (int i = 0; i < len; i++) {
+ char c = value.charAt(i);
+
+- if (c < 0x20 || c >= 0x7f || tspecials.indexOf(c) != -1)
++ if (tspecials.indexOf(c) != -1)
+ return false;
+ }
+ return true;
+ }
+
++ public static boolean containsCTL(String value, int version) {
++ if( value==null) return false;
++ int len = value.length();
++ for (int i = 0; i < len; i++) {
++ char c = value.charAt(i);
++ if (c < 0x20 || c >= 0x7f) {
++ if (c == 0x09)
++ continue; //allow horizontal tabs
++ return true;
++ }
++ }
++ return false;
++ }
++
+ public static boolean isToken2(String value) {
++ return isToken2(value,null);
++ }
++
++ public static boolean isToken2(String value, String literals) {
++ String tspecials2 = (literals==null?ServerCookie.tspecials2:literals);
++
+ if( value==null) return true;
+ int len = value.length();
+
+ for (int i = 0; i < len; i++) {
+ char c = value.charAt(i);
+
+- if (c < 0x20 || c >= 0x7f || tspecials2.indexOf(c) != -1)
++ if (tspecials2.indexOf(c) != -1)
+ return false;
+ }
+ return true;
+@@ -187,8 +216,8 @@
+ // -------------------- Cookie parsing tools
+
+
+- /** Return the header name to set the cookie, based on cookie
+- * version
++ /**
++ * Return the header name to set the cookie, based on cookie version.
+ */
+ public String getCookieHeaderName() {
+ return getCookieHeaderName(version);
+@@ -198,7 +227,6 @@
+ * version
+ */
+ public static String getCookieHeaderName(int version) {
+- if( dbg>0 ) log( (version==1) ? "Set-Cookie2" : "Set-Cookie");
+ if (version == 1) {
+ // RFC2109
+ return "Set-Cookie";
+@@ -214,7 +242,7 @@
+
+ private static final String ancientDate=DateTool.formatOldCookie(new Date(10000));
+
+- public static void appendCookieValue( StringBuffer buf,
++ public static void appendCookieValue( StringBuffer headerBuf,
+ int version,
+ String name,
+ String value,
+@@ -225,9 +253,10 @@
+ boolean isSecure )
+ {
+ // this part is the same for all cookies
++ StringBuffer buf = new StringBuffer();
+ buf.append( name );
+ buf.append("=");
+- maybeQuote2(version, buf, value);
++ version = maybeQuote2(version, buf, value, true);
+
+ // XXX Netscape cookie: "; "
+ // add version 1 specific information
+@@ -238,7 +267,7 @@
+ // Comment=comment
+ if ( comment!=null ) {
+ buf.append ("; Comment=");
+- maybeQuote (version, buf, comment);
++ maybeQuote2 (version, buf, comment);
+ }
+ }
+
+@@ -246,7 +275,7 @@
+
+ if (domain!=null) {
+ buf.append("; Domain=");
+- maybeQuote (version, buf, domain);
++ maybeQuote2 (version, buf, domain);
+ }
+
+ // Max-Age=secs/Discard ... or use old "Expires" format
+@@ -275,14 +304,18 @@
+ // Path=path
+ if (path!=null) {
+ buf.append ("; Path=");
+- maybeQuote (version, buf, path);
++ if (version==0) {
++ maybeQuote2(version, buf, path);
++ } else {
++ maybeQuote2(version, buf, path, ServerCookie.tspecials2NoSlash, false);
++ }
+ }
+
+ // Secure
+ if (isSecure) {
+ buf.append ("; Secure");
+ }
+-
++ headerBuf.append(buf);
+
+ }
+
+@@ -293,25 +326,51 @@
+ buf.append(value);
+ } else {
+ buf.append('"');
+- buf.append(escapeDoubleQuotes(value));
++ buf.append(escapeDoubleQuotes(value,0,value.length()));
+ buf.append('"');
+ }
+ }
+
++ public static boolean alreadyQuoted (String value) {
++ if (value==null || value.length()==0) return false;
++ return (value.charAt(0)=='\"' && value.charAt(value.length()-1)=='\"');
++ }
+
+- public static void maybeQuote2 (int version, StringBuffer buf,
+- String value) {
+- // special case - a \n or \r shouldn't happen in any case
+- if (isToken2(value)) {
+- buf.append(value);
+- } else {
++ public static int maybeQuote2(int version, StringBuffer buf, String value) {
++ return maybeQuote2(version,buf,value,false);
++ }
++ public static int maybeQuote2 (int version, StringBuffer buf, String value, boolean allowVersionSwitch) {
++ return maybeQuote2(version,buf,value,null,allowVersionSwitch);
++ }
++
++ public static int maybeQuote2 (int version, StringBuffer buf, String value, String literals, boolean allowVersionSwitch) {
++ if (value==null || value.length()==0) {
++ buf.append("\"\"");
++ } else if (containsCTL(value,version))
++ throw new IllegalArgumentException("Control character in cookie value, consider BASE64 encoding your value");
++ else if (alreadyQuoted(value)) {
++ buf.append('"');
++ buf.append(escapeDoubleQuotes(value,1,value.length()-1));
++ buf.append('"');
++ } else if (allowVersionSwitch && VERSION_SWITCH && version==0 && !isToken2(value, literals)) {
+ buf.append('"');
+- buf.append(escapeDoubleQuotes(value));
++ buf.append(escapeDoubleQuotes(value,0,value.length()));
+ buf.append('"');
++ version = 1;
++ } else if (version==0 && !isToken(value, literals)) {
++ buf.append('"');
++ buf.append(escapeDoubleQuotes(value,0,value.length()));
++ buf.append('"');
++ } else if (version==1 && !isToken2(value, literals)) {
++ buf.append('"');
++ buf.append(escapeDoubleQuotes(value,0,value.length()));
++ buf.append('"');
++ } else {
++ buf.append(value);
+ }
++ return version;
+ }
+
+-
+ // log
+ static final int dbg=1;
+ public static void log(String s ) {
+@@ -327,25 +386,55 @@
+ *
+ * @return The (possibly) escaped string
+ */
+- private static String escapeDoubleQuotes(String s) {
++ private static String escapeDoubleQuotes(String s, int beginIndex,
++ int endIndex) {
+
+ if (s == null || s.length() == 0 || s.indexOf('"') == -1) {
+ return s;
+ }
+
+ StringBuffer b = new StringBuffer();
+- char p = s.charAt(0);
+- for (int i = 0; i < s.length(); i++) {
++ for (int i = beginIndex; i < endIndex; i++) {
+ char c = s.charAt(i);
+- if (c == '"' && p != '\\')
++ if (c == '\\' ) {
++ b.append(c);
++ //ignore the character after an escape, just append it
++ if (++i>=endIndex) throw new IllegalArgumentException("Invalid escape character in cookie value.");
++ b.append(s.charAt(i));
++ } else if (c == '"')
+ b.append('\\').append('"');
+ else
+ b.append(c);
+- p = c;
+ }
+
+ return b.toString();
+ }
++ /**
++ * Unescapes any double quotes in the given cookie value.
++ *
++ * @param bc The cookie value to modify
++ */
++ public static void unescapeDoubleQuotes(ByteChunk bc) {
++
++ if (bc == null || bc.getLength() == 0 || bc.indexOf('"', 0) == -1) {
++ return;
++ }
++
++ int src = bc.getStart();
++ int end = bc.getEnd();
++ int dest = src;
++ byte[] buffer = bc.getBuffer();
++
++ while (src < end) {
++ if (buffer[src] == '\\' && src < end && buffer[src+1] == '"') {
++ src++;
++ }
++ buffer[dest] = buffer[src];
++ dest ++;
++ src ++;
++ }
++ bc.setEnd(dest);
++ }
+
+ }
+
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-5342.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-5342.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2007-5342.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,25 @@
+--- jakarta-tomcat-catalina/catalina/src/conf/catalina.policy 2007/09/02 21:16:25 572160
++++ jakarta-tomcat-catalina/catalina/src/conf/catalina.policy 2008/01/06 22:38:14 609451
+@@ -82,7 +82,19 @@
+
+ // These permissions apply to JULI
+ grant codeBase "file:${catalina.home}/bin/tomcat-juli.jar" {
+- permission java.security.AllPermission;
++ permission java.util.PropertyPermission "java.util.logging.config.class", "read";
++ permission java.util.PropertyPermission "java.util.logging.config.file", "read";
++ permission java.lang.RuntimePermission "shutdownHooks";
++ permission java.io.FilePermission "${catalina.base}${file.separator}conf${file.separator}logging.properties", "read";
++ permission java.util.PropertyPermission "catalina.base", "read";
++ permission java.util.logging.LoggingPermission "control";
++ permission java.io.FilePermission "${catalina.base}${file.separator}logs", "read, write";
++ permission java.io.FilePermission "${catalina.base}${file.separator}logs${file.separator}*", "read, write";
++ permission java.lang.RuntimePermission "getClassLoader";
++ // To enable per context logging configuration, permit read access to the appropriate file.
++ // Be sure that the logging configuration is secure before enabling such access
++ // eg for the examples web application:
++ // permission java.io.FilePermission "${catalina.base}${file.separator}webapps${file.separator}examples${file.separator}WEB-INF${file.separator}classes${file.separator}logging.properties", "read";
+ };
+
+ // These permissions apply to the servlet API classes
+
+
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-0128.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-0128.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-0128.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,13 @@
+--- ./jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java.orig 2008-04-10 11:29:31.000000000 -0400
++++ ./jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java 2008-04-10 11:30:19.000000000 -0400
+@@ -699,6 +699,10 @@ public abstract class AuthenticatorBase
+ Cookie cookie = new Cookie(Constants.SINGLE_SIGN_ON_COOKIE, ssoId);
+ cookie.setMaxAge(-1);
+ cookie.setPath("/");
++ // Bugzilla 41217
++ javax.servlet.ServletRequest r = (javax.servlet.ServletRequest) request;
++ cookie.setSecure(r.isSecure());
++
+ response.addCookie(cookie);
+
+ // Register this principal with our SSO valve
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-1232.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-1232.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-1232.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,90 @@
+--- jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/Constants.java (original)
++++ jakarta-tomcat-connectors/coyote/src/java/org/apache/coyote/Constants.java Wed Jul 30 02:26:27 2008
+@@ -53,4 +53,12 @@
+ public static final int STAGE_ENDED = 7;
+
+
++ /**
++ * If true, custom HTTP status messages will be used in headers.
++ */
++ public static final boolean USE_CUSTOM_STATUS_MSG_IN_HEADER =
++ Boolean.valueOf(System.getProperty(
++ "org.apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER",
++ "false")).booleanValue();
++
+ }
+
+--- jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/InternalOutputBuffer.java (original)
++++ jakarta-tomcat-connectors/http11/src/java/org/apache/coyote/http11/InternalOutputBuffer.java Wed Jul 30 02:26:27 2008
+@@ -448,11 +448,14 @@
+ buf[pos++] = Constants.SP;
+
+ // Write message
+- String message = response.getMessage();
++ String message = null;
++ if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER) {
++ message = response.getMessage();
++ }
+ if (message == null) {
+ write(getMessage(status));
+ } else {
+- write(message);
++ write(message.replace('\n', ' ').replace('\r', ' '));
+ }
+
+ // End the response status line
+
+--- jakarta-tomcat-connectors/jk/java/org/apache/jk/server/JkCoyoteHandler.java.org 2005-03-26 20:24:11.000000000 +0100
++++ jakarta-tomcat-connectors/jk/java/org/apache/jk/server/JkCoyoteHandler.java 2008-08-18 11:37:00.000000000 +0200
+@@ -363,7 +363,10 @@
+ mb=MessageBytes.newInstance();
+ ep.setNote( tmpMessageBytesNote, mb );
+ }
+- String message=res.getMessage();
++ String message=null;
++ if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER) {
++ message = res.getMessage();
++ }
+ if( message==null ){
+ if( System.getSecurityManager() != null ) {
+ message = (String)AccessController.doPrivileged(
+
+--- jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContextValve.java (original)
++++ jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContextValve.java Wed Jul 30 02:26:27 2008
+@@ -119,8 +119,7 @@
+ || (requestPathMB.equalsIgnoreCase("/META-INF"))
+ || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
+ || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
+- String requestURI = request.getDecodedRequestURI();
+- notFound(requestURI, response);
++ notFound(response);
+ return;
+ }
+
+@@ -136,8 +135,7 @@
+ // Select the Wrapper to be used for this Request
+ Wrapper wrapper = request.getWrapper();
+ if (wrapper == null) {
+- String requestURI = request.getDecodedRequestURI();
+- notFound(requestURI, response);
++ notFound(response);
+ return;
+ }
+
+@@ -206,13 +204,12 @@
+ * application, but currently that code runs at the wrapper level rather
+ * than the context level.
+ *
+- * @param requestURI The request URI for the requested resource
+ * @param response The response we are creating
+ */
+- private void notFound(String requestURI, HttpServletResponse response) {
++ private void notFound(HttpServletResponse response) {
+
+ try {
+- response.sendError(HttpServletResponse.SC_NOT_FOUND, requestURI);
++ response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ } catch (IllegalStateException e) {
+ ;
+ } catch (IOException e) {
+
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-1947.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-1947.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-1947.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,29 @@
+--- jakarta-tomcat-catalina/webapps/host-manager/WEB-INF/classes/org/apache/catalina/hostmanager/HTMLHostManagerServlet.java 2008-05-21 14:00:50.000000000 +0200
++++ jakarta-tomcat-catalina/webapps/host-manager/WEB-INF/classes/org/apache/catalina/hostmanager/HTMLHostManagerServlet.java 2008-07-27 21:51:18.000000000 +0200
+@@ -20,6 +20,7 @@
+ import java.io.IOException;
+ import java.io.PrintWriter;
+ import java.io.StringWriter;
++import java.net.URLEncoder;
+ import java.text.MessageFormat;
+ import java.util.Iterator;
+ import java.util.Map;
+@@ -273,15 +274,15 @@
+ args = new Object[6];
+ args[0] = response.encodeURL
+ (request.getContextPath() +
+- "/html/start?name=" + hostName);
++ "/html/start?name=" + URLEncoder.encode(hostName, "UTF-8"));
+ args[1] = hostsStart;
+ args[2] = response.encodeURL
+ (request.getContextPath() +
+- "/html/stop?name=" + hostName);
++ "/html/stop?name=" + URLEncoder.encode(hostName, "UTF-8"));
+ args[3] = hostsStop;
+ args[4] = response.encodeURL
+ (request.getContextPath() +
+- "/html/remove?name=" + hostName);
++ "/html/remove?name=" + URLEncoder.encode(hostName, "UTF-8"));
+ args[5] = hostsRemove;
+ if (host == this.host) {
+ writer.print(MessageFormat.format(
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-2370.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-2370.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-2370.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,41 @@
+--- jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/ApplicationContext.java (original)
++++ jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/ApplicationContext.java Wed Jul 30 02:34:21 2008
+@@ -379,10 +379,21 @@
+ throw new IllegalArgumentException
+ (sm.getString
+ ("applicationContext.requestDispatcher.iae", path));
++
++ // Get query string
++ String queryString = null;
++ int pos = path.indexOf('?');
++ if (pos >= 0) {
++ queryString = path.substring(pos + 1);
++ path = path.substring(0, pos);
++ }
++
+ path = normalize(path);
+ if (path == null)
+ return (null);
+
++ pos = path.length();
++
+ // Retrieve the thread local URI
+ MessageBytes uriMB = (MessageBytes) localUriMB.get();
+ if (uriMB == null) {
+@@ -394,15 +405,6 @@
+ uriMB.recycle();
+ }
+
+- // Get query string
+- String queryString = null;
+- int pos = path.indexOf('?');
+- if (pos >= 0) {
+- queryString = path.substring(pos + 1);
+- } else {
+- pos = path.length();
+- }
+-
+ // Retrieve the thread local mapping data
+ MappingData mappingData = (MappingData) localMappingData.get();
+ if (mappingData == null) {
+
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-2938.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-2938.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-CVE-2008-2938.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,83 @@
+--- jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/CoyoteAdapter.java 2008-07-17 13:13:43 UTC (rev 717)
++++ jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/connector/CoyoteAdapter.java 2008-07-17 17:43:56 UTC (rev 718)
+@@ -442,6 +442,12 @@
+ }
+ // Character decoding
+ convertURI(decodedURI, request);
++ // Check that the URI is still normalized
++ if (!checkNormalize(req.decodedURI())) {
++ res.setStatus(400);
++ res.setMessage("Invalid URI character encoding");
++ return false;
++ }
+ } else {
+ // The URL is chars or String, and has been sent using an in-memory
+ // protocol handler, we have to assume the URL has been properly
+@@ -821,6 +827,67 @@
+ }
+
+
++ /**
++ * Check that the URI is normalized following character decoding.
++ * <p>
++ * This method checks for "\", "//", "/./" and "/../". This method will
++ * return false if sequences that are supposed to be normalized still
++ * present in the URI.
++ *
++ * @param uriMB URI to be normalized
++ */
++ public static boolean checkNormalize(MessageBytes uriMB) {
++
++ CharChunk uriCC = uriMB.getCharChunk();
++ char[] c = uriCC.getChars();
++ int start = uriCC.getStart();
++ int end = uriCC.getEnd();
++
++ int pos = 0;
++
++ // Check for '\' and for null byte
++ for (pos = start; pos < end; pos++) {
++ if (c[pos] == '\\') {
++ return false;
++ }
++ if (c[pos] == 0) {
++ return false;
++ }
++ }
++
++ // Check for "//"
++ for (pos = start; pos < (end - 1); pos++) {
++ if (c[pos] == '/') {
++ if (c[pos + 1] == '/') {
++ return false;
++ }
++ }
++ }
++
++ // Check for URI ending with "/." or "/.."
++ if (((end - start) >= 2) && (c[end - 1] == '.')) {
++ if ((c[end - 2] == '/')
++ || ((c[end - 2] == '.')
++ && (c[end - 3] == '/'))) {
++ return false;
++ }
++ }
++
++ // Check for "/./"
++ if (uriCC.indexOf("/./", 0, 3, 0) >= 0) {
++ return false;
++ }
++
++ // Check for "/./"
++ if (uriCC.indexOf("/../", 0, 4, 0) >= 0) {
++ return false;
++ }
++
++ return true;
++
++ }
++
++
+ // ------------------------------------------------------ Protected Methods
+
+
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-IT168408.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-IT168408.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-IT168408.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,29 @@
+--- jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Parameters.java 2008-03-31 10:25:46.000000000 +0200
++++ jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/http/Parameters.java 2008-03-31 14:30:26.000000000 +0200
+@@ -499,17 +499,13 @@
+ public void processParameters( MessageBytes data, String encoding ) {
+ if( data==null || data.isNull() || data.getLength() <= 0 ) return;
+
+- if( data.getType() == MessageBytes.T_BYTES ) {
+- ByteChunk bc=data.getByteChunk();
+- processParameters( bc.getBytes(), bc.getOffset(),
+- bc.getLength(), encoding);
+- } else {
+- if (data.getType()!= MessageBytes.T_CHARS )
+- data.toChars();
+- CharChunk cc=data.getCharChunk();
+- processParameters( cc.getChars(), cc.getOffset(),
+- cc.getLength());
+- }
++ if (data.getType() != MessageBytes.T_BYTES) {
++ data.toBytes();
++ }
++ ByteChunk bc=data.getByteChunk();
++ processParameters( bc.getBytes(), bc.getOffset(),
++ bc.getLength(), encoding);
++
+ }
+
+ /** Debug purpose
+
+
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-jboss.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-jboss.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-jboss.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,5731 @@
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-servletapi-5/jakarta-servletapi-5.iml jakarta-tomcat-5.5.9-src/jakarta-servletapi-5/jakarta-servletapi-5.iml
+--- upstream/jakarta-tomcat-5.5.9-src/jakarta-servletapi-5/jakarta-servletapi-5.iml 1969-12-31 19:00:00.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-servletapi-5/jakarta-servletapi-5.iml 2005-09-26 01:21:13.000000000 -0400
+@@ -0,0 +1,21 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<module version="4" relativePaths="true" type="JAVA_MODULE">
++ <component name="ModuleRootManager" />
++ <component name="NewModuleRootManager">
++ <output url="file://$MODULE_DIR$/classes" />
++ <exclude-output />
++ <content url="file://$MODULE_DIR$">
++ <sourceFolder url="file://$MODULE_DIR$/jsr152/examples/WEB-INF/classes" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jsr152/examples/WEB-INF/jsp/applet" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jsr152/examples/plugin/applet" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jsr152/src/ant" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jsr152/src/share" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jsr154/examples/WEB-INF/classes" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jsr154/src/share" isTestSource="false" />
++ </content>
++ <orderEntry type="inheritedJdk" />
++ <orderEntry type="sourceFolder" forTests="false" />
++ <orderEntryProperties />
++ </component>
++</module>
++
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/build.properties.default jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/build.properties.default
+--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/build.properties.default 2005-03-26 14:22:24.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/build.properties.default 2005-09-26 01:27:47.000000000 -0400
+@@ -42,8 +42,8 @@
+ cvsroot=":pserver:anoncvs at cvs.apache.org:/home/cvspublic"
+
+ # ----- Default Base Path for Dependent Packages -----
+-base.path=/usr/share/java
+-#base.path=C:/path/to/the/repository
++base.path=/usr/share/java
++#base.path=C:/tmp/share/java
+ #base.path=/usr/local
+
+ # ----- Jakarta files base location -----
+@@ -59,7 +59,7 @@
+ base-struts.loc=http://archive.apache.org/dist/struts
+
+ # ----- Sourceforge files base location -----
+-base-sf.loc=http://unc.dl.sourceforge.net/sourceforge
++base-sf.loc=http://easynews.dl.sourceforge.net/sourceforge
+
+ # --------------------------------------------------
+ # REQUIRED LIBRARIES
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/jakarta-tomcat-5.iml jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/jakarta-tomcat-5.iml
+--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/jakarta-tomcat-5.iml 1969-12-31 19:00:00.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-5/jakarta-tomcat-5.iml 2005-09-26 01:21:13.000000000 -0400
+@@ -0,0 +1,13 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<module version="4" relativePaths="true" type="JAVA_MODULE">
++ <component name="ModuleRootManager" />
++ <component name="NewModuleRootManager">
++ <output url="file://$MODULE_DIR$/classes" />
++ <exclude-output />
++ <content url="file://$MODULE_DIR$" />
++ <orderEntry type="inheritedJdk" />
++ <orderEntry type="sourceFolder" forTests="false" />
++ <orderEntryProperties />
++ </component>
++</module>
++
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java
+--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java 2005-03-26 14:22:34.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java 2005-09-26 01:31:04.000000000 -0400
+@@ -5008,6 +5008,10 @@
+ destroy();
+ throw e;
+ }
++ // It's possible that addChild may have started us
++ if( initialized ) {
++ return;
++ }
+ }
+ super.init();
+
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java-1.177.txt jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java-1.177.txt
+--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java-1.177.txt 1969-12-31 19:00:00.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/core/StandardContext.java-1.177.txt 2005-09-26 01:29:47.000000000 -0400
+@@ -0,0 +1,5372 @@
++/*
++ * Copyright 1999,2004-2005 The Apache Software Foundation.
++ *
++ * 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.apache.catalina.core;
++
++import java.io.BufferedReader;
++import java.io.File;
++import java.io.FileInputStream;
++import java.io.FileOutputStream;
++import java.io.IOException;
++import java.io.InputStream;
++import java.io.InputStreamReader;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.ArrayList;
++import java.util.HashMap;
++import java.util.Hashtable;
++import java.util.Iterator;
++import java.util.Stack;
++import java.util.TreeMap;
++
++import javax.management.ListenerNotFoundException;
++import javax.management.MBeanNotificationInfo;
++import javax.management.MBeanRegistrationException;
++import javax.management.MBeanServer;
++import javax.management.MalformedObjectNameException;
++import javax.management.Notification;
++import javax.management.NotificationBroadcasterSupport;
++import javax.management.NotificationEmitter;
++import javax.management.NotificationFilter;
++import javax.management.NotificationListener;
++import javax.management.ObjectName;
++import javax.naming.NamingException;
++import javax.naming.directory.DirContext;
++import javax.servlet.FilterConfig;
++import javax.servlet.ServletContext;
++import javax.servlet.ServletContextAttributeListener;
++import javax.servlet.ServletContextEvent;
++import javax.servlet.ServletContextListener;
++import javax.servlet.ServletException;
++import javax.servlet.ServletRequestAttributeListener;
++import javax.servlet.ServletRequestListener;
++import javax.servlet.http.HttpSessionAttributeListener;
++import javax.servlet.http.HttpSessionListener;
++
++import org.apache.catalina.Container;
++import org.apache.catalina.ContainerListener;
++import org.apache.catalina.Context;
++import org.apache.catalina.Engine;
++import org.apache.catalina.Globals;
++import org.apache.catalina.Host;
++import org.apache.catalina.InstanceListener;
++import org.apache.catalina.Lifecycle;
++import org.apache.catalina.LifecycleException;
++import org.apache.catalina.LifecycleListener;
++import org.apache.catalina.Loader;
++import org.apache.catalina.Wrapper;
++import org.apache.catalina.deploy.ApplicationParameter;
++import org.apache.catalina.deploy.ErrorPage;
++import org.apache.catalina.deploy.FilterDef;
++import org.apache.catalina.deploy.FilterMap;
++import org.apache.catalina.deploy.LoginConfig;
++import org.apache.catalina.deploy.MessageDestination;
++import org.apache.catalina.deploy.MessageDestinationRef;
++import org.apache.catalina.deploy.NamingResources;
++import org.apache.catalina.deploy.SecurityCollection;
++import org.apache.catalina.deploy.SecurityConstraint;
++import org.apache.catalina.loader.WebappLoader;
++import org.apache.catalina.startup.ContextConfig;
++import org.apache.catalina.startup.TldConfig;
++import org.apache.catalina.util.CharsetMapper;
++import org.apache.catalina.util.ExtensionValidator;
++import org.apache.catalina.util.RequestUtil;
++import org.apache.catalina.util.URLEncoder;
++import org.apache.commons.logging.Log;
++import org.apache.commons.logging.LogFactory;
++import org.apache.commons.modeler.Registry;
++import org.apache.naming.ContextBindings;
++import org.apache.naming.resources.BaseDirContext;
++import org.apache.naming.resources.DirContextURLStreamHandler;
++import org.apache.naming.resources.FileDirContext;
++import org.apache.naming.resources.ProxyDirContext;
++import org.apache.naming.resources.WARDirContext;
++import org.apache.tomcat.util.compat.JdkCompat;
++
++/**
++ * Standard implementation of the <b>Context</b> interface. Each
++ * child container must be a Wrapper implementation to process the
++ * requests directed to a particular servlet.
++ *
++ * @author Craig R. McClanahan
++ * @author Remy Maucherat
++ * @version $Revision: 1.177 $ $Date: 2005/09/25 00:27:53 $
++ */
++
++public class StandardContext
++ extends ContainerBase
++ implements Context, Serializable, NotificationEmitter
++{
++ private static transient Log log = LogFactory.getLog(StandardContext.class);
++
++
++ // ----------------------------------------------------------- Constructors
++
++
++ /**
++ * Create a new StandardContext component with the default basic Valve.
++ */
++ public StandardContext() {
++
++ super();
++ pipeline.setBasic(new StandardContextValve());
++ broadcaster = new NotificationBroadcasterSupport();
++
++ }
++
++
++ // ----------------------------------------------------- Class Variables
++
++
++ /**
++ * The descriptive information string for this implementation.
++ */
++ private static final String info =
++ "org.apache.catalina.core.StandardContext/1.0";
++
++
++ /**
++ * JDK compatibility support
++ */
++ private static final JdkCompat jdkCompat = JdkCompat.getJdkCompat();
++
++
++ /**
++ * Array containing the safe characters set.
++ */
++ protected static URLEncoder urlEncoder;
++
++
++ /**
++ * GMT timezone - all HTTP dates are on GMT
++ */
++ static {
++ urlEncoder = new URLEncoder();
++ urlEncoder.addSafeCharacter('~');
++ urlEncoder.addSafeCharacter('-');
++ urlEncoder.addSafeCharacter('_');
++ urlEncoder.addSafeCharacter('.');
++ urlEncoder.addSafeCharacter('*');
++ urlEncoder.addSafeCharacter('/');
++ }
++
++
++ // ----------------------------------------------------- Instance Variables
++
++
++ /**
++ * The alternate deployment descriptor name.
++ */
++ private String altDDName = null;
++
++
++ /**
++ * Associated host name.
++ */
++ private String hostName;
++
++
++ /**
++ * The antiJARLocking flag for this Context.
++ */
++ private boolean antiJARLocking = false;
++
++
++ /**
++ * The antiResourceLocking flag for this Context.
++ */
++ private boolean antiResourceLocking = false;
++
++
++ /**
++ * The set of application listener class names configured for this
++ * application, in the order they were encountered in the web.xml file.
++ */
++ private String applicationListeners[] = new String[0];
++
++
++ /**
++ * The set of instantiated application event listener objects</code>.
++ */
++ private transient Object applicationEventListenersObjects[] =
++ new Object[0];
++
++
++ /**
++ * The set of instantiated application lifecycle listener objects</code>.
++ */
++ private transient Object applicationLifecycleListenersObjects[] =
++ new Object[0];
++
++
++ /**
++ * The set of application parameters defined for this application.
++ */
++ private ApplicationParameter applicationParameters[] =
++ new ApplicationParameter[0];
++
++
++ /**
++ * The application available flag for this Context.
++ */
++ private boolean available = false;
++
++ /**
++ * The broadcaster that sends j2ee notifications.
++ */
++ private NotificationBroadcasterSupport broadcaster = null;
++
++ /**
++ * The Locale to character set mapper for this application.
++ */
++ private transient CharsetMapper charsetMapper = null;
++
++
++ /**
++ * The Java class name of the CharsetMapper class to be created.
++ */
++ private String charsetMapperClass =
++ "org.apache.catalina.util.CharsetMapper";
++
++
++ /**
++ * The path to a file to save this Context information.
++ */
++ private String configFile = null;
++
++
++ /**
++ * The "correctly configured" flag for this Context.
++ */
++ private boolean configured = false;
++
++
++ /**
++ * The security constraints for this web application.
++ */
++ private SecurityConstraint constraints[] = new SecurityConstraint[0];
++
++
++ /**
++ * The ServletContext implementation associated with this Context.
++ */
++ private transient ApplicationContext context = null;
++
++
++ /**
++ * Compiler classpath to use.
++ */
++ private String compilerClasspath = null;
++
++
++ /**
++ * Should we attempt to use cookies for session id communication?
++ */
++ private boolean cookies = true;
++
++
++ /**
++ * Should we allow the <code>ServletContext.getContext()</code> method
++ * to access the context of other web applications in this server?
++ */
++ private boolean crossContext = false;
++
++
++ /**
++ * Encoded path.
++ */
++ private String encodedPath = null;
++
++
++ /**
++ * The "follow standard delegation model" flag that will be used to
++ * configure our ClassLoader.
++ */
++ private boolean delegate = false;
++
++
++ /**
++ * The display name of this web application.
++ */
++ private String displayName = null;
++
++
++ /**
++ * Override the default context xml location.
++ */
++ private String defaultContextXml;
++
++
++ /**
++ * Override the default web xml location.
++ */
++ private String defaultWebXml;
++
++
++ /**
++ * The distributable flag for this web application.
++ */
++ private boolean distributable = false;
++
++
++ /**
++ * The document root for this web application.
++ */
++ private String docBase = null;
++
++
++ /**
++ * The exception pages for this web application, keyed by fully qualified
++ * class name of the Java exception.
++ */
++ private HashMap exceptionPages = new HashMap();
++
++
++ /**
++ * The set of filter configurations (and associated filter instances) we
++ * have initialized, keyed by filter name.
++ */
++ private HashMap filterConfigs = new HashMap();
++
++
++ /**
++ * The set of filter definitions for this application, keyed by
++ * filter name.
++ */
++ private HashMap filterDefs = new HashMap();
++
++
++ /**
++ * The set of filter mappings for this application, in the order
++ * they were defined in the deployment descriptor.
++ */
++ private FilterMap filterMaps[] = new FilterMap[0];
++
++
++ /**
++ * The set of classnames of InstanceListeners that will be added
++ * to each newly created Wrapper by <code>createWrapper()</code>.
++ */
++ private String instanceListeners[] = new String[0];
++
++
++ /**
++ * The login configuration descriptor for this web application.
++ */
++ private LoginConfig loginConfig = null;
++
++
++ /**
++ * The mapper associated with this context.
++ */
++ private org.apache.tomcat.util.http.mapper.Mapper mapper =
++ new org.apache.tomcat.util.http.mapper.Mapper();
++
++
++ /**
++ * The naming context listener for this web application.
++ */
++ private transient NamingContextListener namingContextListener = null;
++
++
++ /**
++ * The naming resources for this web application.
++ */
++ private NamingResources namingResources = null;
++
++
++ /**
++ * The message destinations for this web application.
++ */
++ private HashMap messageDestinations = new HashMap();
++
++
++ /**
++ * The MIME mappings for this web application, keyed by extension.
++ */
++ private HashMap mimeMappings = new HashMap();
++
++
++ /**
++ * Special case: error page for status 200.
++ */
++ private ErrorPage okErrorPage = null;
++
++
++ /**
++ * The context initialization parameters for this web application,
++ * keyed by name.
++ */
++ private HashMap parameters = new HashMap();
++
++
++ /**
++ * The request processing pause flag (while reloading occurs)
++ */
++ private boolean paused = false;
++
++
++ /**
++ * The public identifier of the DTD for the web application deployment
++ * descriptor version we are currently parsing. This is used to support
++ * relaxed validation rules when processing version 2.2 web.xml files.
++ */
++ private String publicId = null;
++
++
++ /**
++ * The reloadable flag for this web application.
++ */
++ private boolean reloadable = false;
++
++
++ /**
++ * Unpack WAR property.
++ */
++ private boolean unpackWAR = true;
++
++
++ /**
++ * The DefaultContext override flag for this web application.
++ */
++ private boolean override = false;
++
++
++ /**
++ * The privileged flag for this web application.
++ */
++ private boolean privileged = false;
++
++
++ /**
++ * Should the next call to <code>addWelcomeFile()</code> cause replacement
++ * of any existing welcome files? This will be set before processing the
++ * web application's deployment descriptor, so that application specified
++ * choices <strong>replace</strong>, rather than append to, those defined
++ * in the global descriptor.
++ */
++ private boolean replaceWelcomeFiles = false;
++
++
++ /**
++ * The security role mappings for this application, keyed by role
++ * name (as used within the application).
++ */
++ private HashMap roleMappings = new HashMap();
++
++
++ /**
++ * The security roles for this application, keyed by role name.
++ */
++ private String securityRoles[] = new String[0];
++
++
++ /**
++ * The servlet mappings for this web application, keyed by
++ * matching pattern.
++ */
++ private HashMap servletMappings = new HashMap();
++
++
++ /**
++ * The session timeout (in minutes) for this web application.
++ */
++ private int sessionTimeout = 30;
++
++ /**
++ * The notification sequence number.
++ */
++ private long sequenceNumber = 0;
++
++ /**
++ * The status code error pages for this web application, keyed by
++ * HTTP status code (as an Integer).
++ */
++ private HashMap statusPages = new HashMap();
++
++
++ /**
++ * Set flag to true to cause the system.out and system.err to be redirected
++ * to the logger when executing a servlet.
++ */
++ private boolean swallowOutput = false;
++
++
++ /**
++ * The JSP tag libraries for this web application, keyed by URI
++ */
++ private HashMap taglibs = new HashMap();
++
++
++ /**
++ * The watched resources for this application.
++ */
++ private String watchedResources[] = new String[0];
++
++
++ /**
++ * The welcome files for this application.
++ */
++ private String welcomeFiles[] = new String[0];
++
++
++ /**
++ * The set of classnames of LifecycleListeners that will be added
++ * to each newly created Wrapper by <code>createWrapper()</code>.
++ */
++ private String wrapperLifecycles[] = new String[0];
++
++
++ /**
++ * The set of classnames of ContainerListeners that will be added
++ * to each newly created Wrapper by <code>createWrapper()</code>.
++ */
++ private String wrapperListeners[] = new String[0];
++
++
++ /**
++ * The pathname to the work directory for this context (relative to
++ * the server's home if not absolute).
++ */
++ private String workDir = null;
++
++
++ /**
++ * Java class name of the Wrapper class implementation we use.
++ */
++ private String wrapperClassName = StandardWrapper.class.getName();
++ private Class wrapperClass = null;
++
++
++ /**
++ * JNDI use flag.
++ */
++ private boolean useNaming = true;
++
++
++ /**
++ * Filesystem based flag.
++ */
++ private boolean filesystemBased = false;
++
++
++ /**
++ * Name of the associated naming context.
++ */
++ private String namingContextName = null;
++
++
++ /**
++ * Caching allowed flag.
++ */
++ private boolean cachingAllowed = true;
++
++
++ /**
++ * Case sensitivity.
++ */
++ protected boolean caseSensitive = true;
++
++
++ /**
++ * Allow linking.
++ */
++ protected boolean allowLinking = false;
++
++
++ /**
++ * Cache max size in KB.
++ */
++ protected int cacheMaxSize = 10240; // 10 MB
++
++
++ /**
++ * Cache TTL in ms.
++ */
++ protected int cacheTTL = 5000;
++
++
++ private boolean lazy=true;
++
++ /**
++ * Non proxied resources.
++ */
++ private transient DirContext webappResources = null;
++
++ private long startupTime;
++ private long startTime;
++ private long tldScanTime;
++
++ /**
++ * Name of the engine. If null, the domain is used.
++ */
++ private String engineName = null;
++ private String j2EEApplication="none";
++ private String j2EEServer="none";
++
++
++ /**
++ * Attribute value used to turn on/off XML validation
++ */
++ private boolean webXmlValidation = false;
++
++
++ /**
++ * Attribute value used to turn on/off XML namespace validation
++ */
++ private boolean webXmlNamespaceAware = false;
++
++ /**
++ * Attribute value used to turn on/off TLD processing
++ */
++ private boolean processTlds = true;
++
++ /**
++ * Attribute value used to turn on/off XML validation
++ */
++ private boolean tldValidation = false;
++
++
++ /**
++ * Attribute value used to turn on/off TLD XML namespace validation
++ */
++ private boolean tldNamespaceAware = false;
++
++
++ /**
++ * Should we save the configuration.
++ */
++ private boolean saveConfig = true;
++
++
++ // ----------------------------------------------------- Context Properties
++
++
++ public String getEncodedPath() {
++ return encodedPath;
++ }
++
++
++ public void setName( String name ) {
++ super.setName( name );
++ encodedPath = urlEncoder.encode(name);
++ }
++
++
++ /**
++ * Is caching allowed ?
++ */
++ public boolean isCachingAllowed() {
++ return cachingAllowed;
++ }
++
++
++ /**
++ * Set caching allowed flag.
++ */
++ public void setCachingAllowed(boolean cachingAllowed) {
++ this.cachingAllowed = cachingAllowed;
++ }
++
++
++ /**
++ * Set case sensitivity.
++ */
++ public void setCaseSensitive(boolean caseSensitive) {
++ this.caseSensitive = caseSensitive;
++ }
++
++
++ /**
++ * Is case sensitive ?
++ */
++ public boolean isCaseSensitive() {
++ return caseSensitive;
++ }
++
++
++ /**
++ * Set allow linking.
++ */
++ public void setAllowLinking(boolean allowLinking) {
++ this.allowLinking = allowLinking;
++ }
++
++
++ /**
++ * Is linking allowed.
++ */
++ public boolean isAllowLinking() {
++ return allowLinking;
++ }
++
++
++ /**
++ * Set cache TTL.
++ */
++ public void setCacheTTL(int cacheTTL) {
++ this.cacheTTL = cacheTTL;
++ }
++
++
++ /**
++ * Get cache TTL.
++ */
++ public int getCacheTTL() {
++ return cacheTTL;
++ }
++
++
++ /**
++ * Return the maximum size of the cache in KB.
++ */
++ public int getCacheMaxSize() {
++ return cacheMaxSize;
++ }
++
++
++ /**
++ * Set the maximum size of the cache in KB.
++ */
++ public void setCacheMaxSize(int cacheMaxSize) {
++ this.cacheMaxSize = cacheMaxSize;
++ }
++
++
++ /**
++ * Return the "follow standard delegation model" flag used to configure
++ * our ClassLoader.
++ */
++ public boolean getDelegate() {
++
++ return (this.delegate);
++
++ }
++
++
++ /**
++ * Set the "follow standard delegation model" flag used to configure
++ * our ClassLoader.
++ *
++ * @param delegate The new flag
++ */
++ public void setDelegate(boolean delegate) {
++
++ boolean oldDelegate = this.delegate;
++ this.delegate = delegate;
++ support.firePropertyChange("delegate", new Boolean(oldDelegate),
++ new Boolean(this.delegate));
++
++ }
++
++
++ /**
++ * Returns true if the internal naming support is used.
++ */
++ public boolean isUseNaming() {
++
++ return (useNaming);
++
++ }
++
++
++ /**
++ * Enables or disables naming.
++ */
++ public void setUseNaming(boolean useNaming) {
++ this.useNaming = useNaming;
++ }
++
++
++ /**
++ * Returns true if the resources associated with this context are
++ * filesystem based.
++ */
++ public boolean isFilesystemBased() {
++
++ return (filesystemBased);
++
++ }
++
++
++ /**
++ * Return the set of initialized application event listener objects,
++ * in the order they were specified in the web application deployment
++ * descriptor, for this application.
++ *
++ * @exception IllegalStateException if this method is called before
++ * this application has started, or after it has been stopped
++ */
++ public Object[] getApplicationEventListeners() {
++ return (applicationEventListenersObjects);
++ }
++
++
++ /**
++ * Store the set of initialized application event listener objects,
++ * in the order they were specified in the web application deployment
++ * descriptor, for this application.
++ *
++ * @param listeners The set of instantiated listener objects.
++ */
++ public void setApplicationEventListeners(Object listeners[]) {
++ applicationEventListenersObjects = listeners;
++ }
++
++
++ /**
++ * Return the set of initialized application lifecycle listener objects,
++ * in the order they were specified in the web application deployment
++ * descriptor, for this application.
++ *
++ * @exception IllegalStateException if this method is called before
++ * this application has started, or after it has been stopped
++ */
++ public Object[] getApplicationLifecycleListeners() {
++ return (applicationLifecycleListenersObjects);
++ }
++
++
++ /**
++ * Store the set of initialized application lifecycle listener objects,
++ * in the order they were specified in the web application deployment
++ * descriptor, for this application.
++ *
++ * @param listeners The set of instantiated listener objects.
++ */
++ public void setApplicationLifecycleListeners(Object listeners[]) {
++ applicationLifecycleListenersObjects = listeners;
++ }
++
++
++ /**
++ * Return the antiJARLocking flag for this Context.
++ */
++ public boolean getAntiJARLocking() {
++
++ return (this.antiJARLocking);
++
++ }
++
++
++ /**
++ * Return the antiResourceLocking flag for this Context.
++ */
++ public boolean getAntiResourceLocking() {
++
++ return (this.antiResourceLocking);
++
++ }
++
++
++ /**
++ * Set the antiJARLocking feature for this Context.
++ *
++ * @param antiJARLocking The new flag value
++ */
++ public void setAntiJARLocking(boolean antiJARLocking) {
++
++ boolean oldAntiJARLocking = this.antiJARLocking;
++ this.antiJARLocking = antiJARLocking;
++ support.firePropertyChange("antiJARLocking",
++ new Boolean(oldAntiJARLocking),
++ new Boolean(this.antiJARLocking));
++
++ }
++
++
++ /**
++ * Set the antiResourceLocking feature for this Context.
++ *
++ * @param antiResourceLocking The new flag value
++ */
++ public void setAntiResourceLocking(boolean antiResourceLocking) {
++
++ boolean oldAntiResourceLocking = this.antiResourceLocking;
++ this.antiResourceLocking = antiResourceLocking;
++ support.firePropertyChange("antiResourceLocking",
++ new Boolean(oldAntiResourceLocking),
++ new Boolean(this.antiResourceLocking));
++
++ }
++
++
++ /**
++ * Return the application available flag for this Context.
++ */
++ public boolean getAvailable() {
++
++ return (this.available);
++
++ }
++
++
++ /**
++ * Set the application available flag for this Context.
++ *
++ * @param available The new application available flag
++ */
++ public void setAvailable(boolean available) {
++
++ boolean oldAvailable = this.available;
++ this.available = available;
++ support.firePropertyChange("available",
++ new Boolean(oldAvailable),
++ new Boolean(this.available));
++
++ }
++
++
++ /**
++ * Return the Locale to character set mapper for this Context.
++ */
++ public CharsetMapper getCharsetMapper() {
++
++ // Create a mapper the first time it is requested
++ if (this.charsetMapper == null) {
++ try {
++ Class clazz = Class.forName(charsetMapperClass);
++ this.charsetMapper =
++ (CharsetMapper) clazz.newInstance();
++ } catch (Throwable t) {
++ this.charsetMapper = new CharsetMapper();
++ }
++ }
++
++ return (this.charsetMapper);
++
++ }
++
++
++ /**
++ * Set the Locale to character set mapper for this Context.
++ *
++ * @param mapper The new mapper
++ */
++ public void setCharsetMapper(CharsetMapper mapper) {
++
++ CharsetMapper oldCharsetMapper = this.charsetMapper;
++ this.charsetMapper = mapper;
++ if( mapper != null )
++ this.charsetMapperClass= mapper.getClass().getName();
++ support.firePropertyChange("charsetMapper", oldCharsetMapper,
++ this.charsetMapper);
++
++ }
++
++ /**
++ * Return the path to a file to save this Context information.
++ */
++ public String getConfigFile() {
++
++ return (this.configFile);
++
++ }
++
++
++ /**
++ * Set the path to a file to save this Context information.
++ *
++ * @param configFile The path to a file to save this Context information.
++ */
++ public void setConfigFile(String configFile) {
++
++ this.configFile = configFile;
++ }
++
++
++ /**
++ * Return the "correctly configured" flag for this Context.
++ */
++ public boolean getConfigured() {
++
++ return (this.configured);
++
++ }
++
++
++ /**
++ * Set the "correctly configured" flag for this Context. This can be
++ * set to false by startup listeners that detect a fatal configuration
++ * error to avoid the application from being made available.
++ *
++ * @param configured The new correctly configured flag
++ */
++ public void setConfigured(boolean configured) {
++
++ boolean oldConfigured = this.configured;
++ this.configured = configured;
++ support.firePropertyChange("configured",
++ new Boolean(oldConfigured),
++ new Boolean(this.configured));
++
++ }
++
++
++ /**
++ * Return the "use cookies for session ids" flag.
++ */
++ public boolean getCookies() {
++
++ return (this.cookies);
++
++ }
++
++
++ /**
++ * Set the "use cookies for session ids" flag.
++ *
++ * @param cookies The new flag
++ */
++ public void setCookies(boolean cookies) {
++
++ boolean oldCookies = this.cookies;
++ this.cookies = cookies;
++ support.firePropertyChange("cookies",
++ new Boolean(oldCookies),
++ new Boolean(this.cookies));
++
++ }
++
++
++ /**
++ * Return the "allow crossing servlet contexts" flag.
++ */
++ public boolean getCrossContext() {
++
++ return (this.crossContext);
++
++ }
++
++
++ /**
++ * Set the "allow crossing servlet contexts" flag.
++ *
++ * @param crossContext The new cross contexts flag
++ */
++ public void setCrossContext(boolean crossContext) {
++
++ boolean oldCrossContext = this.crossContext;
++ this.crossContext = crossContext;
++ support.firePropertyChange("crossContext",
++ new Boolean(oldCrossContext),
++ new Boolean(this.crossContext));
++
++ }
++
++ public String getDefaultContextXml() {
++ return defaultContextXml;
++ }
++
++ /**
++ * Set the location of the default context xml that will be used.
++ * If not absolute, it'll be made relative to the engine's base dir
++ * ( which defaults to catalina.base system property ).
++ *
++ * @param defaultContextXml The default web xml
++ */
++ public void setDefaultContextXml(String defaultContextXml) {
++ this.defaultContextXml = defaultContextXml;
++ }
++
++ public String getDefaultWebXml() {
++ return defaultWebXml;
++ }
++
++ /**
++ * Set the location of the default web xml that will be used.
++ * If not absolute, it'll be made relative to the engine's base dir
++ * ( which defaults to catalina.base system property ).
++ *
++ * @param defaultWebXml The default web xml
++ */
++ public void setDefaultWebXml(String defaultWebXml) {
++ this.defaultWebXml = defaultWebXml;
++ }
++
++ /**
++ * Gets the time (in milliseconds) it took to start this context.
++ *
++ * @return Time (in milliseconds) it took to start this context.
++ */
++ public long getStartupTime() {
++ return startupTime;
++ }
++
++ public void setStartupTime(long startupTime) {
++ this.startupTime = startupTime;
++ }
++
++ public long getTldScanTime() {
++ return tldScanTime;
++ }
++
++ public void setTldScanTime(long tldScanTime) {
++ this.tldScanTime = tldScanTime;
++ }
++
++ /**
++ * Return the display name of this web application.
++ */
++ public String getDisplayName() {
++
++ return (this.displayName);
++
++ }
++
++
++ /**
++ * Return the alternate Deployment Descriptor name.
++ */
++ public String getAltDDName(){
++ return altDDName;
++ }
++
++
++ /**
++ * Set an alternate Deployment Descriptor name.
++ */
++ public void setAltDDName(String altDDName) {
++ this.altDDName = altDDName;
++ if (context != null) {
++ context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
++ }
++ }
++
++
++ /**
++ * Return the compiler classpath.
++ */
++ public String getCompilerClasspath(){
++ return compilerClasspath;
++ }
++
++
++ /**
++ * Set the compiler classpath.
++ */
++ public void setCompilerClasspath(String compilerClasspath) {
++ this.compilerClasspath = compilerClasspath;
++ }
++
++
++ /**
++ * Set the display name of this web application.
++ *
++ * @param displayName The new display name
++ */
++ public void setDisplayName(String displayName) {
++
++ String oldDisplayName = this.displayName;
++ this.displayName = displayName;
++ support.firePropertyChange("displayName", oldDisplayName,
++ this.displayName);
++ }
++
++
++ /**
++ * Return the distributable flag for this web application.
++ */
++ public boolean getDistributable() {
++
++ return (this.distributable);
++
++ }
++
++ /**
++ * Set the distributable flag for this web application.
++ *
++ * @param distributable The new distributable flag
++ */
++ public void setDistributable(boolean distributable) {
++ boolean oldDistributable = this.distributable;
++ this.distributable = distributable;
++ support.firePropertyChange("distributable",
++ new Boolean(oldDistributable),
++ new Boolean(this.distributable));
++
++ // Bugzilla 32866
++ if(getManager() != null) {
++ if(log.isDebugEnabled()) {
++ log.debug("Propagating distributable=" + distributable
++ + " to manager");
++ }
++ getManager().setDistributable(distributable);
++ }
++ }
++
++
++ /**
++ * Return the document root for this Context. This can be an absolute
++ * pathname, a relative pathname, or a URL.
++ */
++ public String getDocBase() {
++
++ return (this.docBase);
++
++ }
++
++
++ /**
++ * Set the document root for this Context. This can be an absolute
++ * pathname, a relative pathname, or a URL.
++ *
++ * @param docBase The new document root
++ */
++ public void setDocBase(String docBase) {
++
++ this.docBase = docBase;
++
++ }
++
++ // experimental
++ public boolean isLazy() {
++ return lazy;
++ }
++
++ public void setLazy(boolean lazy) {
++ this.lazy = lazy;
++ }
++
++
++ /**
++ * Return descriptive information about this Container implementation and
++ * the corresponding version number, in the format
++ * <code><description>/<version></code>.
++ */
++ public String getInfo() {
++
++ return (info);
++
++ }
++
++ public String getEngineName() {
++ if( engineName != null ) return engineName;
++ return domain;
++ }
++
++ public void setEngineName(String engineName) {
++ this.engineName = engineName;
++ }
++
++ public String getJ2EEApplication() {
++ return j2EEApplication;
++ }
++
++ public void setJ2EEApplication(String j2EEApplication) {
++ this.j2EEApplication = j2EEApplication;
++ }
++
++ public String getJ2EEServer() {
++ return j2EEServer;
++ }
++
++ public void setJ2EEServer(String j2EEServer) {
++ this.j2EEServer = j2EEServer;
++ }
++
++
++ /**
++ * Set the Loader with which this Context is associated.
++ *
++ * @param loader The newly associated loader
++ */
++ public synchronized void setLoader(Loader loader) {
++
++ super.setLoader(loader);
++
++ }
++
++
++ /**
++ * Return the login configuration descriptor for this web application.
++ */
++ public LoginConfig getLoginConfig() {
++
++ return (this.loginConfig);
++
++ }
++
++
++ /**
++ * Set the login configuration descriptor for this web application.
++ *
++ * @param config The new login configuration
++ */
++ public void setLoginConfig(LoginConfig config) {
++
++ // Validate the incoming property value
++ if (config == null)
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.loginConfig.required"));
++ String loginPage = config.getLoginPage();
++ if ((loginPage != null) && !loginPage.startsWith("/")) {
++ if (isServlet22()) {
++ if(log.isDebugEnabled())
++ log.debug(sm.getString("standardContext.loginConfig.loginWarning",
++ loginPage));
++ config.setLoginPage("/" + loginPage);
++ } else {
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.loginConfig.loginPage",
++ loginPage));
++ }
++ }
++ String errorPage = config.getErrorPage();
++ if ((errorPage != null) && !errorPage.startsWith("/")) {
++ if (isServlet22()) {
++ if(log.isDebugEnabled())
++ log.debug(sm.getString("standardContext.loginConfig.errorWarning",
++ errorPage));
++ config.setErrorPage("/" + errorPage);
++ } else {
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.loginConfig.errorPage",
++ errorPage));
++ }
++ }
++
++ // Process the property setting change
++ LoginConfig oldLoginConfig = this.loginConfig;
++ this.loginConfig = config;
++ support.firePropertyChange("loginConfig",
++ oldLoginConfig, this.loginConfig);
++
++ }
++
++
++ /**
++ * Get the mapper associated with the context.
++ */
++ public org.apache.tomcat.util.http.mapper.Mapper getMapper() {
++ return (mapper);
++ }
++
++
++ /**
++ * Return the naming resources associated with this web application.
++ */
++ public NamingResources getNamingResources() {
++
++ if (namingResources == null) {
++ setNamingResources(new NamingResources());
++ }
++ return (namingResources);
++
++ }
++
++
++ /**
++ * Set the naming resources for this web application.
++ *
++ * @param namingResources The new naming resources
++ */
++ public void setNamingResources(NamingResources namingResources) {
++
++ // Process the property setting change
++ NamingResources oldNamingResources = this.namingResources;
++ this.namingResources = namingResources;
++ namingResources.setContainer(this);
++ support.firePropertyChange("namingResources",
++ oldNamingResources, this.namingResources);
++
++ }
++
++
++ /**
++ * Return the context path for this Context.
++ */
++ public String getPath() {
++
++ return (getName());
++
++ }
++
++
++ /**
++ * Set the context path for this Context.
++ * <p>
++ * <b>IMPLEMENTATION NOTE</b>: The context path is used as the "name" of
++ * a Context, because it must be unique.
++ *
++ * @param path The new context path
++ */
++ public void setPath(String path) {
++ // XXX Use host in name
++ setName(RequestUtil.URLDecode(path));
++
++ }
++
++
++ /**
++ * Return the public identifier of the deployment descriptor DTD that is
++ * currently being parsed.
++ */
++ public String getPublicId() {
++
++ return (this.publicId);
++
++ }
++
++
++ /**
++ * Set the public identifier of the deployment descriptor DTD that is
++ * currently being parsed.
++ *
++ * @param publicId The public identifier
++ */
++ public void setPublicId(String publicId) {
++
++ if (log.isDebugEnabled())
++ log.debug("Setting deployment descriptor public ID to '" +
++ publicId + "'");
++
++ String oldPublicId = this.publicId;
++ this.publicId = publicId;
++ support.firePropertyChange("publicId", oldPublicId, publicId);
++
++ }
++
++
++ /**
++ * Return the reloadable flag for this web application.
++ */
++ public boolean getReloadable() {
++
++ return (this.reloadable);
++
++ }
++
++
++ /**
++ * Return the DefaultContext override flag for this web application.
++ */
++ public boolean getOverride() {
++
++ return (this.override);
++
++ }
++
++
++ /**
++ * Return the privileged flag for this web application.
++ */
++ public boolean getPrivileged() {
++
++ return (this.privileged);
++
++ }
++
++
++ /**
++ * Set the privileged flag for this web application.
++ *
++ * @param privileged The new privileged flag
++ */
++ public void setPrivileged(boolean privileged) {
++
++ boolean oldPrivileged = this.privileged;
++ this.privileged = privileged;
++ support.firePropertyChange("privileged",
++ new Boolean(oldPrivileged),
++ new Boolean(this.privileged));
++
++ }
++
++
++ /**
++ * Set the reloadable flag for this web application.
++ *
++ * @param reloadable The new reloadable flag
++ */
++ public void setReloadable(boolean reloadable) {
++
++ boolean oldReloadable = this.reloadable;
++ this.reloadable = reloadable;
++ support.firePropertyChange("reloadable",
++ new Boolean(oldReloadable),
++ new Boolean(this.reloadable));
++
++ }
++
++
++ /**
++ * Set the DefaultContext override flag for this web application.
++ *
++ * @param override The new override flag
++ */
++ public void setOverride(boolean override) {
++
++ boolean oldOverride = this.override;
++ this.override = override;
++ support.firePropertyChange("override",
++ new Boolean(oldOverride),
++ new Boolean(this.override));
++
++ }
++
++
++ /**
++ * Return the "replace welcome files" property.
++ */
++ public boolean isReplaceWelcomeFiles() {
++
++ return (this.replaceWelcomeFiles);
++
++ }
++
++
++ /**
++ * Set the "replace welcome files" property.
++ *
++ * @param replaceWelcomeFiles The new property value
++ */
++ public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) {
++
++ boolean oldReplaceWelcomeFiles = this.replaceWelcomeFiles;
++ this.replaceWelcomeFiles = replaceWelcomeFiles;
++ support.firePropertyChange("replaceWelcomeFiles",
++ new Boolean(oldReplaceWelcomeFiles),
++ new Boolean(this.replaceWelcomeFiles));
++
++ }
++
++
++ /**
++ * Return the servlet context for which this Context is a facade.
++ */
++ public ServletContext getServletContext() {
++
++ if (context == null) {
++ context = new ApplicationContext(getBasePath(), this);
++ if (altDDName != null)
++ context.setAttribute(Globals.ALT_DD_ATTR,altDDName);
++ }
++ return (context.getFacade());
++
++ }
++
++
++ /**
++ * Return the default session timeout (in minutes) for this
++ * web application.
++ */
++ public int getSessionTimeout() {
++
++ return (this.sessionTimeout);
++
++ }
++
++
++ /**
++ * Set the default session timeout (in minutes) for this
++ * web application.
++ *
++ * @param timeout The new default session timeout
++ */
++ public void setSessionTimeout(int timeout) {
++
++ int oldSessionTimeout = this.sessionTimeout;
++ /*
++ * SRV.13.4 ("Deployment Descriptor"):
++ * If the timeout is 0 or less, the container ensures the default
++ * behaviour of sessions is never to time out.
++ */
++ this.sessionTimeout = (timeout == 0) ? -1 : timeout;
++ support.firePropertyChange("sessionTimeout",
++ new Integer(oldSessionTimeout),
++ new Integer(this.sessionTimeout));
++
++ }
++
++
++ /**
++ * Return the value of the swallowOutput flag.
++ */
++ public boolean getSwallowOutput() {
++
++ return (this.swallowOutput);
++
++ }
++
++
++ /**
++ * Set the value of the swallowOutput flag. If set to true, the system.out
++ * and system.err will be redirected to the logger during a servlet
++ * execution.
++ *
++ * @param swallowOutput The new value
++ */
++ public void setSwallowOutput(boolean swallowOutput) {
++
++ boolean oldSwallowOutput = this.swallowOutput;
++ this.swallowOutput = swallowOutput;
++ support.firePropertyChange("swallowOutput",
++ new Boolean(oldSwallowOutput),
++ new Boolean(this.swallowOutput));
++
++ }
++
++
++ /**
++ * Unpack WAR flag accessor.
++ */
++ public boolean getUnpackWAR() {
++
++ return (unpackWAR);
++
++ }
++
++
++ /**
++ * Unpack WAR flag mutator.
++ */
++ public void setUnpackWAR(boolean unpackWAR) {
++
++ this.unpackWAR = unpackWAR;
++
++ }
++
++ /**
++ * Return the Java class name of the Wrapper implementation used
++ * for servlets registered in this Context.
++ */
++ public String getWrapperClass() {
++
++ return (this.wrapperClassName);
++
++ }
++
++
++ /**
++ * Set the Java class name of the Wrapper implementation used
++ * for servlets registered in this Context.
++ *
++ * @param wrapperClassName The new wrapper class name
++ *
++ * @throws IllegalArgumentException if the specified wrapper class
++ * cannot be found or is not a subclass of StandardWrapper
++ */
++ public void setWrapperClass(String wrapperClassName) {
++
++ this.wrapperClassName = wrapperClassName;
++
++ try {
++ wrapperClass = Class.forName(wrapperClassName);
++ if (!StandardWrapper.class.isAssignableFrom(wrapperClass)) {
++ throw new IllegalArgumentException(
++ sm.getString("standardContext.invalidWrapperClass",
++ wrapperClassName));
++ }
++ } catch (ClassNotFoundException cnfe) {
++ throw new IllegalArgumentException(cnfe.getMessage());
++ }
++ }
++
++
++ /**
++ * Set the resources DirContext object with which this Container is
++ * associated.
++ *
++ * @param resources The newly associated DirContext
++ */
++ public synchronized void setResources(DirContext resources) {
++
++ if (started) {
++ throw new IllegalStateException
++ (sm.getString("standardContext.resources.started"));
++ }
++
++ DirContext oldResources = this.webappResources;
++ if (oldResources == resources)
++ return;
++
++ if (resources instanceof BaseDirContext) {
++ ((BaseDirContext) resources).setCached(isCachingAllowed());
++ ((BaseDirContext) resources).setCacheTTL(getCacheTTL());
++ ((BaseDirContext) resources).setCacheMaxSize(getCacheMaxSize());
++ }
++ if (resources instanceof FileDirContext) {
++ filesystemBased = true;
++ ((FileDirContext) resources).setCaseSensitive(isCaseSensitive());
++ ((FileDirContext) resources).setAllowLinking(isAllowLinking());
++ }
++ this.webappResources = resources;
++
++ // The proxied resources will be refreshed on start
++ this.resources = null;
++
++ support.firePropertyChange("resources", oldResources,
++ this.webappResources);
++
++ }
++
++
++ // ------------------------------------------------------ Public Properties
++
++
++ /**
++ * Return the Locale to character set mapper class for this Context.
++ */
++ public String getCharsetMapperClass() {
++
++ return (this.charsetMapperClass);
++
++ }
++
++
++ /**
++ * Set the Locale to character set mapper class for this Context.
++ *
++ * @param mapper The new mapper class
++ */
++ public void setCharsetMapperClass(String mapper) {
++
++ String oldCharsetMapperClass = this.charsetMapperClass;
++ this.charsetMapperClass = mapper;
++ support.firePropertyChange("charsetMapperClass",
++ oldCharsetMapperClass,
++ this.charsetMapperClass);
++
++ }
++
++
++ /** Get the absolute path to the work dir.
++ * To avoid duplication.
++ *
++ * @return The work path
++ */
++ public String getWorkPath() {
++ File workDir = new File(getWorkDir());
++ if (!workDir.isAbsolute()) {
++ File catalinaHome = engineBase();
++ String catalinaHomePath = null;
++ try {
++ catalinaHomePath = catalinaHome.getCanonicalPath();
++ workDir = new File(catalinaHomePath,
++ getWorkDir());
++ } catch (IOException e) {
++ log.warn("Exception obtaining work path for " + getPath());
++ }
++ }
++ return workDir.getAbsolutePath();
++ }
++
++ /**
++ * Return the work directory for this Context.
++ */
++ public String getWorkDir() {
++
++ return (this.workDir);
++
++ }
++
++
++ /**
++ * Set the work directory for this Context.
++ *
++ * @param workDir The new work directory
++ */
++ public void setWorkDir(String workDir) {
++
++ this.workDir = workDir;
++
++ if (started) {
++ postWorkDirectory();
++ }
++ }
++
++
++ /**
++ * Save config ?
++ */
++ public boolean isSaveConfig() {
++ return saveConfig;
++ }
++
++
++ /**
++ * Set save config flag.
++ */
++ public void setSaveConfig(boolean saveConfig) {
++ this.saveConfig = saveConfig;
++ }
++
++
++ // -------------------------------------------------------- Context Methods
++
++
++ /**
++ * Add a new Listener class name to the set of Listeners
++ * configured for this application.
++ *
++ * @param listener Java class name of a listener class
++ */
++ public void addApplicationListener(String listener) {
++
++ synchronized (applicationListeners) {
++ String results[] =new String[applicationListeners.length + 1];
++ for (int i = 0; i < applicationListeners.length; i++) {
++ if (listener.equals(applicationListeners[i]))
++ return;
++ results[i] = applicationListeners[i];
++ }
++ results[applicationListeners.length] = listener;
++ applicationListeners = results;
++ }
++ fireContainerEvent("addApplicationListener", listener);
++
++ // FIXME - add instance if already started?
++
++ }
++
++
++ /**
++ * Add a new application parameter for this application.
++ *
++ * @param parameter The new application parameter
++ */
++ public void addApplicationParameter(ApplicationParameter parameter) {
++
++ synchronized (applicationParameters) {
++ String newName = parameter.getName();
++ for (int i = 0; i < applicationParameters.length; i++) {
++ if (newName.equals(applicationParameters[i].getName()) &&
++ !applicationParameters[i].getOverride())
++ return;
++ }
++ ApplicationParameter results[] =
++ new ApplicationParameter[applicationParameters.length + 1];
++ System.arraycopy(applicationParameters, 0, results, 0,
++ applicationParameters.length);
++ results[applicationParameters.length] = parameter;
++ applicationParameters = results;
++ }
++ fireContainerEvent("addApplicationParameter", parameter);
++
++ }
++
++
++ /**
++ * Add a child Container, only if the proposed child is an implementation
++ * of Wrapper.
++ *
++ * @param child Child container to be added
++ *
++ * @exception IllegalArgumentException if the proposed container is
++ * not an implementation of Wrapper
++ */
++ public void addChild(Container child) {
++
++ // Global JspServlet
++ Wrapper oldJspServlet = null;
++
++ if (!(child instanceof Wrapper)) {
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.notWrapper"));
++ }
++
++ Wrapper wrapper = (Wrapper) child;
++ boolean isJspServlet = "jsp".equals(child.getName());
++
++ // Allow webapp to override JspServlet inherited from global web.xml.
++ if (isJspServlet) {
++ oldJspServlet = (Wrapper) findChild("jsp");
++ if (oldJspServlet != null) {
++ removeChild(oldJspServlet);
++ }
++ }
++
++ String jspFile = wrapper.getJspFile();
++ if ((jspFile != null) && !jspFile.startsWith("/")) {
++ if (isServlet22()) {
++ if(log.isDebugEnabled())
++ log.debug(sm.getString("standardContext.wrapper.warning",
++ jspFile));
++ wrapper.setJspFile("/" + jspFile);
++ } else {
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.wrapper.error", jspFile));
++ }
++ }
++
++ super.addChild(child);
++
++ if (isJspServlet && oldJspServlet != null) {
++ /*
++ * The webapp-specific JspServlet inherits all the mappings
++ * specified in the global web.xml, and may add additional ones.
++ */
++ String[] jspMappings = oldJspServlet.findMappings();
++ for (int i=0; jspMappings!=null && i<jspMappings.length; i++) {
++ addServletMapping(jspMappings[i], child.getName());
++ }
++ }
++ }
++
++
++ /**
++ * Add a security constraint to the set for this web application.
++ */
++ public void addConstraint(SecurityConstraint constraint) {
++
++ // Validate the proposed constraint
++ SecurityCollection collections[] = constraint.findCollections();
++ for (int i = 0; i < collections.length; i++) {
++ String patterns[] = collections[i].findPatterns();
++ for (int j = 0; j < patterns.length; j++) {
++ patterns[j] = adjustURLPattern(patterns[j]);
++ if (!validateURLPattern(patterns[j]))
++ throw new IllegalArgumentException
++ (sm.getString
++ ("standardContext.securityConstraint.pattern",
++ patterns[j]));
++ }
++ }
++
++ // Add this constraint to the set for our web application
++ synchronized (constraints) {
++ SecurityConstraint results[] =
++ new SecurityConstraint[constraints.length + 1];
++ for (int i = 0; i < constraints.length; i++)
++ results[i] = constraints[i];
++ results[constraints.length] = constraint;
++ constraints = results;
++ }
++
++ }
++
++
++
++ /**
++ * Add an error page for the specified error or Java exception.
++ *
++ * @param errorPage The error page definition to be added
++ */
++ public void addErrorPage(ErrorPage errorPage) {
++ // Validate the input parameters
++ if (errorPage == null)
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.errorPage.required"));
++ String location = errorPage.getLocation();
++ if ((location != null) && !location.startsWith("/")) {
++ if (isServlet22()) {
++ if(log.isDebugEnabled())
++ log.debug(sm.getString("standardContext.errorPage.warning",
++ location));
++ errorPage.setLocation("/" + location);
++ } else {
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.errorPage.error",
++ location));
++ }
++ }
++
++ // Add the specified error page to our internal collections
++ String exceptionType = errorPage.getExceptionType();
++ if (exceptionType != null) {
++ synchronized (exceptionPages) {
++ exceptionPages.put(exceptionType, errorPage);
++ }
++ } else {
++ synchronized (statusPages) {
++ if (errorPage.getErrorCode() == 200) {
++ this.okErrorPage = errorPage;
++ }
++ statusPages.put(new Integer(errorPage.getErrorCode()),
++ errorPage);
++ }
++ }
++ fireContainerEvent("addErrorPage", errorPage);
++
++ }
++
++
++ /**
++ * Add a filter definition to this Context.
++ *
++ * @param filterDef The filter definition to be added
++ */
++ public void addFilterDef(FilterDef filterDef) {
++
++ synchronized (filterDefs) {
++ filterDefs.put(filterDef.getFilterName(), filterDef);
++ }
++ fireContainerEvent("addFilterDef", filterDef);
++
++ }
++
++
++ /**
++ * Add a filter mapping to this Context.
++ *
++ * @param filterMap The filter mapping to be added
++ *
++ * @exception IllegalArgumentException if the specified filter name
++ * does not match an existing filter definition, or the filter mapping
++ * is malformed
++ */
++ public void addFilterMap(FilterMap filterMap) {
++
++ // Validate the proposed filter mapping
++ String filterName = filterMap.getFilterName();
++ String servletName = filterMap.getServletName();
++ String urlPattern = filterMap.getURLPattern();
++ if (findFilterDef(filterName) == null)
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.filterMap.name", filterName));
++ if ((servletName == null) && (urlPattern == null))
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.filterMap.either"));
++ if ((servletName != null) && (urlPattern != null))
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.filterMap.either"));
++ // Because filter-pattern is new in 2.3, no need to adjust
++ // for 2.2 backwards compatibility
++ if ((urlPattern != null) && !validateURLPattern(urlPattern))
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.filterMap.pattern",
++ urlPattern));
++
++ // Add this filter mapping to our registered set
++ synchronized (filterMaps) {
++ FilterMap results[] =new FilterMap[filterMaps.length + 1];
++ System.arraycopy(filterMaps, 0, results, 0, filterMaps.length);
++ results[filterMaps.length] = filterMap;
++ filterMaps = results;
++ }
++ fireContainerEvent("addFilterMap", filterMap);
++
++ }
++
++
++ /**
++ * Add the classname of an InstanceListener to be added to each
++ * Wrapper appended to this Context.
++ *
++ * @param listener Java class name of an InstanceListener class
++ */
++ public void addInstanceListener(String listener) {
++
++ synchronized (instanceListeners) {
++ String results[] =new String[instanceListeners.length + 1];
++ for (int i = 0; i < instanceListeners.length; i++)
++ results[i] = instanceListeners[i];
++ results[instanceListeners.length] = listener;
++ instanceListeners = results;
++ }
++ fireContainerEvent("addInstanceListener", listener);
++
++ }
++
++ /**
++ * Add the given URL pattern as a jsp-property-group. This maps
++ * resources that match the given pattern so they will be passed
++ * to the JSP container. Though there are other elements in the
++ * property group, we only care about the URL pattern here. The
++ * JSP container will parse the rest.
++ *
++ * @param pattern URL pattern to be mapped
++ */
++ public void addJspMapping(String pattern) {
++ String servletName = findServletMapping("*.jsp");
++ if (servletName == null) {
++ servletName = "jsp";
++ }
++
++ if( findChild(servletName) != null) {
++ addServletMapping(pattern, servletName, true);
++ } else {
++ if(log.isDebugEnabled())
++ log.debug("Skiping " + pattern + " , no servlet " + servletName);
++ }
++ }
++
++
++ /**
++ * Add a Locale Encoding Mapping (see Sec 5.4 of Servlet spec 2.4)
++ *
++ * @param locale locale to map an encoding for
++ * @param encoding encoding to be used for a give locale
++ */
++ public void addLocaleEncodingMappingParameter(String locale, String encoding){
++ getCharsetMapper().addCharsetMappingFromDeploymentDescriptor(locale, encoding);
++ }
++
++
++ /**
++ * Add a message destination for this web application.
++ *
++ * @param md New message destination
++ */
++ public void addMessageDestination(MessageDestination md) {
++
++ synchronized (messageDestinations) {
++ messageDestinations.put(md.getName(), md);
++ }
++ fireContainerEvent("addMessageDestination", md.getName());
++
++ }
++
++
++ /**
++ * Add a message destination reference for this web application.
++ *
++ * @param mdr New message destination reference
++ */
++ public void addMessageDestinationRef
++ (MessageDestinationRef mdr) {
++
++ namingResources.addMessageDestinationRef(mdr);
++ fireContainerEvent("addMessageDestinationRef", mdr.getName());
++
++ }
++
++
++ /**
++ * Add a new MIME mapping, replacing any existing mapping for
++ * the specified extension.
++ *
++ * @param extension Filename extension being mapped
++ * @param mimeType Corresponding MIME type
++ */
++ public void addMimeMapping(String extension, String mimeType) {
++
++ synchronized (mimeMappings) {
++ mimeMappings.put(extension, mimeType);
++ }
++ fireContainerEvent("addMimeMapping", extension);
++
++ }
++
++
++ /**
++ * Add a new context initialization parameter.
++ *
++ * @param name Name of the new parameter
++ * @param value Value of the new parameter
++ *
++ * @exception IllegalArgumentException if the name or value is missing,
++ * or if this context initialization parameter has already been
++ * registered
++ */
++ public void addParameter(String name, String value) {
++ // Validate the proposed context initialization parameter
++ if ((name == null) || (value == null))
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.parameter.required"));
++ if (parameters.get(name) != null)
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.parameter.duplicate", name));
++
++ // Add this parameter to our defined set
++ synchronized (parameters) {
++ parameters.put(name, value);
++ }
++ fireContainerEvent("addParameter", name);
++
++ }
++
++
++ /**
++ * Add a security role reference for this web application.
++ *
++ * @param role Security role used in the application
++ * @param link Actual security role to check for
++ */
++ public void addRoleMapping(String role, String link) {
++
++ synchronized (roleMappings) {
++ roleMappings.put(role, link);
++ }
++ fireContainerEvent("addRoleMapping", role);
++
++ }
++
++
++ /**
++ * Add a new security role for this web application.
++ *
++ * @param role New security role
++ */
++ public void addSecurityRole(String role) {
++
++ synchronized (securityRoles) {
++ String results[] =new String[securityRoles.length + 1];
++ for (int i = 0; i < securityRoles.length; i++)
++ results[i] = securityRoles[i];
++ results[securityRoles.length] = role;
++ securityRoles = results;
++ }
++ fireContainerEvent("addSecurityRole", role);
++
++ }
++
++
++ /**
++ * Add a new servlet mapping, replacing any existing mapping for
++ * the specified pattern.
++ *
++ * @param pattern URL pattern to be mapped
++ * @param name Name of the corresponding servlet to execute
++ *
++ * @exception IllegalArgumentException if the specified servlet name
++ * is not known to this Context
++ */
++ public void addServletMapping(String pattern, String name) {
++ addServletMapping(pattern, name, false);
++ }
++
++
++ /**
++ * Add a new servlet mapping, replacing any existing mapping for
++ * the specified pattern.
++ *
++ * @param pattern URL pattern to be mapped
++ * @param name Name of the corresponding servlet to execute
++ * @param jspWildCard true if name identifies the JspServlet
++ * and pattern contains a wildcard; false otherwise
++ *
++ * @exception IllegalArgumentException if the specified servlet name
++ * is not known to this Context
++ */
++ public void addServletMapping(String pattern, String name,
++ boolean jspWildCard) {
++ // Validate the proposed mapping
++ if (findChild(name) == null)
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.servletMap.name", name));
++ pattern = adjustURLPattern(RequestUtil.URLDecode(pattern));
++ if (!validateURLPattern(pattern))
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.servletMap.pattern", pattern));
++
++ // Add this mapping to our registered set
++ synchronized (servletMappings) {
++ String name2 = (String) servletMappings.get(pattern);
++ if (name2 != null) {
++ // Don't allow more than one servlet on the same pattern
++ Wrapper wrapper = (Wrapper) findChild(name2);
++ wrapper.removeMapping(pattern);
++ mapper.removeWrapper(pattern);
++ }
++ servletMappings.put(pattern, name);
++ }
++ Wrapper wrapper = (Wrapper) findChild(name);
++ wrapper.addMapping(pattern);
++
++ // Update context mapper
++ mapper.addWrapper(pattern, wrapper, jspWildCard);
++
++ fireContainerEvent("addServletMapping", pattern);
++
++ }
++
++
++ /**
++ * Add a JSP tag library for the specified URI.
++ *
++ * @param uri URI, relative to the web.xml file, of this tag library
++ * @param location Location of the tag library descriptor
++ */
++ public void addTaglib(String uri, String location) {
++
++ synchronized (taglibs) {
++ taglibs.put(uri, location);
++ }
++ fireContainerEvent("addTaglib", uri);
++
++ }
++
++
++ /**
++ * Add a new watched resource to the set recognized by this Context.
++ *
++ * @param name New watched resource file name
++ */
++ public void addWatchedResource(String name) {
++
++ synchronized (watchedResources) {
++ String results[] = new String[watchedResources.length + 1];
++ for (int i = 0; i < watchedResources.length; i++)
++ results[i] = watchedResources[i];
++ results[watchedResources.length] = name;
++ watchedResources = results;
++ }
++ fireContainerEvent("addWatchedResource", name);
++
++ }
++
++
++ /**
++ * Add a new welcome file to the set recognized by this Context.
++ *
++ * @param name New welcome file name
++ */
++ public void addWelcomeFile(String name) {
++
++ synchronized (welcomeFiles) {
++ // Welcome files from the application deployment descriptor
++ // completely replace those from the default conf/web.xml file
++ if (replaceWelcomeFiles) {
++ welcomeFiles = new String[0];
++ setReplaceWelcomeFiles(false);
++ }
++ String results[] =new String[welcomeFiles.length + 1];
++ for (int i = 0; i < welcomeFiles.length; i++)
++ results[i] = welcomeFiles[i];
++ results[welcomeFiles.length] = name;
++ welcomeFiles = results;
++ }
++ postWelcomeFiles();
++ fireContainerEvent("addWelcomeFile", name);
++
++ }
++
++
++ /**
++ * Add the classname of a LifecycleListener to be added to each
++ * Wrapper appended to this Context.
++ *
++ * @param listener Java class name of a LifecycleListener class
++ */
++ public void addWrapperLifecycle(String listener) {
++
++ synchronized (wrapperLifecycles) {
++ String results[] =new String[wrapperLifecycles.length + 1];
++ for (int i = 0; i < wrapperLifecycles.length; i++)
++ results[i] = wrapperLifecycles[i];
++ results[wrapperLifecycles.length] = listener;
++ wrapperLifecycles = results;
++ }
++ fireContainerEvent("addWrapperLifecycle", listener);
++
++ }
++
++
++ /**
++ * Add the classname of a ContainerListener to be added to each
++ * Wrapper appended to this Context.
++ *
++ * @param listener Java class name of a ContainerListener class
++ */
++ public void addWrapperListener(String listener) {
++
++ synchronized (wrapperListeners) {
++ String results[] =new String[wrapperListeners.length + 1];
++ for (int i = 0; i < wrapperListeners.length; i++)
++ results[i] = wrapperListeners[i];
++ results[wrapperListeners.length] = listener;
++ wrapperListeners = results;
++ }
++ fireContainerEvent("addWrapperListener", listener);
++
++ }
++
++
++ /**
++ * Factory method to create and return a new Wrapper instance, of
++ * the Java implementation class appropriate for this Context
++ * implementation. The constructor of the instantiated Wrapper
++ * will have been called, but no properties will have been set.
++ */
++ public Wrapper createWrapper() {
++
++ Wrapper wrapper = null;
++ if (wrapperClass != null) {
++ try {
++ wrapper = (Wrapper) wrapperClass.newInstance();
++ } catch (Throwable t) {
++ log.error("createWrapper", t);
++ return (null);
++ }
++ } else {
++ wrapper = new StandardWrapper();
++ }
++
++ synchronized (instanceListeners) {
++ for (int i = 0; i < instanceListeners.length; i++) {
++ try {
++ Class clazz = Class.forName(instanceListeners[i]);
++ InstanceListener listener =
++ (InstanceListener) clazz.newInstance();
++ wrapper.addInstanceListener(listener);
++ } catch (Throwable t) {
++ log.error("createWrapper", t);
++ return (null);
++ }
++ }
++ }
++
++ synchronized (wrapperLifecycles) {
++ for (int i = 0; i < wrapperLifecycles.length; i++) {
++ try {
++ Class clazz = Class.forName(wrapperLifecycles[i]);
++ LifecycleListener listener =
++ (LifecycleListener) clazz.newInstance();
++ if (wrapper instanceof Lifecycle)
++ ((Lifecycle) wrapper).addLifecycleListener(listener);
++ } catch (Throwable t) {
++ log.error("createWrapper", t);
++ return (null);
++ }
++ }
++ }
++
++ synchronized (wrapperListeners) {
++ for (int i = 0; i < wrapperListeners.length; i++) {
++ try {
++ Class clazz = Class.forName(wrapperListeners[i]);
++ ContainerListener listener =
++ (ContainerListener) clazz.newInstance();
++ wrapper.addContainerListener(listener);
++ } catch (Throwable t) {
++ log.error("createWrapper", t);
++ return (null);
++ }
++ }
++ }
++
++ return (wrapper);
++
++ }
++
++
++ /**
++ * Return the set of application listener class names configured
++ * for this application.
++ */
++ public String[] findApplicationListeners() {
++
++ return (applicationListeners);
++
++ }
++
++
++ /**
++ * Return the set of application parameters for this application.
++ */
++ public ApplicationParameter[] findApplicationParameters() {
++
++ return (applicationParameters);
++
++ }
++
++
++ /**
++ * Return the security constraints for this web application.
++ * If there are none, a zero-length array is returned.
++ */
++ public SecurityConstraint[] findConstraints() {
++
++ return (constraints);
++
++ }
++
++
++ /**
++ * Return the error page entry for the specified HTTP error code,
++ * if any; otherwise return <code>null</code>.
++ *
++ * @param errorCode Error code to look up
++ */
++ public ErrorPage findErrorPage(int errorCode) {
++ if (errorCode == 200) {
++ return (okErrorPage);
++ } else {
++ return ((ErrorPage) statusPages.get(new Integer(errorCode)));
++ }
++
++ }
++
++
++ /**
++ * Return the error page entry for the specified Java exception type,
++ * if any; otherwise return <code>null</code>.
++ *
++ * @param exceptionType Exception type to look up
++ */
++ public ErrorPage findErrorPage(String exceptionType) {
++
++ synchronized (exceptionPages) {
++ return ((ErrorPage) exceptionPages.get(exceptionType));
++ }
++
++ }
++
++
++ /**
++ * Return the set of defined error pages for all specified error codes
++ * and exception types.
++ */
++ public ErrorPage[] findErrorPages() {
++
++ synchronized(exceptionPages) {
++ synchronized(statusPages) {
++ ErrorPage results1[] = new ErrorPage[exceptionPages.size()];
++ results1 =
++ (ErrorPage[]) exceptionPages.values().toArray(results1);
++ ErrorPage results2[] = new ErrorPage[statusPages.size()];
++ results2 =
++ (ErrorPage[]) statusPages.values().toArray(results2);
++ ErrorPage results[] =
++ new ErrorPage[results1.length + results2.length];
++ for (int i = 0; i < results1.length; i++)
++ results[i] = results1[i];
++ for (int i = results1.length; i < results.length; i++)
++ results[i] = results2[i - results1.length];
++ return (results);
++ }
++ }
++
++ }
++
++
++ /**
++ * Return the filter definition for the specified filter name, if any;
++ * otherwise return <code>null</code>.
++ *
++ * @param filterName Filter name to look up
++ */
++ public FilterDef findFilterDef(String filterName) {
++
++ synchronized (filterDefs) {
++ return ((FilterDef) filterDefs.get(filterName));
++ }
++
++ }
++
++
++ /**
++ * Return the set of defined filters for this Context.
++ */
++ public FilterDef[] findFilterDefs() {
++
++ synchronized (filterDefs) {
++ FilterDef results[] = new FilterDef[filterDefs.size()];
++ return ((FilterDef[]) filterDefs.values().toArray(results));
++ }
++
++ }
++
++
++ /**
++ * Return the set of filter mappings for this Context.
++ */
++ public FilterMap[] findFilterMaps() {
++
++ return (filterMaps);
++
++ }
++
++
++ /**
++ * Return the set of InstanceListener classes that will be added to
++ * newly created Wrappers automatically.
++ */
++ public String[] findInstanceListeners() {
++
++ return (instanceListeners);
++
++ }
++
++
++ /**
++ * FIXME: Fooling introspection ...
++ */
++ public Context findMappingObject() {
++ return (Context) getMappingObject();
++ }
++
++
++ /**
++ * Return the message destination with the specified name, if any;
++ * otherwise, return <code>null</code>.
++ *
++ * @param name Name of the desired message destination
++ */
++ public MessageDestination findMessageDestination(String name) {
++
++ synchronized (messageDestinations) {
++ return ((MessageDestination) messageDestinations.get(name));
++ }
++
++ }
++
++
++ /**
++ * Return the set of defined message destinations for this web
++ * application. If none have been defined, a zero-length array
++ * is returned.
++ */
++ public MessageDestination[] findMessageDestinations() {
++
++ synchronized (messageDestinations) {
++ MessageDestination results[] =
++ new MessageDestination[messageDestinations.size()];
++ return ((MessageDestination[])
++ messageDestinations.values().toArray(results));
++ }
++
++ }
++
++
++ /**
++ * Return the message destination ref with the specified name, if any;
++ * otherwise, return <code>null</code>.
++ *
++ * @param name Name of the desired message destination ref
++ */
++ public MessageDestinationRef
++ findMessageDestinationRef(String name) {
++
++ return namingResources.findMessageDestinationRef(name);
++
++ }
++
++
++ /**
++ * Return the set of defined message destination refs for this web
++ * application. If none have been defined, a zero-length array
++ * is returned.
++ */
++ public MessageDestinationRef[]
++ findMessageDestinationRefs() {
++
++ return namingResources.findMessageDestinationRefs();
++
++ }
++
++
++ /**
++ * Return the MIME type to which the specified extension is mapped,
++ * if any; otherwise return <code>null</code>.
++ *
++ * @param extension Extension to map to a MIME type
++ */
++ public String findMimeMapping(String extension) {
++
++ return ((String) mimeMappings.get(extension));
++
++ }
++
++
++ /**
++ * Return the extensions for which MIME mappings are defined. If there
++ * are none, a zero-length array is returned.
++ */
++ public String[] findMimeMappings() {
++
++ synchronized (mimeMappings) {
++ String results[] = new String[mimeMappings.size()];
++ return
++ ((String[]) mimeMappings.keySet().toArray(results));
++ }
++
++ }
++
++
++ /**
++ * Return the value for the specified context initialization
++ * parameter name, if any; otherwise return <code>null</code>.
++ *
++ * @param name Name of the parameter to return
++ */
++ public String findParameter(String name) {
++
++ synchronized (parameters) {
++ return ((String) parameters.get(name));
++ }
++
++ }
++
++
++ /**
++ * Return the names of all defined context initialization parameters
++ * for this Context. If no parameters are defined, a zero-length
++ * array is returned.
++ */
++ public String[] findParameters() {
++
++ synchronized (parameters) {
++ String results[] = new String[parameters.size()];
++ return ((String[]) parameters.keySet().toArray(results));
++ }
++
++ }
++
++
++ /**
++ * For the given security role (as used by an application), return the
++ * corresponding role name (as defined by the underlying Realm) if there
++ * is one. Otherwise, return the specified role unchanged.
++ *
++ * @param role Security role to map
++ */
++ public String findRoleMapping(String role) {
++
++ String realRole = null;
++ synchronized (roleMappings) {
++ realRole = (String) roleMappings.get(role);
++ }
++ if (realRole != null)
++ return (realRole);
++ else
++ return (role);
++
++ }
++
++
++ /**
++ * Return <code>true</code> if the specified security role is defined
++ * for this application; otherwise return <code>false</code>.
++ *
++ * @param role Security role to verify
++ */
++ public boolean findSecurityRole(String role) {
++
++ synchronized (securityRoles) {
++ for (int i = 0; i < securityRoles.length; i++) {
++ if (role.equals(securityRoles[i]))
++ return (true);
++ }
++ }
++ return (false);
++
++ }
++
++
++ /**
++ * Return the security roles defined for this application. If none
++ * have been defined, a zero-length array is returned.
++ */
++ public String[] findSecurityRoles() {
++
++ return (securityRoles);
++
++ }
++
++
++ /**
++ * Return the servlet name mapped by the specified pattern (if any);
++ * otherwise return <code>null</code>.
++ *
++ * @param pattern Pattern for which a mapping is requested
++ */
++ public String findServletMapping(String pattern) {
++
++ synchronized (servletMappings) {
++ return ((String) servletMappings.get(pattern));
++ }
++
++ }
++
++
++ /**
++ * Return the patterns of all defined servlet mappings for this
++ * Context. If no mappings are defined, a zero-length array is returned.
++ */
++ public String[] findServletMappings() {
++
++ synchronized (servletMappings) {
++ String results[] = new String[servletMappings.size()];
++ return
++ ((String[]) servletMappings.keySet().toArray(results));
++ }
++
++ }
++
++
++ /**
++ * Return the context-relative URI of the error page for the specified
++ * HTTP status code, if any; otherwise return <code>null</code>.
++ *
++ * @param status HTTP status code to look up
++ */
++ public String findStatusPage(int status) {
++
++ return ((String) statusPages.get(new Integer(status)));
++
++ }
++
++
++ /**
++ * Return the set of HTTP status codes for which error pages have
++ * been specified. If none are specified, a zero-length array
++ * is returned.
++ */
++ public int[] findStatusPages() {
++
++ synchronized (statusPages) {
++ int results[] = new int[statusPages.size()];
++ Iterator elements = statusPages.keySet().iterator();
++ int i = 0;
++ while (elements.hasNext())
++ results[i++] = ((Integer) elements.next()).intValue();
++ return (results);
++ }
++
++ }
++
++
++ /**
++ * Return the tag library descriptor location for the specified taglib
++ * URI, if any; otherwise, return <code>null</code>.
++ *
++ * @param uri URI, relative to the web.xml file
++ */
++ public String findTaglib(String uri) {
++
++ synchronized (taglibs) {
++ return ((String) taglibs.get(uri));
++ }
++
++ }
++
++
++ /**
++ * Return the URIs of all tag libraries for which a tag library
++ * descriptor location has been specified. If none are specified,
++ * a zero-length array is returned.
++ */
++ public String[] findTaglibs() {
++
++ synchronized (taglibs) {
++ String results[] = new String[taglibs.size()];
++ return ((String[]) taglibs.keySet().toArray(results));
++ }
++
++ }
++
++
++ /**
++ * Return <code>true</code> if the specified welcome file is defined
++ * for this Context; otherwise return <code>false</code>.
++ *
++ * @param name Welcome file to verify
++ */
++ public boolean findWelcomeFile(String name) {
++
++ synchronized (welcomeFiles) {
++ for (int i = 0; i < welcomeFiles.length; i++) {
++ if (name.equals(welcomeFiles[i]))
++ return (true);
++ }
++ }
++ return (false);
++
++ }
++
++
++ /**
++ * Return the set of watched resources for this Context. If none are
++ * defined, a zero length array will be returned.
++ */
++ public String[] findWatchedResources() {
++ return watchedResources;
++ }
++
++
++ /**
++ * Return the set of welcome files defined for this Context. If none are
++ * defined, a zero-length array is returned.
++ */
++ public String[] findWelcomeFiles() {
++
++ return (welcomeFiles);
++
++ }
++
++
++ /**
++ * Return the set of LifecycleListener classes that will be added to
++ * newly created Wrappers automatically.
++ */
++ public String[] findWrapperLifecycles() {
++
++ return (wrapperLifecycles);
++
++ }
++
++
++ /**
++ * Return the set of ContainerListener classes that will be added to
++ * newly created Wrappers automatically.
++ */
++ public String[] findWrapperListeners() {
++
++ return (wrapperListeners);
++
++ }
++
++
++ /**
++ * Reload this web application, if reloading is supported.
++ * <p>
++ * <b>IMPLEMENTATION NOTE</b>: This method is designed to deal with
++ * reloads required by changes to classes in the underlying repositories
++ * of our class loader. It does not handle changes to the web application
++ * deployment descriptor. If that has occurred, you should stop this
++ * Context and create (and start) a new Context instance instead.
++ *
++ * @exception IllegalStateException if the <code>reloadable</code>
++ * property is set to <code>false</code>.
++ */
++ public synchronized void reload() {
++
++ // Validate our current component state
++ if (!started)
++ throw new IllegalStateException
++ (sm.getString("containerBase.notStarted", logName()));
++
++ // Make sure reloading is enabled
++ // if (!reloadable)
++ // throw new IllegalStateException
++ // (sm.getString("standardContext.notReloadable"));
++ if(log.isInfoEnabled())
++ log.info(sm.getString("standardContext.reloadingStarted"));
++
++ // Stop accepting requests temporarily
++ setPaused(true);
++
++ try {
++ stop();
++ } catch (LifecycleException e) {
++ log.error(sm.getString("standardContext.stoppingContext"), e);
++ }
++
++ try {
++ start();
++ } catch (LifecycleException e) {
++ log.error(sm.getString("standardContext.startingContext"), e);
++ }
++
++ setPaused(false);
++
++ }
++
++
++ /**
++ * Remove the specified application listener class from the set of
++ * listeners for this application.
++ *
++ * @param listener Java class name of the listener to be removed
++ */
++ public void removeApplicationListener(String listener) {
++
++ synchronized (applicationListeners) {
++
++ // Make sure this welcome file is currently present
++ int n = -1;
++ for (int i = 0; i < applicationListeners.length; i++) {
++ if (applicationListeners[i].equals(listener)) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified constraint
++ int j = 0;
++ String results[] = new String[applicationListeners.length - 1];
++ for (int i = 0; i < applicationListeners.length; i++) {
++ if (i != n)
++ results[j++] = applicationListeners[i];
++ }
++ applicationListeners = results;
++
++ }
++
++ // Inform interested listeners
++ fireContainerEvent("removeApplicationListener", listener);
++
++ // FIXME - behavior if already started?
++
++ }
++
++
++ /**
++ * Remove the application parameter with the specified name from
++ * the set for this application.
++ *
++ * @param name Name of the application parameter to remove
++ */
++ public void removeApplicationParameter(String name) {
++
++ synchronized (applicationParameters) {
++
++ // Make sure this parameter is currently present
++ int n = -1;
++ for (int i = 0; i < applicationParameters.length; i++) {
++ if (name.equals(applicationParameters[i].getName())) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified parameter
++ int j = 0;
++ ApplicationParameter results[] =
++ new ApplicationParameter[applicationParameters.length - 1];
++ for (int i = 0; i < applicationParameters.length; i++) {
++ if (i != n)
++ results[j++] = applicationParameters[i];
++ }
++ applicationParameters = results;
++
++ }
++
++ // Inform interested listeners
++ fireContainerEvent("removeApplicationParameter", name);
++
++ }
++
++
++ /**
++ * Add a child Container, only if the proposed child is an implementation
++ * of Wrapper.
++ *
++ * @param child Child container to be added
++ *
++ * @exception IllegalArgumentException if the proposed container is
++ * not an implementation of Wrapper
++ */
++ public void removeChild(Container child) {
++
++ if (!(child instanceof Wrapper)) {
++ throw new IllegalArgumentException
++ (sm.getString("standardContext.notWrapper"));
++ }
++
++ super.removeChild(child);
++
++ }
++
++
++ /**
++ * Remove the specified security constraint from this web application.
++ *
++ * @param constraint Constraint to be removed
++ */
++ public void removeConstraint(SecurityConstraint constraint) {
++
++ synchronized (constraints) {
++
++ // Make sure this constraint is currently present
++ int n = -1;
++ for (int i = 0; i < constraints.length; i++) {
++ if (constraints[i].equals(constraint)) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified constraint
++ int j = 0;
++ SecurityConstraint results[] =
++ new SecurityConstraint[constraints.length - 1];
++ for (int i = 0; i < constraints.length; i++) {
++ if (i != n)
++ results[j++] = constraints[i];
++ }
++ constraints = results;
++
++ }
++
++ // Inform interested listeners
++ fireContainerEvent("removeConstraint", constraint);
++
++ }
++
++
++ /**
++ * Remove the error page for the specified error code or
++ * Java language exception, if it exists; otherwise, no action is taken.
++ *
++ * @param errorPage The error page definition to be removed
++ */
++ public void removeErrorPage(ErrorPage errorPage) {
++
++ String exceptionType = errorPage.getExceptionType();
++ if (exceptionType != null) {
++ synchronized (exceptionPages) {
++ exceptionPages.remove(exceptionType);
++ }
++ } else {
++ synchronized (statusPages) {
++ if (errorPage.getErrorCode() == 200) {
++ this.okErrorPage = null;
++ }
++ statusPages.remove(new Integer(errorPage.getErrorCode()));
++ }
++ }
++ fireContainerEvent("removeErrorPage", errorPage);
++
++ }
++
++
++ /**
++ * Remove the specified filter definition from this Context, if it exists;
++ * otherwise, no action is taken.
++ *
++ * @param filterDef Filter definition to be removed
++ */
++ public void removeFilterDef(FilterDef filterDef) {
++
++ synchronized (filterDefs) {
++ filterDefs.remove(filterDef.getFilterName());
++ }
++ fireContainerEvent("removeFilterDef", filterDef);
++
++ }
++
++
++ /**
++ * Remove a filter mapping from this Context.
++ *
++ * @param filterMap The filter mapping to be removed
++ */
++ public void removeFilterMap(FilterMap filterMap) {
++
++ synchronized (filterMaps) {
++
++ // Make sure this filter mapping is currently present
++ int n = -1;
++ for (int i = 0; i < filterMaps.length; i++) {
++ if (filterMaps[i] == filterMap) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified filter mapping
++ FilterMap results[] = new FilterMap[filterMaps.length - 1];
++ System.arraycopy(filterMaps, 0, results, 0, n);
++ System.arraycopy(filterMaps, n + 1, results, n,
++ (filterMaps.length - 1) - n);
++ filterMaps = results;
++
++ }
++
++ // Inform interested listeners
++ fireContainerEvent("removeFilterMap", filterMap);
++
++ }
++
++
++ /**
++ * Remove a class name from the set of InstanceListener classes that
++ * will be added to newly created Wrappers.
++ *
++ * @param listener Class name of an InstanceListener class to be removed
++ */
++ public void removeInstanceListener(String listener) {
++
++ synchronized (instanceListeners) {
++
++ // Make sure this welcome file is currently present
++ int n = -1;
++ for (int i = 0; i < instanceListeners.length; i++) {
++ if (instanceListeners[i].equals(listener)) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified constraint
++ int j = 0;
++ String results[] = new String[instanceListeners.length - 1];
++ for (int i = 0; i < instanceListeners.length; i++) {
++ if (i != n)
++ results[j++] = instanceListeners[i];
++ }
++ instanceListeners = results;
++
++ }
++
++ // Inform interested listeners
++ fireContainerEvent("removeInstanceListener", listener);
++
++ }
++
++
++ /**
++ * Remove any message destination with the specified name.
++ *
++ * @param name Name of the message destination to remove
++ */
++ public void removeMessageDestination(String name) {
++
++ synchronized (messageDestinations) {
++ messageDestinations.remove(name);
++ }
++ fireContainerEvent("removeMessageDestination", name);
++
++ }
++
++
++ /**
++ * Remove any message destination ref with the specified name.
++ *
++ * @param name Name of the message destination ref to remove
++ */
++ public void removeMessageDestinationRef(String name) {
++
++ namingResources.removeMessageDestinationRef(name);
++ fireContainerEvent("removeMessageDestinationRef", name);
++
++ }
++
++
++ /**
++ * Remove the MIME mapping for the specified extension, if it exists;
++ * otherwise, no action is taken.
++ *
++ * @param extension Extension to remove the mapping for
++ */
++ public void removeMimeMapping(String extension) {
++
++ synchronized (mimeMappings) {
++ mimeMappings.remove(extension);
++ }
++ fireContainerEvent("removeMimeMapping", extension);
++
++ }
++
++
++ /**
++ * Remove the context initialization parameter with the specified
++ * name, if it exists; otherwise, no action is taken.
++ *
++ * @param name Name of the parameter to remove
++ */
++ public void removeParameter(String name) {
++
++ synchronized (parameters) {
++ parameters.remove(name);
++ }
++ fireContainerEvent("removeParameter", name);
++
++ }
++
++
++ /**
++ * Remove any security role reference for the specified name
++ *
++ * @param role Security role (as used in the application) to remove
++ */
++ public void removeRoleMapping(String role) {
++
++ synchronized (roleMappings) {
++ roleMappings.remove(role);
++ }
++ fireContainerEvent("removeRoleMapping", role);
++
++ }
++
++
++ /**
++ * Remove any security role with the specified name.
++ *
++ * @param role Security role to remove
++ */
++ public void removeSecurityRole(String role) {
++
++ synchronized (securityRoles) {
++
++ // Make sure this security role is currently present
++ int n = -1;
++ for (int i = 0; i < securityRoles.length; i++) {
++ if (role.equals(securityRoles[i])) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified security role
++ int j = 0;
++ String results[] = new String[securityRoles.length - 1];
++ for (int i = 0; i < securityRoles.length; i++) {
++ if (i != n)
++ results[j++] = securityRoles[i];
++ }
++ securityRoles = results;
++
++ }
++
++ // Inform interested listeners
++ fireContainerEvent("removeSecurityRole", role);
++
++ }
++
++
++ /**
++ * Remove any servlet mapping for the specified pattern, if it exists;
++ * otherwise, no action is taken.
++ *
++ * @param pattern URL pattern of the mapping to remove
++ */
++ public void removeServletMapping(String pattern) {
++
++ String name = null;
++ synchronized (servletMappings) {
++ name = (String) servletMappings.remove(pattern);
++ }
++ Wrapper wrapper = (Wrapper) findChild(name);
++ if( wrapper != null ) {
++ wrapper.removeMapping(pattern);
++ }
++ mapper.removeWrapper(pattern);
++ fireContainerEvent("removeServletMapping", pattern);
++
++ }
++
++
++ /**
++ * Remove the tag library location forthe specified tag library URI.
++ *
++ * @param uri URI, relative to the web.xml file
++ */
++ public void removeTaglib(String uri) {
++
++ synchronized (taglibs) {
++ taglibs.remove(uri);
++ }
++ fireContainerEvent("removeTaglib", uri);
++ }
++
++
++ /**
++ * Remove the specified watched resource name from the list associated
++ * with this Context.
++ *
++ * @param name Name of the watched resource to be removed
++ */
++ public void removeWatchedResource(String name) {
++
++ synchronized (watchedResources) {
++
++ // Make sure this watched resource is currently present
++ int n = -1;
++ for (int i = 0; i < watchedResources.length; i++) {
++ if (watchedResources[i].equals(name)) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified watched resource
++ int j = 0;
++ String results[] = new String[watchedResources.length - 1];
++ for (int i = 0; i < watchedResources.length; i++) {
++ if (i != n)
++ results[j++] = watchedResources[i];
++ }
++ watchedResources = results;
++
++ }
++
++ fireContainerEvent("removeWatchedResource", name);
++
++ }
++
++
++ /**
++ * Remove the specified welcome file name from the list recognized
++ * by this Context.
++ *
++ * @param name Name of the welcome file to be removed
++ */
++ public void removeWelcomeFile(String name) {
++
++ synchronized (welcomeFiles) {
++
++ // Make sure this welcome file is currently present
++ int n = -1;
++ for (int i = 0; i < welcomeFiles.length; i++) {
++ if (welcomeFiles[i].equals(name)) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified constraint
++ int j = 0;
++ String results[] = new String[welcomeFiles.length - 1];
++ for (int i = 0; i < welcomeFiles.length; i++) {
++ if (i != n)
++ results[j++] = welcomeFiles[i];
++ }
++ welcomeFiles = results;
++
++ }
++
++ // Inform interested listeners
++ postWelcomeFiles();
++ fireContainerEvent("removeWelcomeFile", name);
++
++ }
++
++
++ /**
++ * Remove a class name from the set of LifecycleListener classes that
++ * will be added to newly created Wrappers.
++ *
++ * @param listener Class name of a LifecycleListener class to be removed
++ */
++ public void removeWrapperLifecycle(String listener) {
++
++
++ synchronized (wrapperLifecycles) {
++
++ // Make sure this welcome file is currently present
++ int n = -1;
++ for (int i = 0; i < wrapperLifecycles.length; i++) {
++ if (wrapperLifecycles[i].equals(listener)) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified constraint
++ int j = 0;
++ String results[] = new String[wrapperLifecycles.length - 1];
++ for (int i = 0; i < wrapperLifecycles.length; i++) {
++ if (i != n)
++ results[j++] = wrapperLifecycles[i];
++ }
++ wrapperLifecycles = results;
++
++ }
++
++ // Inform interested listeners
++ fireContainerEvent("removeWrapperLifecycle", listener);
++
++ }
++
++
++ /**
++ * Remove a class name from the set of ContainerListener classes that
++ * will be added to newly created Wrappers.
++ *
++ * @param listener Class name of a ContainerListener class to be removed
++ */
++ public void removeWrapperListener(String listener) {
++
++
++ synchronized (wrapperListeners) {
++
++ // Make sure this welcome file is currently present
++ int n = -1;
++ for (int i = 0; i < wrapperListeners.length; i++) {
++ if (wrapperListeners[i].equals(listener)) {
++ n = i;
++ break;
++ }
++ }
++ if (n < 0)
++ return;
++
++ // Remove the specified constraint
++ int j = 0;
++ String results[] = new String[wrapperListeners.length - 1];
++ for (int i = 0; i < wrapperListeners.length; i++) {
++ if (i != n)
++ results[j++] = wrapperListeners[i];
++ }
++ wrapperListeners = results;
++
++ }
++
++ // Inform interested listeners
++ fireContainerEvent("removeWrapperListener", listener);
++
++ }
++
++
++ /**
++ * Gets the cumulative processing times of all servlets in this
++ * StandardContext.
++ *
++ * @return Cumulative processing times of all servlets in this
++ * StandardContext
++ */
++ public long getProcessingTime() {
++
++ long result = 0;
++
++ Container[] children = findChildren();
++ if (children != null) {
++ for( int i=0; i< children.length; i++ ) {
++ result += ((StandardWrapper)children[i]).getProcessingTime();
++ }
++ }
++
++ return result;
++ }
++
++
++ // --------------------------------------------------------- Public Methods
++
++
++ /**
++ * Configure and initialize the set of filters for this Context.
++ * Return <code>true</code> if all filter initialization completed
++ * successfully, or <code>false</code> otherwise.
++ */
++ public boolean filterStart() {
++
++ if (getLogger().isDebugEnabled())
++ getLogger().debug("Starting filters");
++ // Instantiate and record a FilterConfig for each defined filter
++ boolean ok = true;
++ synchronized (filterConfigs) {
++ filterConfigs.clear();
++ Iterator names = filterDefs.keySet().iterator();
++ while (names.hasNext()) {
++ String name = (String) names.next();
++ if (getLogger().isDebugEnabled())
++ getLogger().debug(" Starting filter '" + name + "'");
++ ApplicationFilterConfig filterConfig = null;
++ try {
++ filterConfig = new ApplicationFilterConfig
++ (this, (FilterDef) filterDefs.get(name));
++ filterConfigs.put(name, filterConfig);
++ } catch (Throwable t) {
++ getLogger().error
++ (sm.getString("standardContext.filterStart", name), t);
++ ok = false;
++ }
++ }
++ }
++
++ return (ok);
++
++ }
++
++
++ /**
++ * Finalize and release the set of filters for this Context.
++ * Return <code>true</code> if all filter finalization completed
++ * successfully, or <code>false</code> otherwise.
++ */
++ public boolean filterStop() {
++
++ if (getLogger().isDebugEnabled())
++ getLogger().debug("Stopping filters");
++
++ // Release all Filter and FilterConfig instances
++ synchronized (filterConfigs) {
++ Iterator names = filterConfigs.keySet().iterator();
++ while (names.hasNext()) {
++ String name = (String) names.next();
++ if (getLogger().isDebugEnabled())
++ getLogger().debug(" Stopping filter '" + name + "'");
++ ApplicationFilterConfig filterConfig =
++ (ApplicationFilterConfig) filterConfigs.get(name);
++ filterConfig.release();
++ }
++ filterConfigs.clear();
++ }
++ return (true);
++
++ }
++
++
++ /**
++ * Find and return the initialized <code>FilterConfig</code> for the
++ * specified filter name, if any; otherwise return <code>null</code>.
++ *
++ * @param name Name of the desired filter
++ */
++ public FilterConfig findFilterConfig(String name) {
++
++ return ((FilterConfig) filterConfigs.get(name));
++
++ }
++
++
++ /**
++ * Configure the set of instantiated application event listeners
++ * for this Context. Return <code>true</code> if all listeners wre
++ * initialized successfully, or <code>false</code> otherwise.
++ */
++ public boolean listenerStart() {
++
++ if (log.isDebugEnabled())
++ log.debug("Configuring application event listeners");
++
++ // Instantiate the required listeners
++ ClassLoader loader = getLoader().getClassLoader();
++ String listeners[] = findApplicationListeners();
++ Object results[] = new Object[listeners.length];
++ boolean ok = true;
++ for (int i = 0; i < results.length; i++) {
++ if (getLogger().isDebugEnabled())
++ getLogger().debug(" Configuring event listener class '" +
++ listeners[i] + "'");
++ try {
++ Class clazz = loader.loadClass(listeners[i]);
++ results[i] = clazz.newInstance();
++ } catch (Throwable t) {
++ getLogger().error
++ (sm.getString("standardContext.applicationListener",
++ listeners[i]), t);
++ ok = false;
++ }
++ }
++ if (!ok) {
++ getLogger().error(sm.getString("standardContext.applicationSkipped"));
++ return (false);
++ }
++
++ // Sort listeners in two arrays
++ ArrayList eventListeners = new ArrayList();
++ ArrayList lifecycleListeners = new ArrayList();
++ for (int i = 0; i < results.length; i++) {
++ if ((results[i] instanceof ServletContextAttributeListener)
++ || (results[i] instanceof ServletRequestAttributeListener)
++ || (results[i] instanceof ServletRequestListener)
++ || (results[i] instanceof HttpSessionAttributeListener)) {
++ eventListeners.add(results[i]);
++ }
++ if ((results[i] instanceof ServletContextListener)
++ || (results[i] instanceof HttpSessionListener)) {
++ lifecycleListeners.add(results[i]);
++ }
++ }
++
++ setApplicationEventListeners(eventListeners.toArray());
++ setApplicationLifecycleListeners(lifecycleListeners.toArray());
++
++ // Send application start events
++
++ if (getLogger().isDebugEnabled())
++ getLogger().debug("Sending application start events");
++
++ Object instances[] = getApplicationLifecycleListeners();
++ if (instances == null)
++ return (ok);
++ ServletContextEvent event =
++ new ServletContextEvent(getServletContext());
++ for (int i = 0; i < instances.length; i++) {
++ if (instances[i] == null)
++ continue;
++ if (!(instances[i] instanceof ServletContextListener))
++ continue;
++ ServletContextListener listener =
++ (ServletContextListener) instances[i];
++ try {
++ fireContainerEvent("beforeContextInitialized", listener);
++ listener.contextInitialized(event);
++ fireContainerEvent("afterContextInitialized", listener);
++ } catch (Throwable t) {
++ fireContainerEvent("afterContextInitialized", listener);
++ getLogger().error
++ (sm.getString("standardContext.listenerStart",
++ instances[i].getClass().getName()), t);
++ ok = false;
++ }
++ }
++ return (ok);
++
++ }
++
++
++ /**
++ * Send an application stop event to all interested listeners.
++ * Return <code>true</code> if all events were sent successfully,
++ * or <code>false</code> otherwise.
++ */
++ public boolean listenerStop() {
++
++ if (log.isDebugEnabled())
++ log.debug("Sending application stop events");
++
++ boolean ok = true;
++ Object listeners[] = getApplicationLifecycleListeners();
++ if (listeners == null)
++ return (ok);
++ ServletContextEvent event =
++ new ServletContextEvent(getServletContext());
++ for (int i = 0; i < listeners.length; i++) {
++ int j = (listeners.length - 1) - i;
++ if (listeners[j] == null)
++ continue;
++ if (!(listeners[j] instanceof ServletContextListener))
++ continue;
++ ServletContextListener listener =
++ (ServletContextListener) listeners[j];
++ try {
++ fireContainerEvent("beforeContextDestroyed", listener);
++ listener.contextDestroyed(event);
++ fireContainerEvent("afterContextDestroyed", listener);
++ } catch (Throwable t) {
++ fireContainerEvent("afterContextDestroyed", listener);
++ getLogger().error
++ (sm.getString("standardContext.listenerStop",
++ listeners[j].getClass().getName()), t);
++ ok = false;
++ }
++ }
++
++ setApplicationEventListeners(null);
++ setApplicationLifecycleListeners(null);
++
++ return (ok);
++
++ }
++
++
++ /**
++ * Allocate resources, including proxy.
++ * Return <code>true</code> if initialization was successfull,
++ * or <code>false</code> otherwise.
++ */
++ public boolean resourcesStart() {
++
++ boolean ok = true;
++
++ Hashtable env = new Hashtable();
++ if (getParent() != null)
++ env.put(ProxyDirContext.HOST, getParent().getName());
++ env.put(ProxyDirContext.CONTEXT, getName());
++
++ try {
++ ProxyDirContext proxyDirContext =
++ new ProxyDirContext(env, webappResources);
++ if (webappResources instanceof FileDirContext) {
++ filesystemBased = true;
++ ((FileDirContext) webappResources).setCaseSensitive
++ (isCaseSensitive());
++ ((FileDirContext) webappResources).setAllowLinking
++ (isAllowLinking());
++ }
++ if (webappResources instanceof BaseDirContext) {
++ ((BaseDirContext) webappResources).setDocBase(getBasePath());
++ ((BaseDirContext) webappResources).setCached
++ (isCachingAllowed());
++ ((BaseDirContext) webappResources).setCacheTTL(getCacheTTL());
++ ((BaseDirContext) webappResources).setCacheMaxSize
++ (getCacheMaxSize());
++ ((BaseDirContext) webappResources).allocate();
++ }
++ // Register the cache in JMX
++ if (isCachingAllowed()) {
++ ObjectName resourcesName =
++ new ObjectName(this.getDomain() + ":type=Cache,host="
++ + getHostname() + ",path="
++ + (("".equals(getPath()))?"/":getPath()));
++ Registry.getRegistry(null, null).registerComponent
++ (proxyDirContext.getCache(), resourcesName, null);
++ }
++ this.resources = proxyDirContext;
++ } catch (Throwable t) {
++ log.error(sm.getString("standardContext.resourcesStart"), t);
++ ok = false;
++ }
++
++ return (ok);
++
++ }
++
++
++ /**
++ * Deallocate resources and destroy proxy.
++ */
++ public boolean resourcesStop() {
++
++ boolean ok = true;
++
++ try {
++ if (resources != null) {
++ if (resources instanceof Lifecycle) {
++ ((Lifecycle) resources).stop();
++ }
++ if (webappResources instanceof BaseDirContext) {
++ ((BaseDirContext) webappResources).release();
++ }
++ // Unregister the cache in JMX
++ if (isCachingAllowed()) {
++ ObjectName resourcesName =
++ new ObjectName(this.getDomain()
++ + ":type=Cache,host="
++ + getHostname() + ",path="
++ + (("".equals(getPath()))?"/"
++ :getPath()));
++ Registry.getRegistry(null, null)
++ .unregisterComponent(resourcesName);
++ }
++ }
++ } catch (Throwable t) {
++ log.error(sm.getString("standardContext.resourcesStop"), t);
++ ok = false;
++ }
++
++ this.resources = null;
++
++ return (ok);
++
++ }
++
++
++ /**
++ * Load and initialize all servlets marked "load on startup" in the
++ * web application deployment descriptor.
++ *
++ * @param children Array of wrappers for all currently defined
++ * servlets (including those not declared load on startup)
++ */
++ public void loadOnStartup(Container children[]) {
++
++ // Collect "load on startup" servlets that need to be initialized
++ TreeMap map = new TreeMap();
++ for (int i = 0; i < children.length; i++) {
++ Wrapper wrapper = (Wrapper) children[i];
++ int loadOnStartup = wrapper.getLoadOnStartup();
++ if (loadOnStartup < 0)
++ continue;
++ if (loadOnStartup == 0) // Arbitrarily put them last
++ loadOnStartup = Integer.MAX_VALUE;
++ Integer key = new Integer(loadOnStartup);
++ ArrayList list = (ArrayList) map.get(key);
++ if (list == null) {
++ list = new ArrayList();
++ map.put(key, list);
++ }
++ list.add(wrapper);
++ }
++
++ // Load the collected "load on startup" servlets
++ Iterator keys = map.keySet().iterator();
++ while (keys.hasNext()) {
++ Integer key = (Integer) keys.next();
++ ArrayList list = (ArrayList) map.get(key);
++ Iterator wrappers = list.iterator();
++ while (wrappers.hasNext()) {
++ Wrapper wrapper = (Wrapper) wrappers.next();
++ try {
++ wrapper.load();
++ } catch (ServletException e) {
++ getLogger().error(sm.getString("standardWrapper.loadException",
++ getName()), StandardWrapper.getRootCause(e));
++ // NOTE: load errors (including a servlet that throws
++ // UnavailableException from tht init() method) are NOT
++ // fatal to application startup
++ }
++ }
++ }
++
++ }
++
++
++ /**
++ * Start this Context component.
++ *
++ * @exception LifecycleException if a startup error occurs
++ */
++ public synchronized void start() throws LifecycleException {
++ //if (lazy ) return;
++ if (started) {
++ if(log.isInfoEnabled())
++ log.info(sm.getString("containerBase.alreadyStarted", logName()));
++ return;
++ }
++ if( !initialized ) {
++ try {
++ init();
++ } catch( Exception ex ) {
++ throw new LifecycleException("Error initializaing ", ex);
++ }
++ }
++ if(log.isDebugEnabled())
++ log.debug("Starting " + ("".equals(getName()) ? "ROOT" : getName()));
++
++ // Set JMX object name for proper pipeline registration
++ preRegisterJMX();
++
++ if ((oname != null) &&
++ (Registry.getRegistry(null, null).getMBeanServer().isRegistered(oname))) {
++ // As things depend on the JMX registration, the context
++ // must be reregistered again once properly initialized
++ Registry.getRegistry(null, null).unregisterComponent(oname);
++ }
++
++ // Notify our interested LifecycleListeners
++ lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
++
++ setAvailable(false);
++ setConfigured(false);
++ boolean ok = true;
++
++ // Add missing components as necessary
++ if (webappResources == null) { // (1) Required by Loader
++ if (log.isDebugEnabled())
++ log.debug("Configuring default Resources");
++ try {
++ if ((docBase != null) && (docBase.endsWith(".war")) && (!(new File(getBasePath())).isDirectory()))
++ setResources(new WARDirContext());
++ else
++ setResources(new FileDirContext());
++ } catch (IllegalArgumentException e) {
++ log.error("Error initializing resources: " + e.getMessage());
++ ok = false;
++ }
++ }
++ if (ok) {
++ if (!resourcesStart()) {
++ log.error( "Error in resourceStart()");
++ ok = false;
++ }
++ }
++
++ // Look for a realm - that may have been configured earlier.
++ // If the realm is added after context - it'll set itself.
++ if( realm == null && mserver != null ) {
++ ObjectName realmName=null;
++ try {
++ realmName=new ObjectName( getEngineName() + ":type=Realm,host=" +
++ getHostname() + ",path=" + getPath());
++ if( mserver.isRegistered(realmName ) ) {
++ mserver.invoke(realmName, "init",
++ new Object[] {},
++ new String[] {}
++ );
++ }
++ } catch( Throwable t ) {
++ if(log.isDebugEnabled())
++ log.debug("No realm for this host " + realmName);
++ }
++ }
++
++ if (getLoader() == null) {
++ ClassLoader parent = null;
++ if (getPrivileged()) {
++ if (log.isDebugEnabled())
++ log.debug("Configuring privileged default Loader");
++ parent = this.getClass().getClassLoader();
++ } else {
++ if (log.isDebugEnabled())
++ log.debug("Configuring non-privileged default Loader");
++ parent = getParentClassLoader();
++ }
++ WebappLoader webappLoader = new WebappLoader(parent);
++ webappLoader.setDelegate(getDelegate());
++ setLoader(webappLoader);
++ }
++
++ // Initialize character set mapper
++ getCharsetMapper();
++
++ // Post work directory
++ postWorkDirectory();
++
++ // Validate required extensions
++ boolean dependencyCheck = true;
++ try {
++ dependencyCheck = ExtensionValidator.validateApplication
++ (getResources(), this);
++ } catch (IOException ioe) {
++ log.error("Error in dependencyCheck", ioe);
++ dependencyCheck = false;
++ }
++
++ if (!dependencyCheck) {
++ // do not make application available if depency check fails
++ ok = false;
++ }
++
++ // Reading the "catalina.useNaming" environment variable
++ String useNamingProperty = System.getProperty("catalina.useNaming");
++ if ((useNamingProperty != null)
++ && (useNamingProperty.equals("false"))) {
++ useNaming = false;
++ }
++
++ if (ok && isUseNaming()) {
++ if (namingContextListener == null) {
++ namingContextListener = new NamingContextListener();
++ namingContextListener.setName(getNamingContextName());
++ addLifecycleListener(namingContextListener);
++ }
++ }
++
++ // Binding thread
++ ClassLoader oldCCL = bindThread();
++
++ // Standard container startup
++ if (log.isDebugEnabled())
++ log.debug("Processing standard container startup");
++
++ if (ok) {
++
++ boolean mainOk = false;
++ try {
++
++ started = true;
++
++ // Start our subordinate components, if any
++ if ((loader != null) && (loader instanceof Lifecycle))
++ ((Lifecycle) loader).start();
++
++ // Unbinding thread
++ unbindThread(oldCCL);
++
++ // Binding thread
++ oldCCL = bindThread();
++
++ if ((logger != null) && (logger instanceof Lifecycle))
++ ((Lifecycle) logger).start();
++ if ((cluster != null) && (cluster instanceof Lifecycle))
++ ((Lifecycle) cluster).start();
++ if ((realm != null) && (realm instanceof Lifecycle))
++ ((Lifecycle) realm).start();
++ if ((resources != null) && (resources instanceof Lifecycle))
++ ((Lifecycle) resources).start();
++
++ // Start our child containers, if any
++ Container children[] = findChildren();
++ for (int i = 0; i < children.length; i++) {
++ if (children[i] instanceof Lifecycle)
++ ((Lifecycle) children[i]).start();
++ }
++
++ // Start the Valves in our pipeline (including the basic),
++ // if any
++ if (pipeline instanceof Lifecycle) {
++ ((Lifecycle) pipeline).start();
++ }
++
++ if(getProcessTlds()) {
++ processTlds();
++ }
++
++ // Notify our interested LifecycleListeners
++ lifecycle.fireLifecycleEvent(START_EVENT, null);
++
++ // Start manager
++ if ((manager != null) && (manager instanceof Lifecycle)) {
++ ((Lifecycle) getManager()).start();
++ }
++
++ // Start ContainerBackgroundProcessor thread
++ super.threadStart();
++
++ mainOk = true;
++
++ } finally {
++ // Unbinding thread
++ unbindThread(oldCCL);
++ if (!mainOk) {
++ // An exception occurred
++ // Register with JMX anyway, to allow management
++ registerJMX();
++ }
++ }
++
++ }
++ if (!getConfigured()) {
++ log.error( "Error getConfigured");
++ ok = false;
++ }
++
++ // We put the resources into the servlet context
++ if (ok)
++ getServletContext().setAttribute
++ (Globals.RESOURCES_ATTR, getResources());
++
++ // Initialize associated mapper
++ mapper.setContext(getPath(), welcomeFiles, resources);
++
++ // Binding thread
++ oldCCL = bindThread();
++
++ // Create context attributes that will be required
++ if (ok) {
++ postWelcomeFiles();
++ }
++
++ if (ok) {
++ // Notify our interested LifecycleListeners
++ lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
++ }
++
++ // Configure and call application event listeners and filters
++ if (ok) {
++ if (!listenerStart()) {
++ log.error( "Error listenerStart");
++ ok = false;
++ }
++ }
++ if (ok) {
++ if (!filterStart()) {
++ log.error( "Error filterStart");
++ ok = false;
++ }
++ }
++
++ // Load and initialize all "load on startup" servlets
++ if (ok) {
++ loadOnStartup(findChildren());
++ }
++
++ // Unbinding thread
++ unbindThread(oldCCL);
++
++ // Set available status depending upon startup success
++ if (ok) {
++ if (log.isDebugEnabled())
++ log.debug("Starting completed");
++ setAvailable(true);
++ } else {
++ log.error(sm.getString("standardContext.startFailed", getName()));
++ try {
++ stop();
++ } catch (Throwable t) {
++ log.error(sm.getString("standardContext.startCleanup"), t);
++ }
++ setAvailable(false);
++ }
++
++ // JMX registration
++ registerJMX();
++
++ startTime=System.currentTimeMillis();
++
++ // Send j2ee.state.running notification
++ if (ok && (this.getObjectName() != null)) {
++ Notification notification =
++ new Notification("j2ee.state.running", this.getObjectName(),
++ sequenceNumber++);
++ broadcaster.sendNotification(notification);
++ }
++
++ // Close all JARs right away to avoid always opening a peak number
++ // of files on startup
++ if (getLoader() instanceof WebappLoader) {
++ ((WebappLoader) getLoader()).closeJARs(true);
++ }
++
++ // Reinitializing if something went wrong
++ if (!ok && started) {
++ stop();
++ }
++
++ //cacheContext();
++ }
++
++ /**
++ * Processes TLDs.
++ *
++ * @throws LifecycleException If an error occurs
++ */
++ protected void processTlds() throws LifecycleException {
++ TldConfig tldConfig = new TldConfig();
++ tldConfig.setContext(this);
++
++ // (1) check if the attribute has been defined
++ // on the context element.
++ tldConfig.setTldValidation(tldValidation);
++ tldConfig.setTldNamespaceAware(tldNamespaceAware);
++
++ // (2) if the attribute wasn't defined on the context
++ // try the host.
++ if (!tldValidation) {
++ tldConfig.setTldValidation
++ (((StandardHost) getParent()).getXmlValidation());
++ }
++
++ if (!tldNamespaceAware) {
++ tldConfig.setTldNamespaceAware
++ (((StandardHost) getParent()).getXmlNamespaceAware());
++ }
++
++ try {
++ tldConfig.execute();
++ } catch (Exception ex) {
++ log.error("Error reading tld listeners "
++ + ex.toString(), ex);
++ }
++ }
++
++ private void cacheContext() {
++ try {
++ File workDir=new File( getWorkPath() );
++
++ File ctxSer=new File( workDir, "_tomcat_context.ser");
++ FileOutputStream fos=new FileOutputStream( ctxSer );
++ ObjectOutputStream oos=new ObjectOutputStream( fos );
++ oos.writeObject(this);
++ oos.close();
++ fos.close();
++ } catch( Throwable t ) {
++ if(log.isInfoEnabled())
++ log.info("Error saving context.ser ", t);
++ }
++ }
++
++
++ /**
++ * Stop this Context component.
++ *
++ * @exception LifecycleException if a shutdown error occurs
++ */
++ public synchronized void stop() throws LifecycleException {
++
++ // Validate and update our current component state
++ if (!started) {
++ if(log.isInfoEnabled())
++ log.info(sm.getString("containerBase.notStarted", logName()));
++ return;
++ }
++
++ // Notify our interested LifecycleListeners
++ lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
++
++ // Send j2ee.state.stopping notification
++ if (this.getObjectName() != null) {
++ Notification notification =
++ new Notification("j2ee.state.stopping", this.getObjectName(),
++ sequenceNumber++);
++ broadcaster.sendNotification(notification);
++ }
++
++ // Mark this application as unavailable while we shut down
++ setAvailable(false);
++
++ // Binding thread
++ ClassLoader oldCCL = bindThread();
++
++ // Stop our filters
++ filterStop();
++
++ // Stop ContainerBackgroundProcessor thread
++ super.threadStop();
++
++ if ((manager != null) && (manager instanceof Lifecycle)) {
++ ((Lifecycle) manager).stop();
++ }
++
++ // Finalize our character set mapper
++ setCharsetMapper(null);
++
++ // Normal container shutdown processing
++ if (log.isDebugEnabled())
++ log.debug("Processing standard container shutdown");
++ // Notify our interested LifecycleListeners
++ lifecycle.fireLifecycleEvent(STOP_EVENT, null);
++ started = false;
++
++ try {
++
++ // Stop the Valves in our pipeline (including the basic), if any
++ if (pipeline instanceof Lifecycle) {
++ ((Lifecycle) pipeline).stop();
++ }
++
++ // Stop our child containers, if any
++ Container[] children = findChildren();
++ for (int i = 0; i < children.length; i++) {
++ if (children[i] instanceof Lifecycle)
++ ((Lifecycle) children[i]).stop();
++ }
++
++ // Stop our application listeners
++ listenerStop();
++
++ // Clear all application-originated servlet context attributes
++ if (context != null)
++ context.clearAttributes();
++
++ // Stop resources
++ resourcesStop();
++
++ if ((realm != null) && (realm instanceof Lifecycle)) {
++ ((Lifecycle) realm).stop();
++ }
++ if ((cluster != null) && (cluster instanceof Lifecycle)) {
++ ((Lifecycle) cluster).stop();
++ }
++ if ((logger != null) && (logger instanceof Lifecycle)) {
++ ((Lifecycle) logger).stop();
++ }
++ if ((loader != null) && (loader instanceof Lifecycle)) {
++ ((Lifecycle) loader).stop();
++ }
++
++ } finally {
++
++ // Unbinding thread
++ unbindThread(oldCCL);
++
++ }
++
++ // Send j2ee.state.stopped notification
++ if (this.getObjectName() != null) {
++ Notification notification =
++ new Notification("j2ee.state.stopped", this.getObjectName(),
++ sequenceNumber++);
++ broadcaster.sendNotification(notification);
++ }
++
++ // Reset application context
++ context = null;
++
++ // This object will no longer be visible or used.
++ try {
++ resetContext();
++ } catch( Exception ex ) {
++ log.error( "Error reseting context " + this + " " + ex, ex );
++ }
++
++ // Notify our interested LifecycleListeners
++ lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
++
++ if (log.isDebugEnabled())
++ log.debug("Stopping complete");
++
++ }
++
++ /** Destroy needs to clean up the context completely.
++ *
++ * The problem is that undoing all the config in start() and restoring
++ * a 'fresh' state is impossible. After stop()/destroy()/init()/start()
++ * we should have the same state as if a fresh start was done - i.e
++ * read modified web.xml, etc. This can only be done by completely
++ * removing the context object and remapping a new one, or by cleaning
++ * up everything.
++ *
++ * XXX Should this be done in stop() ?
++ *
++ */
++ public void destroy() throws Exception {
++ if( oname != null ) {
++ // Send j2ee.object.deleted notification
++ Notification notification =
++ new Notification("j2ee.object.deleted", this.getObjectName(),
++ sequenceNumber++);
++ broadcaster.sendNotification(notification);
++ }
++ super.destroy();
++
++ // Notify our interested LifecycleListeners
++ lifecycle.fireLifecycleEvent(DESTROY_EVENT, null);
++
++ instanceListeners = new String[0];
++ applicationListeners = new String[0];
++ }
++
++ private void resetContext() throws Exception, MBeanRegistrationException {
++ // Restore the original state ( pre reading web.xml in start )
++ // If you extend this - override this method and make sure to clean up
++ children=new HashMap();
++ startupTime = 0;
++ startTime = 0;
++ tldScanTime = 0;
++
++ // Bugzilla 32867
++ distributable = false;
++
++ if(log.isDebugEnabled())
++ log.debug("resetContext " + oname + " " + mserver);
++ }
++
++ /**
++ * Return a String representation of this component.
++ */
++ public String toString() {
++
++ StringBuffer sb = new StringBuffer();
++ if (getParent() != null) {
++ sb.append(getParent().toString());
++ sb.append(".");
++ }
++ sb.append("StandardContext[");
++ sb.append(getName());
++ sb.append("]");
++ return (sb.toString());
++
++ }
++
++
++ // ------------------------------------------------------ Protected Methods
++
++
++ /**
++ * Adjust the URL pattern to begin with a leading slash, if appropriate
++ * (i.e. we are running a servlet 2.2 application). Otherwise, return
++ * the specified URL pattern unchanged.
++ *
++ * @param urlPattern The URL pattern to be adjusted (if needed)
++ * and returned
++ */
++ protected String adjustURLPattern(String urlPattern) {
++
++ if (urlPattern == null)
++ return (urlPattern);
++ if (urlPattern.startsWith("/") || urlPattern.startsWith("*."))
++ return (urlPattern);
++ if (!isServlet22())
++ return (urlPattern);
++ if(log.isDebugEnabled())
++ log.debug(sm.getString("standardContext.urlPattern.patternWarning",
++ urlPattern));
++ return ("/" + urlPattern);
++
++ }
++
++
++ /**
++ * Are we processing a version 2.2 deployment descriptor?
++ */
++ protected boolean isServlet22() {
++
++ if (this.publicId == null)
++ return (false);
++ if (this.publicId.equals
++ (org.apache.catalina.startup.Constants.WebDtdPublicId_22))
++ return (true);
++ else
++ return (false);
++
++ }
++
++
++ /**
++ * Return a File object representing the base directory for the
++ * entire servlet container (i.e. the Engine container if present).
++ */
++ protected File engineBase() {
++ String base=System.getProperty("catalina.base");
++ if( base == null ) {
++ StandardEngine eng=(StandardEngine)this.getParent().getParent();
++ base=eng.getBaseDir();
++ }
++ return (new File(base));
++ }
++
++
++ // -------------------------------------------------------- Private Methods
++
++
++ /**
++ * Bind current thread, both for CL purposes and for JNDI ENC support
++ * during : startup, shutdown and realoading of the context.
++ *
++ * @return the previous context class loader
++ */
++ private ClassLoader bindThread() {
++
++ ClassLoader oldContextClassLoader =
++ Thread.currentThread().getContextClassLoader();
++
++ if (getResources() == null)
++ return oldContextClassLoader;
++
++ if (getLoader().getClassLoader() != null) {
++ Thread.currentThread().setContextClassLoader
++ (getLoader().getClassLoader());
++ }
++
++ DirContextURLStreamHandler.bind(getResources());
++
++ if (isUseNaming()) {
++ try {
++ ContextBindings.bindThread(this, this);
++ } catch (NamingException e) {
++ // Silent catch, as this is a normal case during the early
++ // startup stages
++ }
++ }
++
++ return oldContextClassLoader;
++
++ }
++
++
++ /**
++ * Unbind thread.
++ */
++ private void unbindThread(ClassLoader oldContextClassLoader) {
++
++ Thread.currentThread().setContextClassLoader(oldContextClassLoader);
++
++ oldContextClassLoader = null;
++
++ if (isUseNaming()) {
++ ContextBindings.unbindThread(this, this);
++ }
++
++ DirContextURLStreamHandler.unbind();
++
++ }
++
++
++
++ /**
++ * Get base path.
++ */
++ private String getBasePath() {
++ String docBase = null;
++ Container container = this;
++ while (container != null) {
++ if (container instanceof Host)
++ break;
++ container = container.getParent();
++ }
++ File file = new File(getDocBase());
++ if (!file.isAbsolute()) {
++ if (container == null) {
++ docBase = (new File(engineBase(), getDocBase())).getPath();
++ } else {
++ // Use the "appBase" property of this container
++ String appBase = ((Host) container).getAppBase();
++ file = new File(appBase);
++ if (!file.isAbsolute())
++ file = new File(engineBase(), appBase);
++ docBase = (new File(file, getDocBase())).getPath();
++ }
++ } else {
++ docBase = file.getPath();
++ }
++ return docBase;
++ }
++
++
++ /**
++ * Get app base.
++ */
++ private String getAppBase() {
++ String appBase = null;
++ Container container = this;
++ while (container != null) {
++ if (container instanceof Host)
++ break;
++ container = container.getParent();
++ }
++ if (container != null) {
++ appBase = ((Host) container).getAppBase();
++ }
++ return appBase;
++ }
++
++
++ /**
++ * Get config base.
++ */
++ public File getConfigBase() {
++ File configBase =
++ new File(System.getProperty("catalina.base"), "conf");
++ if (!configBase.exists()) {
++ return null;
++ }
++ Container container = this;
++ Container host = null;
++ Container engine = null;
++ while (container != null) {
++ if (container instanceof Host)
++ host = container;
++ if (container instanceof Engine)
++ engine = container;
++ container = container.getParent();
++ }
++ if (engine != null) {
++ configBase = new File(configBase, engine.getName());
++ }
++ if (host != null) {
++ configBase = new File(configBase, host.getName());
++ }
++ if (saveConfig) {
++ configBase.mkdirs();
++ }
++ return configBase;
++ }
++
++
++ /**
++ * Given a context path, get the config file name.
++ */
++ protected String getDefaultConfigFile() {
++ String basename = null;
++ String path = getPath();
++ if (path.equals("")) {
++ basename = "ROOT";
++ } else {
++ basename = path.substring(1).replace('/', '#');
++ }
++ return (basename + ".xml");
++ }
++
++
++ /**
++ * Copy a file.
++ */
++ private boolean copy(File src, File dest) {
++ FileInputStream is = null;
++ FileOutputStream os = null;
++ try {
++ is = new FileInputStream(src);
++ os = new FileOutputStream(dest);
++ byte[] buf = new byte[4096];
++ while (true) {
++ int len = is.read(buf);
++ if (len < 0)
++ break;
++ os.write(buf, 0, len);
++ }
++ is.close();
++ os.close();
++ } catch (IOException e) {
++ return false;
++ } finally {
++ try {
++ if (is != null) {
++ is.close();
++ }
++ } catch (Exception e) {
++ // Ignore
++ }
++ try {
++ if (os != null) {
++ os.close();
++ }
++ } catch (Exception e) {
++ // Ignore
++ }
++ }
++ return true;
++ }
++
++
++ /**
++ * Get naming context full name.
++ */
++ private String getNamingContextName() {
++ if (namingContextName == null) {
++ Container parent = getParent();
++ if (parent == null) {
++ namingContextName = getName();
++ } else {
++ Stack stk = new Stack();
++ StringBuffer buff = new StringBuffer();
++ while (parent != null) {
++ stk.push(parent.getName());
++ parent = parent.getParent();
++ }
++ while (!stk.empty()) {
++ buff.append("/" + stk.pop());
++ }
++ buff.append(getName());
++ namingContextName = buff.toString();
++ }
++ }
++ return namingContextName;
++ }
++
++
++ /**
++ * Return the request processing paused flag for this Context.
++ */
++ public boolean getPaused() {
++
++ return (this.paused);
++
++ }
++
++
++ /**
++ * Post a copy of our web application resources as a servlet context
++ * attribute.
++ */
++ private void postResources() {
++
++ getServletContext().setAttribute
++ (Globals.RESOURCES_ATTR, getResources());
++
++ }
++
++
++ /**
++ * Post a copy of our current list of welcome files as a servlet context
++ * attribute, so that the default servlet can find them.
++ */
++ private void postWelcomeFiles() {
++
++ getServletContext().setAttribute("org.apache.catalina.WELCOME_FILES",
++ welcomeFiles);
++
++ }
++
++ public String getHostname() {
++ Container parentHost = getParent();
++ if (parentHost != null) {
++ hostName = parentHost.getName();
++ }
++ if ((hostName == null) || (hostName.length() < 1))
++ hostName = "_";
++ return hostName;
++ }
++
++ /**
++ * Set the appropriate context attribute for our work directory.
++ */
++ private void postWorkDirectory() {
++
++ // Acquire (or calculate) the work directory path
++ String workDir = getWorkDir();
++ if (workDir == null) {
++
++ // Retrieve our parent (normally a host) name
++ String hostName = null;
++ String engineName = null;
++ String hostWorkDir = null;
++ Container parentHost = getParent();
++ if (parentHost != null) {
++ hostName = parentHost.getName();
++ if (parentHost instanceof StandardHost) {
++ hostWorkDir = ((StandardHost)parentHost).getWorkDir();
++ }
++ Container parentEngine = parentHost.getParent();
++ if (parentEngine != null) {
++ engineName = parentEngine.getName();
++ }
++ }
++ if ((hostName == null) || (hostName.length() < 1))
++ hostName = "_";
++ if ((engineName == null) || (engineName.length() < 1))
++ engineName = "_";
++
++ String temp = getPath();
++ if (temp.startsWith("/"))
++ temp = temp.substring(1);
++ temp = temp.replace('/', '_');
++ temp = temp.replace('\\', '_');
++ if (temp.length() < 1)
++ temp = "_";
++ if (hostWorkDir != null ) {
++ workDir = hostWorkDir + File.separator + temp;
++ } else {
++ workDir = "work" + File.separator + engineName +
++ File.separator + hostName + File.separator + temp;
++ }
++ setWorkDir(workDir);
++ }
++
++ // Create this directory if necessary
++ File dir = new File(workDir);
++ if (!dir.isAbsolute()) {
++ File catalinaHome = engineBase();
++ String catalinaHomePath = null;
++ try {
++ catalinaHomePath = catalinaHome.getCanonicalPath();
++ dir = new File(catalinaHomePath, workDir);
++ } catch (IOException e) {
++ }
++ }
++ dir.mkdirs();
++
++ // Set the appropriate servlet context attribute
++ getServletContext().setAttribute(Globals.WORK_DIR_ATTR, dir);
++ if (getServletContext() instanceof ApplicationContext)
++ ((ApplicationContext) getServletContext()).setAttributeReadOnly
++ (Globals.WORK_DIR_ATTR);
++
++ }
++
++
++ /**
++ * Set the request processing paused flag for this Context.
++ *
++ * @param paused The new request processing paused flag
++ */
++ private void setPaused(boolean paused) {
++
++ this.paused = paused;
++
++ }
++
++
++ /**
++ * Validate the syntax of a proposed <code><url-pattern></code>
++ * for conformance with specification requirements.
++ *
++ * @param urlPattern URL pattern to be validated
++ */
++ private boolean validateURLPattern(String urlPattern) {
++
++ if (urlPattern == null)
++ return (false);
++ if (urlPattern.indexOf('\n') >= 0 || urlPattern.indexOf('\r') >= 0) {
++ getLogger().warn(sm.getString("standardContext.crlfinurl",urlPattern));
++ }
++ if (urlPattern.startsWith("*.")) {
++ if (urlPattern.indexOf('/') < 0)
++ return (true);
++ else
++ return (false);
++ }
++ if ( (urlPattern.startsWith("/")) &&
++ (urlPattern.indexOf("*.") < 0))
++ return (true);
++ else
++ return (false);
++
++ }
++
++
++ // ------------------------------------------------------------- Operations
++
++
++ /**
++ * JSR77 deploymentDescriptor attribute
++ *
++ * @return string deployment descriptor
++ */
++ public String getDeploymentDescriptor() {
++
++ InputStream stream = null;
++ ServletContext servletContext = getServletContext();
++ if (servletContext != null) {
++ stream = servletContext.getResourceAsStream(
++ org.apache.catalina.startup.Constants.ApplicationWebXml);
++ }
++ if (stream == null) {
++ return "";
++ }
++ BufferedReader br = new BufferedReader(
++ new InputStreamReader(stream));
++ StringBuffer sb = new StringBuffer();
++ String strRead = "";
++ try {
++ while (strRead != null) {
++ sb.append(strRead);
++ strRead = br.readLine();
++ }
++ } catch (IOException e) {
++ return "";
++ }
++
++ return sb.toString();
++
++ }
++
++
++ /**
++ * JSR77 servlets attribute
++ *
++ * @return list of all servlets ( we know about )
++ */
++ public String[] getServlets() {
++
++ String[] result = null;
++
++ Container[] children = findChildren();
++ if (children != null) {
++ result = new String[children.length];
++ for( int i=0; i< children.length; i++ ) {
++ result[i] = ((StandardWrapper)children[i]).getObjectName();
++ }
++ }
++
++ return result;
++ }
++
++
++ public ObjectName createObjectName(String hostDomain, ObjectName parentName)
++ throws MalformedObjectNameException
++ {
++ String onameStr;
++ StandardHost hst=(StandardHost)getParent();
++
++ String pathName=getName();
++ String hostName=getParent().getName();
++ String name= "//" + ((hostName==null)? "DEFAULT" : hostName) +
++ (("".equals(pathName))?"/":pathName );
++
++ String suffix=",J2EEApplication=" +
++ getJ2EEApplication() + ",J2EEServer=" +
++ getJ2EEServer();
++
++ onameStr="j2eeType=WebModule,name=" + name + suffix;
++ if( log.isDebugEnabled())
++ log.debug("Registering " + onameStr + " for " + oname);
++
++ // default case - no domain explictely set.
++ if( getDomain() == null ) domain=hst.getDomain();
++
++ ObjectName oname=new ObjectName(getDomain() + ":" + onameStr);
++ return oname;
++ }
++
++ private void preRegisterJMX() {
++ try {
++ StandardHost host = (StandardHost) getParent();
++ if ((oname == null)
++ || (oname.getKeyProperty("j2eeType") == null)) {
++ oname = createObjectName(host.getDomain(), host.getJmxName());
++ controller = oname;
++ }
++ } catch(Exception ex) {
++ if(log.isInfoEnabled())
++ log.info("Error registering ctx with jmx " + this + " " +
++ oname + " " + ex.toString(), ex );
++ }
++ }
++
++ private void registerJMX() {
++ try {
++ if (log.isDebugEnabled()) {
++ log.debug("Checking for " + oname );
++ }
++ if(! Registry.getRegistry(null, null)
++ .getMBeanServer().isRegistered(oname)) {
++ controller = oname;
++ Registry.getRegistry(null, null)
++ .registerComponent(this, oname, null);
++
++ // Send j2ee.object.created notification
++ if (this.getObjectName() != null) {
++ Notification notification = new Notification(
++ "j2ee.object.created",
++ this.getObjectName(),
++ sequenceNumber++);
++ broadcaster.sendNotification(notification);
++ }
++ }
++ Container children[] = findChildren();
++ for (int i=0; children!=null && i<children.length; i++) {
++ ((StandardWrapper)children[i]).registerJMX( this );
++ }
++ } catch (Exception ex) {
++ if(log.isInfoEnabled())
++ log.info("Error registering wrapper with jmx " + this + " " +
++ oname + " " + ex.toString(), ex );
++ }
++ }
++
++ /** There are 2 cases:
++ * 1.The context is created and registered by internal APIS
++ * 2. The context is created by JMX, and it'll self-register.
++ *
++ * @param server The server
++ * @param name The object name
++ * @return ObjectName The name of the object
++ * @throws Exception If an error occurs
++ */
++ public ObjectName preRegister(MBeanServer server,
++ ObjectName name)
++ throws Exception
++ {
++ if( oname != null ) {
++ //log.info( "Already registered " + oname + " " + name);
++ // Temporary - /admin uses the old names
++ return name;
++ }
++ ObjectName result=super.preRegister(server,name);
++ return name;
++ }
++
++ public void preDeregister() throws Exception {
++ if( started ) {
++ try {
++ stop();
++ } catch( Exception ex ) {
++ log.error( "error stopping ", ex);
++ }
++ }
++ }
++
++ public void init() throws Exception {
++
++ if( this.getParent() == null ) {
++ ObjectName parentName=getParentName();
++
++ if( ! mserver.isRegistered(parentName)) {
++ if(log.isDebugEnabled())
++ log.debug("No host, creating one " + parentName);
++ StandardHost host=new StandardHost();
++ host.setName(hostName);
++ host.setAutoDeploy(false);
++ Registry.getRegistry(null, null)
++ .registerComponent(host, parentName, null);
++ mserver.invoke(parentName, "init", new Object[] {}, new String[] {} );
++ }
++ ContextConfig config = new ContextConfig();
++ this.addLifecycleListener(config);
++
++ if(log.isDebugEnabled())
++ log.debug( "AddChild " + parentName + " " + this);
++ try {
++ mserver.invoke(parentName, "addChild", new Object[] { this },
++ new String[] {"org.apache.catalina.Container"});
++ } catch (Exception e) {
++ destroy();
++ throw e;
++ }
++ // It's possible that addChild may have started us
++ if( initialized ) {
++ return;
++ }
++ }
++ super.init();
++
++ // Notify our interested LifecycleListeners
++ lifecycle.fireLifecycleEvent(INIT_EVENT, null);
++
++ // Send j2ee.state.starting notification
++ if (this.getObjectName() != null) {
++ Notification notification = new Notification("j2ee.state.starting",
++ this.getObjectName(),
++ sequenceNumber++);
++ broadcaster.sendNotification(notification);
++ }
++
++ }
++
++ public ObjectName getParentName() throws MalformedObjectNameException {
++ // "Life" update
++ String path=oname.getKeyProperty("name");
++ if( path == null ) {
++ log.error( "No name attribute " +name );
++ return null;
++ }
++ if( ! path.startsWith( "//")) {
++ log.error("Invalid name " + name);
++ }
++ path=path.substring(2);
++ int delim=path.indexOf( "/" );
++ hostName="localhost"; // Should be default...
++ if( delim > 0 ) {
++ hostName=path.substring(0, delim);
++ path = path.substring(delim);
++ if (path.equals("/")) {
++ this.setName("");
++ } else {
++ this.setName(path);
++ }
++ } else {
++ if(log.isDebugEnabled())
++ log.debug("Setting path " + path );
++ this.setName( path );
++ }
++ // XXX The service and domain should be the same.
++ String parentDomain=getEngineName();
++ if( parentDomain == null ) parentDomain=domain;
++ ObjectName parentName=new ObjectName( parentDomain + ":" +
++ "type=Host,host=" + hostName);
++ return parentName;
++ }
++
++ public void create() throws Exception{
++ init();
++ }
++
++ /* Remove a JMX notficationListener
++ * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
++ */
++ public void removeNotificationListener(NotificationListener listener,
++ NotificationFilter filter, Object object) throws ListenerNotFoundException {
++ broadcaster.removeNotificationListener(listener,filter,object);
++
++ }
++
++ private MBeanNotificationInfo[] notificationInfo;
++
++ /* Get JMX Broadcaster Info
++ * @TODO use StringManager for international support!
++ * @TODO This two events we not send j2ee.state.failed and j2ee.attribute.changed!
++ * @see javax.management.NotificationBroadcaster#getNotificationInfo()
++ */
++ public MBeanNotificationInfo[] getNotificationInfo() {
++ // FIXME: i18n
++ if(notificationInfo == null) {
++ notificationInfo = new MBeanNotificationInfo[]{
++ new MBeanNotificationInfo(new String[] {
++ "j2ee.object.created"},
++ Notification.class.getName(),
++ "web application is created"
++ ),
++ new MBeanNotificationInfo(new String[] {
++ "j2ee.state.starting"},
++ Notification.class.getName(),
++ "change web application is starting"
++ ),
++ new MBeanNotificationInfo(new String[] {
++ "j2ee.state.running"},
++ Notification.class.getName(),
++ "web application is running"
++ ),
++ new MBeanNotificationInfo(new String[] {
++ "j2ee.state.stopped"},
++ Notification.class.getName(),
++ "web application start to stopped"
++ ),
++ new MBeanNotificationInfo(new String[] {
++ "j2ee.object.stopped"},
++ Notification.class.getName(),
++ "web application is stopped"
++ ),
++ new MBeanNotificationInfo(new String[] {
++ "j2ee.object.deleted"},
++ Notification.class.getName(),
++ "web application is deleted"
++ )
++ };
++
++ }
++
++ return notificationInfo;
++ }
++
++
++ /* Add a JMX-NotificationListener
++ * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
++ */
++ public void addNotificationListener(NotificationListener listener,
++ NotificationFilter filter, Object object) throws IllegalArgumentException {
++ broadcaster.addNotificationListener(listener,filter,object);
++
++ }
++
++
++ /**
++ * Remove a JMX-NotificationListener
++ * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
++ */
++ public void removeNotificationListener(NotificationListener listener)
++ throws ListenerNotFoundException {
++ broadcaster.removeNotificationListener(listener);
++
++ }
++
++
++ // ------------------------------------------------------------- Attributes
++
++
++ /**
++ * Return the naming resources associated with this web application.
++ */
++ public javax.naming.directory.DirContext getStaticResources() {
++
++ return getResources();
++
++ }
++
++
++ /**
++ * Return the naming resources associated with this web application.
++ * FIXME: Fooling introspection ...
++ */
++ public javax.naming.directory.DirContext findStaticResources() {
++
++ return getResources();
++
++ }
++
++
++ /**
++ * Return the naming resources associated with this web application.
++ */
++ public String[] getWelcomeFiles() {
++
++ return findWelcomeFiles();
++
++ }
++
++ /**
++ * Set the validation feature of the XML parser used when
++ * parsing xml instances.
++ * @param webXmlValidation true to enable xml instance validation
++ */
++ public void setXmlValidation(boolean webXmlValidation){
++
++ this.webXmlValidation = webXmlValidation;
++
++ }
++
++ /**
++ * Get the server.xml <context> attribute's xmlValidation.
++ * @return true if validation is enabled.
++ *
++ */
++ public boolean getXmlValidation(){
++ return webXmlValidation;
++ }
++
++
++ /**
++ * Get the server.xml <context> attribute's xmlNamespaceAware.
++ * @return true if namespace awarenes is enabled.
++ */
++ public boolean getXmlNamespaceAware(){
++ return webXmlNamespaceAware;
++ }
++
++
++ /**
++ * Set the namespace aware feature of the XML parser used when
++ * parsing xml instances.
++ * @param webXmlNamespaceAware true to enable namespace awareness
++ */
++ public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
++ this.webXmlNamespaceAware= webXmlNamespaceAware;
++ }
++
++
++ /**
++ * Set the validation feature of the XML parser used when
++ * parsing tlds files.
++ * @param tldValidation true to enable xml instance validation
++ */
++ public void setTldValidation(boolean tldValidation){
++
++ this.tldValidation = tldValidation;
++
++ }
++
++ /**
++ * Get the server.xml <context> attribute's webXmlValidation.
++ * @return true if validation is enabled.
++ *
++ */
++ public boolean getTldValidation(){
++ return tldValidation;
++ }
++
++ /**
++ * Sets the process TLDs attribute.
++ *
++ * @param newProcessTlds The new value
++ */
++ public void setProcessTlds(boolean newProcessTlds) {
++ processTlds = newProcessTlds;
++ }
++
++ /**
++ * Returns the processTlds attribute value.
++ */
++ public boolean getProcessTlds() {
++ return processTlds;
++ }
++
++ /**
++ * Get the server.xml <host> attribute's xmlNamespaceAware.
++ * @return true if namespace awarenes is enabled.
++ */
++ public boolean getTldNamespaceAware(){
++ return tldNamespaceAware;
++ }
++
++
++ /**
++ * Set the namespace aware feature of the XML parser used when
++ * parsing xml instances.
++ * @param tldNamespaceAware true to enable namespace awareness
++ */
++ public void setTldNamespaceAware(boolean tldNamespaceAware){
++ this.tldNamespaceAware= tldNamespaceAware;
++ }
++
++
++ /**
++ * Support for "stateManageable" JSR77
++ */
++ public boolean isStateManageable() {
++ return true;
++ }
++
++ public void startRecursive() throws LifecycleException {
++ // nothing to start recursive, the servlets will be started by load-on-startup
++ start();
++ }
++
++ public int getState() {
++ if( started ) {
++ return 1; // RUNNING
++ }
++ if( initialized ) {
++ return 0; // starting ?
++ }
++ if( ! available ) {
++ return 4; //FAILED
++ }
++ // 2 - STOPPING
++ return 3; // STOPPED
++ }
++
++ /**
++ * The J2EE Server ObjectName this module is deployed on.
++ */
++ private String server = null;
++
++ /**
++ * The Java virtual machines on which this module is running.
++ */
++ private String[] javaVMs = null;
++
++ public String getServer() {
++ return server;
++ }
++
++ public String setServer(String server) {
++ return this.server=server;
++ }
++
++ public String[] getJavaVMs() {
++ return javaVMs;
++ }
++
++ public String[] setJavaVMs(String[] javaVMs) {
++ return this.javaVMs = javaVMs;
++ }
++
++ /**
++ * Gets the time this context was started.
++ *
++ * @return Time (in milliseconds since January 1, 1970, 00:00:00) when this
++ * context was started
++ */
++ public long getStartTime() {
++ return startTime;
++ }
++
++ public boolean isEventProvider() {
++ return false;
++ }
++
++ public boolean isStatisticsProvider() {
++ return false;
++ }
++
++}
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/jakarta-tomcat-catalina.iml jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/jakarta-tomcat-catalina.iml
+--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/jakarta-tomcat-catalina.iml 1969-12-31 19:00:00.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-catalina/jakarta-tomcat-catalina.iml 2005-09-26 01:21:13.000000000 -0400
+@@ -0,0 +1,16 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<module version="4" relativePaths="true" type="JAVA_MODULE">
++ <component name="ModuleRootManager" />
++ <component name="NewModuleRootManager">
++ <output url="file://$MODULE_DIR$/classes" />
++ <exclude-output />
++ <content url="file://$MODULE_DIR$">
++ <sourceFolder url="file://$MODULE_DIR$/catalina/src/share" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/catalina/src/test" isTestSource="false" />
++ </content>
++ <orderEntry type="inheritedJdk" />
++ <orderEntry type="sourceFolder" forTests="false" />
++ <orderEntryProperties />
++ </component>
++</module>
++
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/jakarta-tomcat-connectors.iml jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/jakarta-tomcat-connectors.iml
+--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/jakarta-tomcat-connectors.iml 1969-12-31 19:00:00.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/jakarta-tomcat-connectors.iml 2005-09-26 01:21:13.000000000 -0400
+@@ -0,0 +1,28 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<module version="4" relativePaths="true" type="JAVA_MODULE">
++ <component name="ModuleRootManager" />
++ <component name="NewModuleRootManager">
++ <output url="file://$MODULE_DIR$/classes" />
++ <exclude-output />
++ <content url="file://$MODULE_DIR$">
++ <sourceFolder url="file://$MODULE_DIR$/coyote/src/java" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/coyote/src/test" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/http11/src/java" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/http11/src/test/java" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jk/java" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jk/jkant/java" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jk/test" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jni/examples" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jni/java" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/jni/test" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/juli/src/java" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/naming/src" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/util/java" isTestSource="false" />
++ <sourceFolder url="file://$MODULE_DIR$/util/loader" isTestSource="false" />
++ </content>
++ <orderEntry type="inheritedJdk" />
++ <orderEntry type="sourceFolder" forTests="false" />
++ <orderEntryProperties />
++ </component>
++</module>
++
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jakarta-tomcat-jasper.iml jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jakarta-tomcat-jasper.iml
+--- upstream/jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jakarta-tomcat-jasper.iml 1969-12-31 19:00:00.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jakarta-tomcat-jasper.iml 2005-09-26 00:02:02.000000000 -0400
+@@ -0,0 +1,15 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<module version="4" relativePaths="true" type="JAVA_MODULE">
++ <component name="ModuleRootManager" />
++ <component name="NewModuleRootManager">
++ <output url="file://$MODULE_DIR$/classes" />
++ <exclude-output />
++ <content url="file://$MODULE_DIR$">
++ <sourceFolder url="file://$MODULE_DIR$/jasper2/src/share" isTestSource="false" />
++ </content>
++ <orderEntry type="inheritedJdk" />
++ <orderEntry type="sourceFolder" forTests="false" />
++ <orderEntryProperties />
++ </component>
++</module>
++
+diff -Nru upstream/jakarta-tomcat-5.5.9-src/LICENSE jakarta-tomcat-5.5.9-src/LICENSE
+--- upstream/jakarta-tomcat-5.5.9-src/LICENSE 1969-12-31 19:00:00.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/LICENSE 2005-09-26 00:05:01.000000000 -0400
+@@ -0,0 +1,201 @@
++ Apache License
++ Version 2.0, January 2004
++ http://www.apache.org/licenses/
++
++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
++
++ 1. Definitions.
++
++ "License" shall mean the terms and conditions for use, reproduction,
++ and distribution as defined by Sections 1 through 9 of this document.
++
++ "Licensor" shall mean the copyright owner or entity authorized by
++ the copyright owner that is granting the License.
++
++ "Legal Entity" shall mean the union of the acting entity and all
++ other entities that control, are controlled by, or are under common
++ control with that entity. For the purposes of this definition,
++ "control" means (i) the power, direct or indirect, to cause the
++ direction or management of such entity, whether by contract or
++ otherwise, or (ii) ownership of fifty percent (50%) or more of the
++ outstanding shares, or (iii) beneficial ownership of such entity.
++
++ "You" (or "Your") shall mean an individual or Legal Entity
++ exercising permissions granted by this License.
++
++ "Source" form shall mean the preferred form for making modifications,
++ including but not limited to software source code, documentation
++ source, and configuration files.
++
++ "Object" form shall mean any form resulting from mechanical
++ transformation or translation of a Source form, including but
++ not limited to compiled object code, generated documentation,
++ and conversions to other media types.
++
++ "Work" shall mean the work of authorship, whether in Source or
++ Object form, made available under the License, as indicated by a
++ copyright notice that is included in or attached to the work
++ (an example is provided in the Appendix below).
++
++ "Derivative Works" shall mean any work, whether in Source or Object
++ form, that is based on (or derived from) the Work and for which the
++ editorial revisions, annotations, elaborations, or other modifications
++ represent, as a whole, an original work of authorship. For the purposes
++ of this License, Derivative Works shall not include works that remain
++ separable from, or merely link (or bind by name) to the interfaces of,
++ the Work and Derivative Works thereof.
++
++ "Contribution" shall mean any work of authorship, including
++ the original version of the Work and any modifications or additions
++ to that Work or Derivative Works thereof, that is intentionally
++ submitted to Licensor for inclusion in the Work by the copyright owner
++ or by an individual or Legal Entity authorized to submit on behalf of
++ the copyright owner. For the purposes of this definition, "submitted"
++ means any form of electronic, verbal, or written communication sent
++ to the Licensor or its representatives, including but not limited to
++ communication on electronic mailing lists, source code control systems,
++ and issue tracking systems that are managed by, or on behalf of, the
++ Licensor for the purpose of discussing and improving the Work, but
++ excluding communication that is conspicuously marked or otherwise
++ designated in writing by the copyright owner as "Not a Contribution."
++
++ "Contributor" shall mean Licensor and any individual or Legal Entity
++ on behalf of whom a Contribution has been received by Licensor and
++ subsequently incorporated within the Work.
++
++ 2. Grant of Copyright License. Subject to the terms and conditions of
++ this License, each Contributor hereby grants to You a perpetual,
++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
++ copyright license to reproduce, prepare Derivative Works of,
++ publicly display, publicly perform, sublicense, and distribute the
++ Work and such Derivative Works in Source or Object form.
++
++ 3. Grant of Patent License. Subject to the terms and conditions of
++ this License, each Contributor hereby grants to You a perpetual,
++ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
++ (except as stated in this section) patent license to make, have made,
++ use, offer to sell, sell, import, and otherwise transfer the Work,
++ where such license applies only to those patent claims licensable
++ by such Contributor that are necessarily infringed by their
++ Contribution(s) alone or by combination of their Contribution(s)
++ with the Work to which such Contribution(s) was submitted. If You
++ institute patent litigation against any entity (including a
++ cross-claim or counterclaim in a lawsuit) alleging that the Work
++ or a Contribution incorporated within the Work constitutes direct
++ or contributory patent infringement, then any patent licenses
++ granted to You under this License for that Work shall terminate
++ as of the date such litigation is filed.
++
++ 4. Redistribution. You may reproduce and distribute copies of the
++ Work or Derivative Works thereof in any medium, with or without
++ modifications, and in Source or Object form, provided that You
++ meet the following conditions:
++
++ (a) You must give any other recipients of the Work or
++ Derivative Works a copy of this License; and
++
++ (b) You must cause any modified files to carry prominent notices
++ stating that You changed the files; and
++
++ (c) You must retain, in the Source form of any Derivative Works
++ that You distribute, all copyright, patent, trademark, and
++ attribution notices from the Source form of the Work,
++ excluding those notices that do not pertain to any part of
++ the Derivative Works; and
++
++ (d) If the Work includes a "NOTICE" text file as part of its
++ distribution, then any Derivative Works that You distribute must
++ include a readable copy of the attribution notices contained
++ within such NOTICE file, excluding those notices that do not
++ pertain to any part of the Derivative Works, in at least one
++ of the following places: within a NOTICE text file distributed
++ as part of the Derivative Works; within the Source form or
++ documentation, if provided along with the Derivative Works; or,
++ within a display generated by the Derivative Works, if and
++ wherever such third-party notices normally appear. The contents
++ of the NOTICE file are for informational purposes only and
++ do not modify the License. You may add Your own attribution
++ notices within Derivative Works that You distribute, alongside
++ or as an addendum to the NOTICE text from the Work, provided
++ that such additional attribution notices cannot be construed
++ as modifying the License.
++
++ You may add Your own copyright statement to Your modifications and
++ may provide additional or different license terms and conditions
++ for use, reproduction, or distribution of Your modifications, or
++ for any such Derivative Works as a whole, provided Your use,
++ reproduction, and distribution of the Work otherwise complies with
++ the conditions stated in this License.
++
++ 5. Submission of Contributions. Unless You explicitly state otherwise,
++ any Contribution intentionally submitted for inclusion in the Work
++ by You to the Licensor shall be under the terms and conditions of
++ this License, without any additional terms or conditions.
++ Notwithstanding the above, nothing herein shall supersede or modify
++ the terms of any separate license agreement you may have executed
++ with Licensor regarding such Contributions.
++
++ 6. Trademarks. This License does not grant permission to use the trade
++ names, trademarks, service marks, or product names of the Licensor,
++ except as required for reasonable and customary use in describing the
++ origin of the Work and reproducing the content of the NOTICE file.
++
++ 7. Disclaimer of Warranty. Unless required by applicable law or
++ agreed to in writing, Licensor provides the Work (and each
++ Contributor provides its Contributions) on an "AS IS" BASIS,
++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
++ implied, including, without limitation, any warranties or conditions
++ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
++ PARTICULAR PURPOSE. You are solely responsible for determining the
++ appropriateness of using or redistributing the Work and assume any
++ risks associated with Your exercise of permissions under this License.
++
++ 8. Limitation of Liability. In no event and under no legal theory,
++ whether in tort (including negligence), contract, or otherwise,
++ unless required by applicable law (such as deliberate and grossly
++ negligent acts) or agreed to in writing, shall any Contributor be
++ liable to You for damages, including any direct, indirect, special,
++ incidental, or consequential damages of any character arising as a
++ result of this License or out of the use or inability to use the
++ Work (including but not limited to damages for loss of goodwill,
++ work stoppage, computer failure or malfunction, or any and all
++ other commercial damages or losses), even if such Contributor
++ has been advised of the possibility of such damages.
++
++ 9. Accepting Warranty or Additional Liability. While redistributing
++ the Work or Derivative Works thereof, You may choose to offer,
++ and charge a fee for, acceptance of support, warranty, indemnity,
++ or other liability obligations and/or rights consistent with this
++ License. However, in accepting such obligations, You may act only
++ on Your own behalf and on Your sole responsibility, not on behalf
++ of any other Contributor, and only if You agree to indemnify,
++ defend, and hold each Contributor harmless for any liability
++ incurred by, or claims asserted against, such Contributor by reason
++ of your accepting any such warranty or additional liability.
++
++ END OF TERMS AND CONDITIONS
++
++ APPENDIX: How to apply the Apache License to your work.
++
++ To apply the Apache License to your work, attach the following
++ boilerplate notice, with the fields enclosed by brackets "[]"
++ replaced with your own identifying information. (Don't include
++ the brackets!) The text should be enclosed in the appropriate
++ comment syntax for the file format. We also recommend that a
++ file or class name and description of purpose be included on the
++ same "printed page" as the copyright notice for easier
++ identification within third-party archives.
++
++ Copyright [yyyy] [name of copyright owner]
++
++ 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.
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-removeJSSEfor13.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-removeJSSEfor13.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9-removeJSSEfor13.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,234 @@
+--- jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSE13Factory.java 2005-03-26 14:24:17.000000000 -0500
++++ /dev/null 2006-08-15 16:32:17.991678056 -0400
+@@ -1,43 +0,0 @@
+-/*
+- * Copyright 1999-2004 The Apache Software Foundation
+- *
+- * 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.apache.tomcat.util.net.jsse;
+-
+-import java.net.Socket;
+-import javax.net.ssl.SSLSocket;
+-import org.apache.tomcat.util.net.SSLSupport;
+-import org.apache.tomcat.util.net.ServerSocketFactory;
+-
+-/**
+- * Implementation class for JSSEFactory for JSSE 1.0.x (that is an extension
+- * to the 1.3 JVM).
+- *
+- * @author Bill Barker
+- */
+-
+-class JSSE13Factory implements JSSEFactory {
+-
+- JSSE13Factory() {
+- }
+-
+- public ServerSocketFactory getSocketFactory() {
+- return new JSSE13SocketFactory();
+- }
+-
+- public SSLSupport getSSLSupport(Socket socket) {
+- return new JSSESupport((SSLSocket)socket);
+- }
+-}
+--- jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSE13SocketFactory.java 2005-03-26 14:24:17.000000000 -0500
++++ /dev/null 2006-08-15 16:32:17.991678056 -0400
+@@ -1,156 +0,0 @@
+-/*
+- * Copyright 1999-2004 The Apache Software Foundation
+- *
+- * 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.apache.tomcat.util.net.jsse;
+-
+-import java.io.IOException;
+-import java.security.KeyStore;
+-import java.security.SecureRandom;
+-import java.security.Security;
+-import java.security.Provider;
+-
+-import javax.net.ssl.SSLServerSocket;
+-import javax.net.ssl.SSLSocket;
+-
+-/*
+- 1. Make the JSSE's jars available, either as an installed
+- extension (copy them into jre/lib/ext) or by adding
+- them to the Tomcat classpath.
+- 2. keytool -genkey -alias tomcat -keyalg RSA
+- Use "changeit" as password ( this is the default we use )
+- */
+-
+-/**
+- * SSL server socket factory. It _requires_ a valid RSA key and
+- * JSSE.
+- *
+- * @author Harish Prabandham
+- * @author Costin Manolache
+- * @author Stefan Freyr Stefansson
+- * @author EKR -- renamed to JSSESocketFactory
+- * @author Bill Barker
+- */
+-public class JSSE13SocketFactory extends JSSESocketFactory
+-{
+- /**
+- * Flag for client authentication
+- */
+- protected boolean clientAuth = false;
+-
+- public JSSE13SocketFactory () {
+- super();
+- }
+-
+- /**
+- * Reads the keystore and initializes the SSL socket factory.
+- *
+- * NOTE: This method is identical in functionality to the method of the
+- * same name in JSSE14SocketFactory, except that this method is used with
+- * JSSE 1.0.x (which is an extension to the 1.3 JVM), whereas the other is
+- * used with JSSE 1.1.x (which ships with the 1.4 JVM). Therefore, this
+- * method uses classes in com.sun.net.ssl, which have since moved to
+- * javax.net.ssl, and explicitly registers the required security providers,
+- * which come standard in a 1.4 JVM.
+- */
+- void init() throws IOException {
+- try {
+- try {
+- Class ssps = Class.forName("sun.security.provider.Sun");
+- Security.addProvider ((Provider)ssps.newInstance());
+- }catch(Exception cnfe) {
+- //Ignore, since this is a non-Sun JVM
+- }
+- Security.addProvider (new com.sun.net.ssl.internal.ssl.Provider());
+-
+- String clientAuthStr = (String)attributes.get("clientauth");
+- if("true".equalsIgnoreCase(clientAuthStr) ||
+- "yes".equalsIgnoreCase(clientAuthStr) ||
+- "want".equalsIgnoreCase(clientAuthStr)) {
+- clientAuth = true;
+- }
+-
+- // SSL protocol variant (e.g., TLS, SSL v3, etc.)
+- String protocol = (String)attributes.get("protocol");
+- if (protocol == null) protocol = defaultProtocol;
+-
+- // Certificate encoding algorithm (e.g., SunX509)
+- String algorithm = (String)attributes.get("algorithm");
+- if (algorithm == null) algorithm = defaultAlgorithm;
+-
+- // Set up KeyManager, which will extract server key
+- com.sun.net.ssl.KeyManagerFactory kmf =
+- com.sun.net.ssl.KeyManagerFactory.getInstance(algorithm);
+- String keystoreType = (String)attributes.get("keystoreType");
+- if (keystoreType == null) {
+- keystoreType = defaultKeystoreType;
+- }
+- String keystorePass = getKeystorePassword();
+- kmf.init(getKeystore(keystoreType, keystorePass),
+- keystorePass.toCharArray());
+-
+- // Set up TrustManager
+- com.sun.net.ssl.TrustManager[] tm = null;
+- String truststoreType = (String)attributes.get("truststoreType");
+- if(truststoreType == null) {
+- truststoreType = keystoreType;
+- }
+- KeyStore trustStore = getTrustStore(truststoreType);
+- if (trustStore != null) {
+- com.sun.net.ssl.TrustManagerFactory tmf =
+- com.sun.net.ssl.TrustManagerFactory.getInstance("SunX509");
+- tmf.init(trustStore);
+- tm = tmf.getTrustManagers();
+- }
+-
+- // Create and init SSLContext
+- com.sun.net.ssl.SSLContext context =
+- com.sun.net.ssl.SSLContext.getInstance(protocol);
+- context.init(kmf.getKeyManagers(), tm, new SecureRandom());
+-
+- // Create proxy
+- sslProxy = context.getServerSocketFactory();
+-
+- // Determine which cipher suites to enable
+- String requestedCiphers = (String)attributes.get("ciphers");
+- enabledCiphers = getEnabledCiphers(requestedCiphers,
+- sslProxy.getSupportedCipherSuites());
+-
+- } catch(Exception e) {
+- if( e instanceof IOException )
+- throw (IOException)e;
+- throw new IOException(e.getMessage());
+- }
+- }
+- protected String[] getEnabledProtocols(SSLServerSocket socket,
+- String requestedProtocols){
+- return null;
+- }
+- protected void setEnabledProtocols(SSLServerSocket socket,
+- String [] protocols){
+- }
+-
+- protected void configureClientAuth(SSLServerSocket socket){
+- socket.setNeedClientAuth(clientAuth);
+- }
+-
+- protected void configureClientAuth(SSLSocket socket){
+- // In JSSE 1.0.2 docs it does not explicitly
+- // state whether SSLSockets returned from
+- // SSLServerSocket.accept() inherit this setting.
+- socket.setNeedClientAuth(clientAuth);
+- }
+-
+-}
+--- jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java.original 2006-10-25 16:33:35.000000000 -0400
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java 2006-10-25 16:58:14.000000000 -0400
+@@ -46,18 +46,21 @@
+ public JSSEImplementation() throws ClassNotFoundException {
+ // Check to see if JSSE is floating around somewhere
+ Class.forName(SSLSocketClass);
+- if( JdkCompat.isJava14() ) {
++ if( JdkCompat.isJava14() || JdkCompat.isJava15() ) {
+ try {
+ Class factcl = Class.forName(JSSE14Factory);
+ factory = (JSSEFactory)factcl.newInstance();
+ } catch(Exception ex) {
+- factory = new JSSE13Factory();
+- if(logger.isDebugEnabled()) {
+- logger.debug("Error getting factory: " + JSSE14Factory, ex);
++ if(logger.isErrorEnabled()) {
++ logger.error("Error getting factory: " + JSSE14Factory, ex);
+ }
++ throw (ClassNotFoundException) new ClassNotFoundException("error initializing JSSE factory").initCause(ex);
+ }
+ } else {
+- factory = new JSSE13Factory();
++ if(logger.isErrorEnabled()) {
++ logger.error("SSL is not supported for Java 1.3 and lower");
++ }
++ throw new IllegalStateException("SSL not supported for Java 1.3 and lower");
+ }
+ }
+
Added: apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9.patch01-JspServlet-5.15.17-backport.patch
===================================================================
--- apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9.patch01-JspServlet-5.15.17-backport.patch (rev 0)
+++ apache-tomcat/5.5.9.patch07-brew/src/tomcat5-5.5.9.patch01-JspServlet-5.15.17-backport.patch 2009-05-06 21:11:34 UTC (rev 26738)
@@ -0,0 +1,41 @@
+--- jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/servlet/JspServlet.java.old 2005-03-26 17:22:44.000000000 -0500
++++ jakarta-tomcat-5.5.9-src/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/servlet/JspServlet.java 2006-12-12 15:21:50.000000000 -0500
+@@ -17,6 +17,7 @@
+ package org.apache.jasper.servlet;
+
+ import java.io.IOException;
++import java.lang.reflect.Constructor;
+ import java.util.Enumeration;
+
+ import javax.servlet.ServletConfig;
+@@ -72,7 +73,29 @@
+ this.context = config.getServletContext();
+
+ // Initialize the JSP Runtime Context
+- options = new EmbeddedServletOptions(config, context);
++ // Check for a custom Options implementation
++ String engineOptionsName =
++ config.getInitParameter("engineOptionsClass");
++ if (engineOptionsName != null) {
++ // Instantiate the indicated Options implementation
++ try {
++ ClassLoader loader = Thread.currentThread()
++ .getContextClassLoader();
++ Class engineOptionsClass = loader.loadClass(engineOptionsName);
++ Class[] ctorSig = { ServletConfig.class, ServletContext.class };
++ Constructor ctor = engineOptionsClass.getConstructor(ctorSig);
++ Object[] args = { config, context };
++ options = (Options) ctor.newInstance(args);
++ } catch (Throwable e) {
++ // Need to localize this.
++ log.warn("Failed to load engineOptionsClass", e);
++ // Use the default Options implementation
++ options = new EmbeddedServletOptions(config, context);
++ }
++ } else {
++ // Use the default Options implementation
++ options = new EmbeddedServletOptions(config, context);
++ }
+ rctxt = new JspRuntimeContext(context,options);
+
+ if (log.isDebugEnabled()) {
More information about the jboss-cvs-commits
mailing list