tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject svn commit: r442109 [1/2] - in /tomcat/sandbox/tomcat-lite: ./ bin/ java/org/apache/tomcat/lite/ java/org/apache/tomcat/lite/http/ java/org/apache/tomcat/servlets/file/ java/org/apache/tomcat/servlets/session/ java/org/apache/tomcat/standalone/ java/or...
Date Mon, 11 Sep 2006 06:09:57 GMT
Author: costin
Date: Sun Sep 10 23:09:56 2006
New Revision: 442109

URL: http://svn.apache.org/viewvc?view=rev&rev=442109
Log:
Cleanup deps on catalina, cleanup a bit build.xml ( still need a better handling of deps )


Added:
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/HttpMessages.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocalStrings.properties
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MimeHeaders.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Parameters.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ServerCookie.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/package.html
    tomcat/sandbox/tomcat-lite/resources/deploy.MF   (with props)
    tomcat/sandbox/tomcat-lite/webapps/__x_classpath_jasper/
    tomcat/sandbox/tomcat-lite/webapps/__x_classpath_jasper/WEB-INF/
    tomcat/sandbox/tomcat-lite/webapps/__x_classpath_jasper/WEB-INF/lib/
Removed:
    tomcat/sandbox/tomcat-lite/bin/jam_http11.sh
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/standalone/ETomcat.java
Modified:
    tomcat/sandbox/tomcat-lite/.classpath
    tomcat/sandbox/tomcat-lite/.project
    tomcat/sandbox/tomcat-lite/bin/jam_tomcat.sh
    tomcat/sandbox/tomcat-lite/build.xml
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/ModuleClassLoader.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/http11/Endpoint.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/http11/Http11Processor.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/http11/Http11Protocol.java
    tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/net/simple/SimpleEndpoint.java

Modified: tomcat/sandbox/tomcat-lite/.classpath
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/.classpath?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/.classpath (original)
+++ tomcat/sandbox/tomcat-lite/.classpath Sun Sep 10 23:09:56 2006
@@ -1,7 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="java"/>
+	<classpathentry kind="lib" path="webapps/__x_deploy/WEB-INF/lib/javax.annotation.jar"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/tomcat6"/>
+	<classpathentry kind="lib" path="webapps/__x_classpath_jasper/WEB-INF/lib/jasper.jar"/>
+	<classpathentry kind="lib" path="resources/coyote-api.jar"/>
+	<classpathentry kind="lib" path="resources/javax.servlet.jar"/>
+	<classpathentry kind="lib" path="resources/tomcat-utils.jar"/>
 	<classpathentry kind="output" path="classes"/>
 </classpath>

Modified: tomcat/sandbox/tomcat-lite/.project
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/.project?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/.project (original)
+++ tomcat/sandbox/tomcat-lite/.project Sun Sep 10 23:09:56 2006
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>sandbox</name>
+	<name>tomcat-lite</name>
 	<comment></comment>
 	<projects>
 	</projects>

Modified: tomcat/sandbox/tomcat-lite/bin/jam_tomcat.sh
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/bin/jam_tomcat.sh?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/bin/jam_tomcat.sh (original)
+++ tomcat/sandbox/tomcat-lite/bin/jam_tomcat.sh Sun Sep 10 23:09:56 2006
@@ -1,4 +1,5 @@
 #!/bin/sh 
 
-BASE=`pwd`/..
-jamvm -Xms32M -cp $BASE/sandbox/runtime/tomcat-runtime.jar:$BASE/repository/mx4j-3.0.1/lib/mx4j.jar org.apache.tomcat.standalone.Main $*
+BASE=.
+jamvm -Xms32M -cp $BASE/classes:$BASE/tomcat-lite.jar org.apache.tomcat.lite.TomcatLite
+

Modified: tomcat/sandbox/tomcat-lite/build.xml
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/build.xml?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/build.xml (original)
+++ tomcat/sandbox/tomcat-lite/build.xml Sun Sep 10 23:09:56 2006
@@ -39,7 +39,7 @@
   <property name="compile.deprecation"  value="false" />
   <property name="compile.source"       value="1.5" />
 
-  <property name="tc6.classes" location="${tc6.home}/.settings/output"/>
+  <property name="tc6.classes" location="${tc6.home}/output/classes"/>
 
   <path id="runtime-deps" >  
     <pathelement location="${base.path}/tomcat-deps/jasper-compiler-jdt.jar" />
@@ -71,29 +71,26 @@
     <delete dir="${tc6.classes}" includes="**"/>
   </target>
   
-  <target name="tomcat-lite.jar" depends="compile,pack_tomcat-lite.jar"/>
-  
-  <target name="pack_tomcat-lite.jar" >
-    <jar destfile="tomcat-lite.jar" manifest="resources/tomcat-lite.MF">
-      <fileset dir="${sandbox.home}/classes" >
-        <include name="org/apache/commons/logging/*.class"/>
-        <include name="org/apache/tomcat/lite/**"/>
-        <include name="org/apache/tomcat/servlets/**"/>
-        <include name="org/apache/tomcat/util/buf/**"/>
-        <include name="org/apache/tomcat/util/loader/**"/>
-        <include name="org/apache/tomcat/util/net/**"/>
-      </fileset>
+  <target name="tomcat6-deps">
+    <jar destfile="resources/javax.servlet.jar" >
       <fileset dir="${tc6.classes}" >
         <include name="javax/servlet/*"/>
         <include name="javax/servlet/http/*"/>
+      </fileset>
+    </jar>
+    <jar destfile="resources/coyote-api.jar" >
+      <fileset dir="${tc6.classes}" >
         <include name="org/apache/coyote/*"/>
         <include name="org/apache/coyote/http11/Constants.class"/>
         <include name="org/apache/coyote/http11/InputFilter.class"/>
         <include name="org/apache/coyote/http11/OutputFilter.class"/>
         <include name="org/apache/coyote/http11/LocalStrings.properties"/>
         <include name="org/apache/coyote/http11/filters/**"/>
+      </fileset>
+    </jar>
+    <jar destfile="resources/tomcat-utils.jar" >
+      <fileset dir="${tc6.classes}" >
         <include name="org/apache/tomcat/util/collections/*"/>
-        <include name="org/apache/tomcat/util/http/*"/>
         <include name="org/apache/tomcat/util/http/res/LocalStrings.properties"/>
         <include name="org/apache/tomcat/util/res/**"/>
         <include name="org/apache/tomcat/util/*"/>
@@ -101,11 +98,43 @@
         <include name="org/apache/tomcat/util/*"/>
       </fileset>
     </jar>
+  </target>
+  
+  <target name="tomcat-lite.jar" depends="compile,pack_tomcat-lite.jar"/>
+  
+  <target name="pack_tomcat-lite.jar" >
+    <jar destfile="tomcat-lite.jar" manifest="resources/tomcat-lite.MF">
+      <fileset dir="${sandbox.home}/classes" >
+        <include name="org/apache/commons/logging/*.class"/>
+        <include name="org/apache/tomcat/lite/**"/>
+        <include name="org/apache/tomcat/servlets/**"/>
+        <!-- exclude name="org/apache/tomcat/servlets/deploy/**"/ -->
+        <include name="org/apache/tomcat/util/buf/**"/>
+        <include name="org/apache/tomcat/util/loader/**"/>
+        <include name="org/apache/tomcat/util/net/**"/>
+      </fileset>
+      <zipfileset src="resources/javax.servlet.jar"/>
+      <zipfileset src="resources/coyote-api.jar"/>
+      <zipfileset src="resources/tomcat-utils.jar"/>
+    </jar>
 
     <jar destfile="webapps/__x_classpath/WEB-INF/lib/jasper.jar" 
          manifest="resources/jasper.MF">
       <fileset dir="${tc6.classes}" >
-        <include name="org/apache/jasper/*"/>
+        <include name="org/apache/jasper/**"/>
+      </fileset>
+    </jar>
+    <mkdir dir="webapps/__x_deploy/WEB-INF/lib"/>
+    <jar destfile="webapps/__x_deploy/WEB-INF/lib/javax.annotation.jar" 
+         manifest="resources/deploy.MF">
+      <fileset dir="${tc6.classes}" >
+        <include name="javax/annotation/**"/>        
+      </fileset>
+    </jar>
+    <jar destfile="webapps/__x_deploy/WEB-INF/lib/deploy.jar" 
+         manifest="resources/deploy.MF">
+      <fileset dir="${sandbox.home}/classes" >
+        <include name="org/apache/tomcat/servlets/deploy/**"/>        
       </fileset>
     </jar>
     

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java Sun Sep 10 23:09:56 2006
@@ -36,7 +36,6 @@
 import java.util.Properties;
 import java.util.Set;
 import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentHashMap;
 
 import javax.servlet.Filter;
 import javax.servlet.RequestDispatcher;
@@ -49,7 +48,6 @@
 import javax.servlet.ServletContextListener;
 import javax.servlet.ServletException;
 
-import org.apache.catalina.util.RequestUtil;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.tomcat.lite.TomcatLite.ContextConfigData;
@@ -64,6 +62,7 @@
 import org.apache.tomcat.servlets.file.WebdavServlet;
 import org.apache.tomcat.servlets.session.SessionManagerServlet;
 import org.apache.tomcat.servlets.util.Enumerator;
+import org.apache.tomcat.servlets.util.RequestUtil;
 import org.apache.tomcat.servlets.util.UrlUtils;
 import org.apache.tomcat.util.loader.Repository;
 import org.apache.tomcat.util.res.StringManager;
@@ -128,7 +127,7 @@
     /**
      * The context attributes for this context.
      */
-    private transient Map attributes = new ConcurrentHashMap();
+    private transient Map attributes = new HashMap();
 
     /**
      * List of read only attributes for this context.
@@ -191,7 +190,8 @@
     void setContextPath(String path) {
         this.contextPath = path;
         mapper.contextMapElement.name = path;
-        log = LogFactory.getLog("webapp." + path.replace("/", "."));
+        
+        log = LogFactory.getLog("webapp." + path.replace('/', '.'));
     }
     
     void setBasePath(String basePath) {
@@ -980,7 +980,8 @@
         
         Repository ctxRepo = null;
         // create a class loader
-        if (getContextPath().startsWith("/__x_classpath")) {
+        if (getContextPath().startsWith("/__x_classpath") ||
+                getContextPath().startsWith("/__x_deploy")) {
             ctxRepo = getEngine().getRepository();
         } else {
             ctxRepo = new Repository();

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java Sun Sep 10 23:09:56 2006
@@ -19,7 +19,6 @@
 import javax.servlet.UnavailableException;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.catalina.util.RequestUtil;
 import org.apache.coyote.Request;
 import org.apache.coyote.Response;
 import org.apache.tomcat.lite.ctxmap.WebappContextMapper;

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java Sun Sep 10 23:09:56 2006
@@ -12,7 +12,9 @@
 import org.apache.tomcat.lite.ServletRequestImpl;
 import org.apache.tomcat.lite.ServletResponseImpl;
 import org.apache.tomcat.lite.util.MessageWriter;
+import org.apache.tomcat.util.net.http11.Endpoint;
 import org.apache.tomcat.util.net.http11.Http11Protocol;
+import org.apache.tomcat.util.net.simple.SimpleEndpoint;
 
 /** Main adapter - top mapping and adaptation.
  * 
@@ -30,12 +32,13 @@
     private TomcatLite facade;
 
     public CoyoteAdapter() {
-        proto = new Http11Protocol();
-        proto.setAdapter(this);
     }
     
     public void init() throws ServletException {
         try {
+            // let's play with the simple one for now, to debug jamvm
+            proto = new Http11Protocol(new SimpleEndpoint());
+            proto.setAdapter(this);
             ServletContextImpl ctx = (ServletContextImpl)getServletContext();
             facade = ctx.getEngine();
             proto.getEndpoint().setPort(8800);

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java Sun Sep 10 23:09:56 2006
@@ -48,7 +48,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.catalina.util.ServerInfo;
 import org.apache.tomcat.servlets.util.CopyUtils;
 import org.apache.tomcat.servlets.util.FileCopyUtils;
 import org.apache.tomcat.servlets.util.Range;

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java Sun Sep 10 23:09:56 2006
@@ -48,7 +48,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.catalina.util.ServerInfo;
 import org.apache.tomcat.servlets.util.CopyUtils;
 import org.apache.tomcat.servlets.util.URLEncoder;
 import org.apache.tomcat.util.res.StringManager;
@@ -95,7 +94,18 @@
     // Context base dir
     protected File basePath;
     protected String basePathName;
-    
+
+    public static final String TOMCAT_CSS =
+        "H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} " +
+        "H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} " +
+        "H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} " +
+        "BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} " +
+        "B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} " +
+        "P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}" +
+        "A {color : black;}" +
+        "A.name {color : black;}" +
+        "HR {color : #525D76;}";
+
     // ----------------------------------------------------- Static Initializer
 
 
@@ -331,7 +341,7 @@
         sb.append(sm.getString("directory.title", name));
         sb.append("</title>\r\n");
         sb.append("<STYLE><!--");
-        sb.append(org.apache.catalina.util.TomcatCSS.TOMCAT_CSS);
+        sb.append(TOMCAT_CSS);
         sb.append("--></STYLE> ");
         sb.append("</head>\r\n");
         sb.append("<body>");
@@ -440,7 +450,6 @@
             sb.append("<HR size=\"1\" noshade=\"noshade\">");
         }
 
-        sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
         sb.append("</body>\r\n");
         sb.append("</html>\r\n");
 

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/session/SessionManagerServlet.java Sun Sep 10 23:09:56 2006
@@ -33,7 +33,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
-import org.apache.catalina.Globals;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.tomcat.servlets.util.RandomGenerator;

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java?view=auto&rev=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java Sun Sep 10 23:09:56 2006
@@ -0,0 +1,481 @@
+/*
+ *  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.http;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.StringTokenizer;
+
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+
+/**
+ * A collection of cookies - reusable and tuned for server side performance.
+ * Based on RFC2965 ( and 2109 )
+ *
+ * This class is not synchronized.
+ *
+ * @author Costin Manolache
+ * @author kevin seguin
+ */
+public final class Cookies { // extends MultiMap {
+
+    private static org.apache.commons.logging.Log log=
+        org.apache.commons.logging.LogFactory.getLog(Cookies.class );
+    
+    // expected average number of cookies per request
+    public static final int INITIAL_SIZE=4; 
+    ServerCookie scookies[]=new ServerCookie[INITIAL_SIZE];
+    int cookieCount=0;
+    boolean unprocessed=true;
+
+    MimeHeaders headers;
+    
+    /**
+     *  Construct a new cookie collection, that will extract
+     *  the information from headers.
+     *
+     * @param headers Cookies are lazy-evaluated and will extract the
+     *     information from the provided headers.
+     */
+    public Cookies(MimeHeaders headers) {
+        this.headers=headers;
+    }
+
+    /**
+     * Construct a new uninitialized cookie collection.
+     * Use {@link #setHeaders} to initialize.
+     */
+    // [seguin] added so that an empty Cookies object could be
+    // created, have headers set, then recycled.
+    public Cookies() {
+    }
+
+    /**
+     * Set the headers from which cookies will be pulled.
+     * This has the side effect of recycling the object.
+     *
+     * @param headers Cookies are lazy-evaluated and will extract the
+     *     information from the provided headers.
+     */
+    // [seguin] added so that an empty Cookies object could be
+    // created, have headers set, then recycled.
+    public void setHeaders(MimeHeaders headers) {
+        recycle();
+        this.headers=headers;
+    }
+
+    /**
+     * Recycle.
+     */
+    public void recycle() {
+            for( int i=0; i< cookieCount; i++ ) {
+            if( scookies[i]!=null )
+                scookies[i].recycle();
+        }
+        cookieCount=0;
+        unprocessed=true;
+    }
+
+    /**
+     * EXPENSIVE!!!  only for debugging.
+     */
+    public String toString() {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        pw.println("=== Cookies ===");
+        int count = getCookieCount();
+        for (int i = 0; i < count; ++i) {
+            pw.println(getCookie(i).toString());
+        }
+        return sw.toString();
+    }
+
+    // -------------------- Indexed access --------------------
+    
+    public ServerCookie getCookie( int idx ) {
+        if( unprocessed ) {
+            getCookieCount(); // will also update the cookies
+        }
+        return scookies[idx];
+    }
+
+    public int getCookieCount() {
+        if( unprocessed ) {
+            unprocessed=false;
+            processCookies(headers);
+        }
+        return cookieCount;
+    }
+
+    // -------------------- Adding cookies --------------------
+
+    /** Register a new, unitialized cookie. Cookies are recycled, and
+     *  most of the time an existing ServerCookie object is returned.
+     *  The caller can set the name/value and attributes for the cookie
+     */
+    public ServerCookie addCookie() {
+        if( cookieCount >= scookies.length  ) {
+            ServerCookie scookiesTmp[]=new ServerCookie[2*cookieCount];
+            System.arraycopy( scookies, 0, scookiesTmp, 0, cookieCount);
+            scookies=scookiesTmp;
+        }
+        
+        ServerCookie c = scookies[cookieCount];
+        if( c==null ) {
+            c= new ServerCookie();
+            scookies[cookieCount]=c;
+        }
+        cookieCount++;
+        return c;
+    }
+
+
+    // code from CookieTools 
+
+    /** Add all Cookie found in the headers of a request.
+     */
+    public  void processCookies( MimeHeaders headers ) {
+        if( headers==null )
+            return;// nothing to process
+        // process each "cookie" header
+        int pos=0;
+        while( pos>=0 ) {
+            // Cookie2: version ? not needed
+            pos=headers.findHeader( "Cookie", pos );
+            // no more cookie headers headers
+            if( pos<0 ) break;
+
+            MessageBytes cookieValue=headers.getValue( pos );
+            if( cookieValue==null || cookieValue.isNull() ) {
+                pos++;
+                continue;
+            }
+
+            // Uncomment to test the new parsing code
+            if( cookieValue.getType() == MessageBytes.T_BYTES ) {
+                if( dbg>0 ) log( "Parsing b[]: " + cookieValue.toString());
+                ByteChunk bc=cookieValue.getByteChunk();
+                processCookieHeader( bc.getBytes(),
+                                     bc.getOffset(),
+                                     bc.getLength());
+            } else {
+                if( dbg>0 ) log( "Parsing S: " + cookieValue.toString());
+                processCookieHeader( cookieValue.toString() );
+            }
+            pos++;// search from the next position
+        }
+    }
+
+    /** 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== '\'' || cc=='"' ) {
+                startValue++;
+                endValue=indexOf( bytes, startValue, end, cc );
+                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;
+    }
+
+    public static int indexOf( byte bytes[], int off, int end, byte qq )
+    {
+        while( off < end ) {
+            byte b=bytes[off];
+            if( b==qq )
+                return off;
+            off++;
+        }
+        return off;
+    }
+
+    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;
+        if (b == null || blen != s.length()) {
+            return false;
+        }
+        int boff = start;
+        for (int i = 0; i < blen; i++) {
+            if (b[boff++] != s.charAt(i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+
+    // ---------------------------------------------------------
+    // -------------------- DEPRECATED, OLD --------------------
+    
+    private void processCookieHeader(  String cookieString )
+    {
+        if( dbg>0 ) log( "Parsing cookie header " + cookieString );
+        // normal cookie, with a string value.
+        // This is the original code, un-optimized - it shouldn't
+        // happen in normal case
+
+        StringTokenizer tok = new StringTokenizer(cookieString,
+                                                  ";", false);
+        while (tok.hasMoreTokens()) {
+            String token = tok.nextToken();
+            int i = token.indexOf("=");
+            if (i > -1) {
+                
+                // XXX
+                // the trims here are a *hack* -- this should
+                // be more properly fixed to be spec compliant
+                
+                String name = token.substring(0, i).trim();
+                String value = token.substring(i+1, token.length()).trim();
+                // RFC 2109 and bug 
+                value=stripQuote( value );
+                ServerCookie cookie = addCookie();
+                
+                cookie.getName().setString(name);
+                cookie.getValue().setString(value);
+                if( dbg > 0 ) log( "Add cookie " + name + "=" + value);
+            } else {
+                // we have a bad cookie.... just let it go
+            }
+        }
+    }
+
+    /**
+     *
+     * Strips quotes from the start and end of the cookie string
+     * This conforms to RFC 2109
+     * 
+     * @param value            a <code>String</code> specifying the cookie 
+     *                         value (possibly quoted).
+     *
+     * @see #setValue
+     *
+     */
+    private static String stripQuote( String value )
+    {
+        //        log("Strip quote from " + value );
+        if (((value.startsWith("\"")) && (value.endsWith("\""))) ||
+            ((value.startsWith("'") && (value.endsWith("'"))))) {
+            try {
+                return value.substring(1,value.length()-1);
+            } catch (Exception ex) { 
+            }
+        }
+        return value;
+    }  
+
+
+    // log
+    static final int dbg=0;
+    public void log(String s ) {
+        if (log.isDebugEnabled())
+            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 ));
+        }
+            
+    }
+    */
+
+}

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java?view=auto&rev=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java Sun Sep 10 23:09:56 2006
@@ -0,0 +1,230 @@
+/*
+ *  Copyright 1999-2006 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.http;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Utility class to generate HTTP dates.
+ * 
+ * @author Remy Maucherat
+ */
+public final class FastHttpDateFormat {
+
+
+    // -------------------------------------------------------------- Variables
+
+
+    protected static final int CACHE_SIZE = 
+        Integer.parseInt(System.getProperty("org.apache.tomcat.util.http.FastHttpDateFormat.CACHE_SIZE", "1000"));
+
+    
+    /**
+     * HTTP date format.
+     */
+    protected static final SimpleDateFormat format = 
+        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
+
+
+    /**
+     * The set of SimpleDateFormat formats to use in getDateHeader().
+     */
+    protected static final SimpleDateFormat formats[] = {
+        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
+        new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
+        new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
+    };
+
+
+    protected final static TimeZone gmtZone = TimeZone.getTimeZone("GMT");
+
+
+    /**
+     * GMT timezone - all HTTP dates are on GMT
+     */
+    static {
+
+        format.setTimeZone(gmtZone);
+
+        formats[0].setTimeZone(gmtZone);
+        formats[1].setTimeZone(gmtZone);
+        formats[2].setTimeZone(gmtZone);
+
+    }
+
+
+    /**
+     * Instant on which the currentDate object was generated.
+     */
+    protected static long currentDateGenerated = 0L;
+
+
+    /**
+     * Current formatted date.
+     */
+    protected static String currentDate = null;
+
+
+    /**
+     * Formatter cache.
+     */
+    protected static final HashMap<Long, String> formatCache = 
+        new HashMap<Long, String>(CACHE_SIZE);
+
+
+    /**
+     * Parser cache.
+     */
+    protected static final HashMap<String, Long> parseCache = 
+        new HashMap<String, Long>(CACHE_SIZE);
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Get the current date in HTTP format.
+     */
+    public static final String getCurrentDate() {
+
+        long now = System.currentTimeMillis();
+        if ((now - currentDateGenerated) > 1000) {
+            synchronized (format) {
+                if ((now - currentDateGenerated) > 1000) {
+                    currentDateGenerated = now;
+                    currentDate = format.format(new Date(now));
+                }
+            }
+        }
+        return currentDate;
+
+    }
+
+
+    /**
+     * Get the HTTP format of the specified date.
+     */
+    public static final String formatDate
+        (long value, DateFormat threadLocalformat) {
+
+        Long longValue = new Long(value);
+        String cachedDate = formatCache.get(longValue);
+        if (cachedDate != null)
+            return cachedDate;
+
+        String newDate = null;
+        Date dateValue = new Date(value);
+        if (threadLocalformat != null) {
+            newDate = threadLocalformat.format(dateValue);
+            updateFormatCache(longValue, newDate);
+        } else {
+            synchronized (formatCache) {
+                synchronized (format) {
+                    newDate = format.format(dateValue);
+                }
+                updateFormatCache(longValue, newDate);
+            }
+        }
+        return newDate;
+
+    }
+
+
+    /**
+     * Try to parse the given date as a HTTP date.
+     */
+    public static final long parseDate(String value, 
+                                       DateFormat[] threadLocalformats) {
+
+        Long cachedDate = parseCache.get(value);
+        if (cachedDate != null)
+            return cachedDate.longValue();
+
+        Long date = null;
+        if (threadLocalformats != null) {
+            date = internalParseDate(value, threadLocalformats);
+            updateParseCache(value, date);
+        } else {
+            synchronized (parseCache) {
+                date = internalParseDate(value, formats);
+                updateParseCache(value, date);
+            }
+        }
+        if (date == null) {
+            return (-1L);
+        } else {
+            return date.longValue();
+        }
+
+    }
+
+
+    /**
+     * Parse date with given formatters.
+     */
+    private static final Long internalParseDate
+        (String value, DateFormat[] formats) {
+        Date date = null;
+        for (int i = 0; (date == null) && (i < formats.length); i++) {
+            try {
+                date = formats[i].parse(value);
+            } catch (ParseException e) {
+                ;
+            }
+        }
+        if (date == null) {
+            return null;
+        }
+        return new Long(date.getTime());
+    }
+
+
+    /**
+     * Update cache.
+     */
+    private static void updateFormatCache(Long key, String value) {
+        if (value == null) {
+            return;
+        }
+        if (formatCache.size() > CACHE_SIZE) {
+            formatCache.clear();
+        }
+        formatCache.put(key, value);
+    }
+
+
+    /**
+     * Update cache.
+     */
+    private static void updateParseCache(String key, Long value) {
+        if (value == null) {
+            return;
+        }
+        if (parseCache.size() > CACHE_SIZE) {
+            parseCache.clear();
+        }
+        parseCache.put(key, value);
+    }
+
+
+}

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/HttpMessages.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/HttpMessages.java?view=auto&rev=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/HttpMessages.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/HttpMessages.java Sun Sep 10 23:09:56 2006
@@ -0,0 +1,106 @@
+/*
+ *  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.http;
+
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * Handle (internationalized) HTTP messages.
+ * 
+ * @author James Duncan Davidson [duncan@eng.sun.com]
+ * @author James Todd [gonzo@eng.sun.com]
+ * @author Jason Hunter [jch@eng.sun.com]
+ * @author Harish Prabandham
+ * @author costin@eng.sun.com
+ */
+public class HttpMessages {
+    // XXX move message resources in this package
+    protected static StringManager sm =
+        StringManager.getManager("org.apache.tomcat.util.http");
+	
+    static String st_200=null;
+    static String st_302=null;
+    static String st_400=null;
+    static String st_404=null;
+    
+    /** Get the status string associated with a status code.
+     *  No I18N - return the messages defined in the HTTP spec.
+     *  ( the user isn't supposed to see them, this is the last
+     *  thing to translate)
+     *
+     *  Common messages are cached.
+     *
+     */
+    public static String getMessage( int status ) {
+	// method from Response.
+	
+	// Does HTTP requires/allow international messages or
+	// are pre-defined? The user doesn't see them most of the time
+	switch( status ) {
+	case 200:
+	    if( st_200==null ) st_200=sm.getString( "sc.200");
+	    return st_200;
+	case 302:
+	    if( st_302==null ) st_302=sm.getString( "sc.302");
+	    return st_302;
+	case 400:
+	    if( st_400==null ) st_400=sm.getString( "sc.400");
+	    return st_400;
+	case 404:
+	    if( st_404==null ) st_404=sm.getString( "sc.404");
+	    return st_404;
+	}
+	return sm.getString("sc."+ status);
+    }
+
+    /**
+     * Filter the specified message string for characters that are sensitive
+     * in HTML.  This avoids potential attacks caused by including JavaScript
+     * codes in the request URL that is often reported in error messages.
+     *
+     * @param message The message string to be filtered
+     */
+    public static String filter(String message) {
+
+	if (message == null)
+	    return (null);
+
+	char content[] = new char[message.length()];
+	message.getChars(0, message.length(), content, 0);
+	StringBuffer result = new StringBuffer(content.length + 50);
+	for (int i = 0; i < content.length; i++) {
+	    switch (content[i]) {
+	    case '<':
+		result.append("&lt;");
+		break;
+	    case '>':
+		result.append("&gt;");
+		break;
+	    case '&':
+		result.append("&amp;");
+		break;
+	    case '"':
+		result.append("&quot;");
+		break;
+	    default:
+		result.append(content[i]);
+	    }
+	}
+	return (result.toString());
+    }
+
+}

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocalStrings.properties?view=auto&rev=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocalStrings.properties (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocalStrings.properties Sun Sep 10 23:09:56 2006
@@ -0,0 +1,46 @@
+# HttpMessages
+sc.100=Continue
+sc.101=Switching Protocols
+sc.200=OK
+sc.201=Created
+sc.202=Accepted
+sc.203=Non-Authoritative Information
+sc.204=No Content
+sc.205=Reset Content
+sc.206=Partial Content
+sc.207=Multi-Status
+sc.300=Multiple Choices
+sc.301=Moved Permanently
+sc.302=Moved Temporarily
+sc.303=See Other
+sc.304=Not Modified
+sc.305=Use Proxy
+sc.307=Temporary Redirect
+sc.400=Bad Request
+sc.401=Unauthorized
+sc.402=Payment Required
+sc.403=Forbidden
+sc.404=Not Found
+sc.405=Method Not Allowed
+sc.406=Not Acceptable
+sc.407=Proxy Authentication Required
+sc.408=Request Timeout
+sc.409=Conflict
+sc.410=Gone
+sc.411=Length Required
+sc.412=Precondition Failed
+sc.413=Request Entity Too Large
+sc.414=Request-URI Too Long
+sc.415=Unsupported Media Type
+sc.416=Requested Range Not Satisfiable
+sc.417=Expectation Failed
+sc.422=Unprocessable Entity
+sc.423=Locked
+sc.424=Failed Dependency
+sc.500=Internal Server Error
+sc.501=Not Implemented
+sc.502=Bad Gateway
+sc.503=Service Unavailable
+sc.504=Gateway Timeout
+sc.505=HTTP Version Not Supported
+sc.507=Insufficient Storage

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MimeHeaders.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MimeHeaders.java?view=auto&rev=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MimeHeaders.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MimeHeaders.java Sun Sep 10 23:09:56 2006
@@ -0,0 +1,456 @@
+/*
+ *  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.http;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Enumeration;
+
+import org.apache.tomcat.util.buf.MessageBytes;
+
+/* XXX XXX XXX Need a major rewrite  !!!!
+ */
+
+/**
+ * This class is used to contain standard internet message headers,
+ * used for SMTP (RFC822) and HTTP (RFC2068) messages as well as for
+ * MIME (RFC 2045) applications such as transferring typed data and
+ * grouping related items in multipart message bodies.
+ *
+ * <P> Message headers, as specified in RFC822, include a field name
+ * and a field body.  Order has no semantic significance, and several
+ * fields with the same name may exist.  However, most fields do not
+ * (and should not) exist more than once in a header.
+ *
+ * <P> Many kinds of field body must conform to a specified syntax,
+ * including the standard parenthesized comment syntax.  This class
+ * supports only two simple syntaxes, for dates and integers.
+ *
+ * <P> When processing headers, care must be taken to handle the case of
+ * multiple same-name fields correctly.  The values of such fields are
+ * only available as strings.  They may be accessed by index (treating
+ * the header as an array of fields), or by name (returning an array
+ * of string values).
+ */
+
+/* Headers are first parsed and stored in the order they are
+   received. This is based on the fact that most servlets will not
+   directly access all headers, and most headers are single-valued.
+   ( the alternative - a hash or similar data structure - will add
+   an overhead that is not needed in most cases )
+   
+   Apache seems to be using a similar method for storing and manipulating
+   headers.
+       
+   Future enhancements:
+   - hash the headers the first time a header is requested ( i.e. if the
+   servlet needs direct access to headers).
+   - scan "common" values ( length, cookies, etc ) during the parse
+   ( addHeader hook )
+   
+*/
+    
+
+
+/**
+ *  Memory-efficient repository for Mime Headers. When the object is recycled, it
+ *  will keep the allocated headers[] and all the MimeHeaderField - no GC is generated.
+ *
+ *  For input headers it is possible to use the MessageByte for Fileds - so no GC
+ *  will be generated.
+ *
+ *  The only garbage is generated when using the String for header names/values -
+ *  this can't be avoided when the servlet calls header methods, but is easy
+ *  to avoid inside tomcat. The goal is to use _only_ MessageByte-based Fields,
+ *  and reduce to 0 the memory overhead of tomcat.
+ *
+ *  TODO:
+ *  XXX one-buffer parsing - for http ( other protocols don't need that )
+ *  XXX remove unused methods
+ *  XXX External enumerations, with 0 GC.
+ *  XXX use HeaderName ID
+ *  
+ * 
+ * @author dac@eng.sun.com
+ * @author James Todd [gonzo@eng.sun.com]
+ * @author Costin Manolache
+ * @author kevin seguin
+ */
+public class MimeHeaders {
+    /** Initial size - should be == average number of headers per request
+     *  XXX  make it configurable ( fine-tuning of web-apps )
+     */
+    public static final int DEFAULT_HEADER_SIZE=8;
+    
+    /**
+     * The header fields.
+     */
+    private MimeHeaderField[] headers = new
+	MimeHeaderField[DEFAULT_HEADER_SIZE];
+
+    /**
+     * The current number of header fields.
+     */
+    private int count;
+
+    /**
+     * Creates a new MimeHeaders object using a default buffer size.
+     */
+    public MimeHeaders() {
+    }
+
+    /**
+     * Clears all header fields.
+     */
+    // [seguin] added for consistency -- most other objects have recycle().
+    public void recycle() {
+        clear();
+    }
+
+    /**
+     * Clears all header fields.
+     */
+    public void clear() {
+	for (int i = 0; i < count; i++) {
+	    headers[i].recycle();
+	}
+	count = 0;
+    }
+
+    /**
+     * EXPENSIVE!!!  only for debugging.
+     */
+    public String toString() {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        pw.println("=== MimeHeaders ===");
+        Enumeration e = names();
+        while (e.hasMoreElements()) {
+            String n = (String)e.nextElement();
+            pw.println(n + " = " + getHeader(n));
+        }
+        return sw.toString();
+    }
+
+    // -------------------- Idx access to headers ----------
+    
+    /**
+     * Returns the current number of header fields.
+     */
+    public int size() {
+	return count;
+    }
+
+    /**
+     * Returns the Nth header name, or null if there is no such header.
+     * This may be used to iterate through all header fields.
+     */
+    public MessageBytes getName(int n) {
+	return n >= 0 && n < count ? headers[n].getName() : null;
+    }
+
+    /**
+     * Returns the Nth header value, or null if there is no such header.
+     * This may be used to iterate through all header fields.
+     */
+    public MessageBytes getValue(int n) {
+	return n >= 0 && n < count ? headers[n].getValue() : null;
+    }
+
+    /** Find the index of a header with the given name.
+     */
+    public int findHeader( String name, int starting ) {
+	// We can use a hash - but it's not clear how much
+	// benefit you can get - there is an  overhead 
+	// and the number of headers is small (4-5 ?)
+	// Another problem is that we'll pay the overhead
+	// of constructing the hashtable
+
+	// A custom search tree may be better
+        for (int i = starting; i < count; i++) {
+	    if (headers[i].getName().equalsIgnoreCase(name)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+    
+    // -------------------- --------------------
+
+    /**
+     * Returns an enumeration of strings representing the header field names.
+     * Field names may appear multiple times in this enumeration, indicating
+     * that multiple fields with that name exist in this header.
+     */
+    public Enumeration names() {
+	return new NamesEnumerator(this);
+    }
+
+    public Enumeration values(String name) {
+	return new ValuesEnumerator(this, name);
+    }
+
+    // -------------------- Adding headers --------------------
+    
+
+    /**
+     * Adds a partially constructed field to the header.  This
+     * field has not had its name or value initialized.
+     */
+    private MimeHeaderField createHeader() {
+	MimeHeaderField mh;
+	int len = headers.length;
+	if (count >= len) {
+	    // expand header list array
+	    MimeHeaderField tmp[] = new MimeHeaderField[count * 2];
+	    System.arraycopy(headers, 0, tmp, 0, len);
+	    headers = tmp;
+	}
+	if ((mh = headers[count]) == null) {
+	    headers[count] = mh = new MimeHeaderField();
+	}
+	count++;
+	return mh;
+    }
+
+    /** Create a new named header , return the MessageBytes
+	container for the new value
+    */
+    public MessageBytes addValue( String name ) {
+ 	MimeHeaderField mh = createHeader();
+	mh.getName().setString(name);
+	return mh.getValue();
+    }
+
+    /** Create a new named header using un-translated byte[].
+	The conversion to chars can be delayed until
+	encoding is known.
+     */
+    public MessageBytes addValue(byte b[], int startN, int len)
+    {
+	MimeHeaderField mhf=createHeader();
+	mhf.getName().setBytes(b, startN, len);
+	return mhf.getValue();
+    }
+
+    /** Create a new named header using translated char[].
+     */
+    public MessageBytes addValue(char c[], int startN, int len)
+    {
+	MimeHeaderField mhf=createHeader();
+	mhf.getName().setChars(c, startN, len);
+	return mhf.getValue();
+    }
+
+    /** Allow "set" operations - 
+        return a MessageBytes container for the
+	header value ( existing header or new
+	if this .
+    */
+    public MessageBytes setValue( String name ) {
+        for ( int i = 0; i < count; i++ ) {
+            if(headers[i].getName().equalsIgnoreCase(name)) {
+                for ( int j=i+1; j < count; j++ ) {
+                    if(headers[j].getName().equalsIgnoreCase(name)) {
+                        removeHeader(j--);
+                    }
+                }
+                return headers[i].getValue();
+            }
+        }
+        MimeHeaderField mh = createHeader();
+        mh.getName().setString(name);
+        return mh.getValue();
+    }
+
+    //-------------------- Getting headers --------------------
+    /**
+     * Finds and returns a header field with the given name.  If no such
+     * field exists, null is returned.  If more than one such field is
+     * in the header, an arbitrary one is returned.
+     */
+    public MessageBytes getValue(String name) {
+        for (int i = 0; i < count; i++) {
+	    if (headers[i].getName().equalsIgnoreCase(name)) {
+                return headers[i].getValue();
+            }
+        }
+        return null;
+    }
+
+    // bad shortcut - it'll convert to string ( too early probably,
+    // encoding is guessed very late )
+    public String getHeader(String name) {
+	MessageBytes mh = getValue(name);
+	return mh != null ? mh.toString() : null;
+    }
+
+    // -------------------- Removing --------------------
+    /**
+     * Removes a header field with the specified name.  Does nothing
+     * if such a field could not be found.
+     * @param name the name of the header field to be removed
+     */
+    public void removeHeader(String name) {
+        // XXX
+        // warning: rather sticky code; heavily tuned
+
+        for (int i = 0; i < count; i++) {
+            if (headers[i].getName().equalsIgnoreCase(name)) {
+                removeHeader(i--);
+            }
+        }
+    }
+
+    /**
+     * reset and swap with last header
+     * @param idx the index of the header to remove.
+     */
+    private void removeHeader(int idx) {
+        MimeHeaderField mh = headers[idx];
+        
+        mh.recycle();
+        headers[idx] = headers[count - 1];
+        headers[count - 1] = mh;
+        count--;
+    }
+
+}
+
+/** Enumerate the distinct header names.
+    Each nextElement() is O(n) ( a comparation is
+    done with all previous elements ).
+
+    This is less frequesnt than add() -
+    we want to keep add O(1).
+*/
+class NamesEnumerator implements Enumeration {
+    int pos;
+    int size;
+    String next;
+    MimeHeaders headers;
+
+    NamesEnumerator(MimeHeaders headers) {
+	this.headers=headers;
+	pos=0;
+	size = headers.size();
+	findNext();
+    }
+
+    private void findNext() {
+	next=null;
+	for(  ; pos< size; pos++ ) {
+	    next=headers.getName( pos ).toString();
+	    for( int j=0; j<pos ; j++ ) {
+		if( headers.getName( j ).equalsIgnoreCase( next )) {
+		    // duplicate.
+		    next=null;
+		    break;
+		}
+	    }
+	    if( next!=null ) {
+		// it's not a duplicate
+		break;
+	    }
+	}
+	// next time findNext is called it will try the
+	// next element
+	pos++;
+    }
+    
+    public boolean hasMoreElements() {
+	return next!=null;
+    }
+
+    public Object nextElement() {
+	String current=next;
+	findNext();
+	return current;
+    }
+}
+
+/** Enumerate the values for a (possibly ) multiple
+    value element.
+*/
+class ValuesEnumerator implements Enumeration {
+    int pos;
+    int size;
+    MessageBytes next;
+    MimeHeaders headers;
+    String name;
+
+    ValuesEnumerator(MimeHeaders headers, String name) {
+        this.name=name;
+	this.headers=headers;
+	pos=0;
+	size = headers.size();
+	findNext();
+    }
+
+    private void findNext() {
+	next=null;
+	for( ; pos< size; pos++ ) {
+	    MessageBytes n1=headers.getName( pos );
+	    if( n1.equalsIgnoreCase( name )) {
+		next=headers.getValue( pos );
+		break;
+	    }
+	}
+	pos++;
+    }
+    
+    public boolean hasMoreElements() {
+	return next!=null;
+    }
+
+    public Object nextElement() {
+	MessageBytes current=next;
+	findNext();
+	return current.toString();
+    }
+}
+
+class MimeHeaderField {
+    // multiple headers with same name - a linked list will
+    // speed up name enumerations and search ( both cpu and
+    // GC)
+    MimeHeaderField next;
+    MimeHeaderField prev; 
+    
+    protected final MessageBytes nameB = MessageBytes.newInstance();
+    protected final MessageBytes valueB = MessageBytes.newInstance();
+
+    /**
+     * Creates a new, uninitialized header field.
+     */
+    public MimeHeaderField() {
+    }
+
+    public void recycle() {
+	nameB.recycle();
+	valueB.recycle();
+	next=null;
+    }
+
+    public MessageBytes getName() {
+	return nameB;
+    }
+
+    public MessageBytes getValue() {
+	return valueB;
+    }
+}

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Parameters.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Parameters.java?view=auto&rev=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Parameters.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Parameters.java Sun Sep 10 23:09:56 2006
@@ -0,0 +1,611 @@
+/*
+ *  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.http;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.buf.UDecoder;
+import org.apache.tomcat.util.collections.MultiMap;
+
+/**
+ * 
+ * @author Costin Manolache
+ */
+public final class Parameters extends MultiMap {
+
+    
+    private static org.apache.commons.logging.Log log=
+        org.apache.commons.logging.LogFactory.getLog(Parameters.class );
+    
+    // Transition: we'll use the same Hashtable( String->String[] )
+    // for the beginning. When we are sure all accesses happen through
+    // this class - we can switch to MultiMap
+    private Hashtable paramHashStringArray=new Hashtable();
+    private boolean didQueryParameters=false;
+    private boolean didMerge=false;
+    
+    MessageBytes queryMB;
+    MimeHeaders  headers;
+
+    UDecoder urlDec;
+    MessageBytes decodedQuery=MessageBytes.newInstance();
+    
+    public static final int INITIAL_SIZE=4;
+
+    // Garbage-less parameter merging.
+    // In a sub-request with parameters, the new parameters
+    // will be stored in child. When a getParameter happens,
+    // the 2 are merged togheter. The child will be altered
+    // to contain the merged values - the parent is allways the
+    // original request.
+    private Parameters child=null;
+    private Parameters parent=null;
+    private Parameters currentChild=null;
+
+    String encoding=null;
+    String queryStringEncoding=null;
+    
+    /**
+     * 
+     */
+    public Parameters() {
+	super( INITIAL_SIZE );
+    }
+
+    public void setQuery( MessageBytes queryMB ) {
+	this.queryMB=queryMB;
+    }
+
+    public void setHeaders( MimeHeaders headers ) {
+	this.headers=headers;
+    }
+
+    public void setEncoding( String s ) {
+	encoding=s;
+	if(debug>0) log( "Set encoding to " + s );
+    }
+
+    public void setQueryStringEncoding( String s ) {
+	queryStringEncoding=s;
+	if(debug>0) log( "Set query string encoding to " + s );
+    }
+
+    public void recycle() {
+	super.recycle();
+	paramHashStringArray.clear();
+	didQueryParameters=false;
+	currentChild=null;
+	didMerge=false;
+	encoding=null;
+	decodedQuery.recycle();
+    }
+    
+    // -------------------- Sub-request support --------------------
+
+    public Parameters getCurrentSet() {
+	if( currentChild==null )
+	    return this;
+	return currentChild;
+    }
+    
+    /** Create ( or reuse ) a child that will be used during a sub-request.
+	All future changes ( setting query string, adding parameters )
+	will affect the child ( the parent request is never changed ).
+	Both setters and getters will return the data from the deepest
+	child, merged with data from parents.
+    */
+    public void push() {
+	// We maintain a linked list, that will grow to the size of the
+	// longest include chain.
+	// The list has 2 points of interest:
+	// - request.parameters() is the original request and head,
+	// - request.parameters().currentChild() is the current set.
+	// The ->child and parent<- links are preserved ( currentChild is not
+	// the last in the list )
+	
+	// create a new element in the linked list
+	// note that we reuse the child, if any - pop will not
+	// set child to null !
+	if( currentChild==null ) {
+	    currentChild=new Parameters();
+	    currentChild.setURLDecoder( urlDec );
+	    currentChild.parent=this;
+	    return;
+	}
+	if( currentChild.child==null ) {
+	    currentChild.child=new Parameters();
+	    currentChild.setURLDecoder( urlDec );
+	    currentChild.child.parent=currentChild;
+	} // it is not null if this object already had a child
+	// i.e. a deeper include() ( we keep it )
+
+	// the head will be the new element.
+	currentChild=currentChild.child;
+	currentChild.setEncoding( encoding );
+    }
+
+    /** Discard the last child. This happens when we return from a
+	sub-request and the parameters are locally modified.
+     */
+    public void pop() {
+	if( currentChild==null ) {
+	    throw new RuntimeException( "Attempt to pop without a push" );
+	}
+	currentChild.recycle();
+	currentChild=currentChild.parent;
+	// don't remove the top.
+    }
+    
+    // -------------------- Data access --------------------
+    // Access to the current name/values, no side effect ( processing ).
+    // You must explicitely call handleQueryParameters and the post methods.
+    
+    // This is the original data representation ( hash of String->String[])
+
+    public void addParameterValues( String key, String[] newValues) {
+        if ( key==null ) return;
+        String values[];
+        if (paramHashStringArray.containsKey(key)) {
+            String oldValues[] = (String[])paramHashStringArray.get(key);
+            values = new String[oldValues.length + newValues.length];
+            for (int i = 0; i < oldValues.length; i++) {
+                values[i] = oldValues[i];
+            }
+            for (int i = 0; i < newValues.length; i++) {
+                values[i+ oldValues.length] = newValues[i];
+            }
+        } else {
+            values = newValues;
+        }
+
+        paramHashStringArray.put(key, values);
+    }
+
+    public String[] getParameterValues(String name) {
+	handleQueryParameters();
+	// sub-request
+	if( currentChild!=null ) {
+	    currentChild.merge();
+	    return (String[])currentChild.paramHashStringArray.get(name);
+	}
+
+	// no "facade"
+	String values[]=(String[])paramHashStringArray.get(name);
+	return values;
+    }
+ 
+    public Enumeration getParameterNames() {
+	handleQueryParameters();
+	// Slow - the original code
+	if( currentChild!=null ) {
+	    currentChild.merge();
+	    return currentChild.paramHashStringArray.keys();
+	}
+
+	// merge in child
+        return paramHashStringArray.keys();
+    }
+
+    /** Combine the parameters from parent with our local ones
+     */
+    private void merge() {
+	// recursive
+	if( debug > 0 ) {
+	    log("Before merging " + this + " " + parent + " " + didMerge );
+	    log(  paramsAsString());
+	}
+	// Local parameters first - they take precedence as in spec.
+	handleQueryParameters();
+
+	// we already merged with the parent
+	if( didMerge ) return;
+
+	// we are the top level
+	if( parent==null ) return;
+
+	// Add the parent props to the child ( lower precedence )
+	parent.merge();
+	Hashtable parentProps=parent.paramHashStringArray;
+	merge2( paramHashStringArray , parentProps);
+	didMerge=true;
+	if(debug > 0 )
+	    log("After " + paramsAsString());
+    }
+
+
+    // Shortcut.
+    public String getParameter(String name ) {
+	String[] values = getParameterValues(name);
+        if (values != null) {
+	    if( values.length==0 ) return "";
+            return values[0];
+        } else {
+	    return null;
+        }
+    }
+    // -------------------- Processing --------------------
+    /** Process the query string into parameters
+     */
+    public void handleQueryParameters() {
+	if( didQueryParameters ) return;
+
+	didQueryParameters=true;
+
+	if( queryMB==null || queryMB.isNull() )
+	    return;
+	
+	if( debug > 0  )
+	    log( "Decoding query " + decodedQuery + " " + queryStringEncoding);
+
+        try {
+            decodedQuery.duplicate( queryMB );
+        } catch (IOException e) {
+            // Can't happen, as decodedQuery can't overflow
+            e.printStackTrace();
+        }
+        processParameters( decodedQuery, queryStringEncoding );
+    }
+
+    // --------------------
+    
+    /** Combine 2 hashtables into a new one.
+     *  ( two will be added to one ).
+     *  Used to combine child parameters ( RequestDispatcher's query )
+     *  with parent parameters ( original query or parent dispatcher )
+     */
+    private static void merge2(Hashtable one, Hashtable two ) {
+        Enumeration e = two.keys();
+
+	while (e.hasMoreElements()) {
+	    String name = (String) e.nextElement();
+	    String[] oneValue = (String[]) one.get(name);
+	    String[] twoValue = (String[]) two.get(name);
+	    String[] combinedValue;
+
+	    if (twoValue == null) {
+		continue;
+	    } else {
+		if( oneValue==null ) {
+		    combinedValue = new String[twoValue.length];
+		    System.arraycopy(twoValue, 0, combinedValue,
+				     0, twoValue.length);
+		} else {
+		    combinedValue = new String[oneValue.length +
+					       twoValue.length];
+		    System.arraycopy(oneValue, 0, combinedValue, 0,
+				     oneValue.length);
+		    System.arraycopy(twoValue, 0, combinedValue,
+				     oneValue.length, twoValue.length);
+		}
+		one.put(name, combinedValue);
+	    }
+	}
+    }
+
+    // incredibly inefficient data representation for parameters,
+    // until we test the new one
+    private void addParam( String key, String value ) {
+	if( key==null ) return;
+	String values[];
+	if (paramHashStringArray.containsKey(key)) {
+	    String oldValues[] = (String[])paramHashStringArray.
+		get(key);
+	    values = new String[oldValues.length + 1];
+	    for (int i = 0; i < oldValues.length; i++) {
+		values[i] = oldValues[i];
+	    }
+	    values[oldValues.length] = value;
+	} else {
+	    values = new String[1];
+	    values[0] = value;
+	}
+	
+	
+	paramHashStringArray.put(key, values);
+    }
+
+    public void setURLDecoder( UDecoder u ) {
+	urlDec=u;
+    }
+
+    // -------------------- Parameter parsing --------------------
+
+    // This code is not used right now - it's the optimized version
+    // of the above.
+
+    // we are called from a single thread - we can do it the hard way
+    // if needed
+    ByteChunk tmpName=new ByteChunk();
+    ByteChunk tmpValue=new ByteChunk();
+    CharChunk tmpNameC=new CharChunk(1024);
+    CharChunk tmpValueC=new CharChunk(1024);
+    
+    public void processParameters( byte bytes[], int start, int len ) {
+        processParameters(bytes, start, len, encoding);
+    }
+
+    public void processParameters( byte bytes[], int start, int len, 
+                                   String enc ) {
+	int end=start+len;
+	int pos=start;
+	
+	if( debug>0 ) 
+	    log( "Bytes: " + new String( bytes, start, len ));
+
+        do {
+	    boolean noEq=false;
+	    int valStart=-1;
+	    int valEnd=-1;
+	    
+	    int nameStart=pos;
+	    int nameEnd=ByteChunk.indexOf(bytes, nameStart, end, '=' );
+	    // Workaround for a&b&c encoding
+	    int nameEnd2=ByteChunk.indexOf(bytes, nameStart, end, '&' );
+	    if( (nameEnd2!=-1 ) &&
+		( nameEnd==-1 || nameEnd > nameEnd2) ) {
+		nameEnd=nameEnd2;
+		noEq=true;
+		valStart=nameEnd;
+		valEnd=nameEnd;
+		if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + new String(bytes, nameStart, nameEnd-nameStart) );
+	    }
+	    if( nameEnd== -1 ) 
+		nameEnd=end;
+
+	    if( ! noEq ) {
+		valStart= (nameEnd < end) ? nameEnd+1 : end;
+		valEnd=ByteChunk.indexOf(bytes, valStart, end, '&');
+		if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
+	    }
+	    
+	    pos=valEnd+1;
+	    
+	    if( nameEnd<=nameStart ) {
+		continue;
+		// invalid chunk - it's better to ignore
+		// XXX log it ?
+	    }
+	    tmpName.setBytes( bytes, nameStart, nameEnd-nameStart );
+	    tmpValue.setBytes( bytes, valStart, valEnd-valStart );
+
+            try {
+                addParam( urlDecode(tmpName, enc), urlDecode(tmpValue, enc) );
+            } catch (IOException e) {
+                // Exception during character decoding: skip parameter
+            }
+
+	    tmpName.recycle();
+	    tmpValue.recycle();
+
+	} while( pos<end );
+    }
+
+    private String urlDecode(ByteChunk bc, String enc)
+        throws IOException {
+        if( urlDec==null ) {
+            urlDec=new UDecoder();   
+        }
+        urlDec.convert(bc);
+        String result = null;
+        if (enc != null) {
+            bc.setEncoding(enc);
+            result = bc.toString();
+        } else {
+            CharChunk cc = tmpNameC;
+            cc.allocate(bc.getLength(), -1);
+            // Default encoding: fast conversion
+            byte[] bbuf = bc.getBuffer();
+            char[] cbuf = cc.getBuffer();
+            int start = bc.getStart();
+            for (int i = 0; i < bc.getLength(); i++) {
+                cbuf[i] = (char) (bbuf[i + start] & 0xff);
+            }
+            cc.setChars(cbuf, 0, bc.getLength());
+            result = cc.toString();
+            cc.recycle();
+        }
+        return result;
+    }
+
+    public void processParameters( char chars[], int start, int len ) {
+	int end=start+len;
+	int pos=start;
+	
+	if( debug>0 ) 
+	    log( "Chars: " + new String( chars, start, len ));
+        do {
+	    boolean noEq=false;
+	    int nameStart=pos;
+	    int valStart=-1;
+	    int valEnd=-1;
+	    
+	    int nameEnd=CharChunk.indexOf(chars, nameStart, end, '=' );
+	    int nameEnd2=CharChunk.indexOf(chars, nameStart, end, '&' );
+	    if( (nameEnd2!=-1 ) &&
+		( nameEnd==-1 || nameEnd > nameEnd2) ) {
+		nameEnd=nameEnd2;
+		noEq=true;
+		valStart=nameEnd;
+		valEnd=nameEnd;
+		if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + new String(chars, nameStart, nameEnd-nameStart) );
+	    }
+	    if( nameEnd== -1 ) nameEnd=end;
+	    
+	    if( ! noEq ) {
+		valStart= (nameEnd < end) ? nameEnd+1 : end;
+		valEnd=CharChunk.indexOf(chars, valStart, end, '&');
+		if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
+	    }
+	    
+	    pos=valEnd+1;
+	    
+	    if( nameEnd<=nameStart ) {
+		continue;
+		// invalid chunk - no name, it's better to ignore
+		// XXX log it ?
+	    }
+	    
+	    try {
+		tmpNameC.append( chars, nameStart, nameEnd-nameStart );
+		tmpValueC.append( chars, valStart, valEnd-valStart );
+
+		if( debug > 0 )
+		    log( tmpNameC + "= " + tmpValueC);
+
+		if( urlDec==null ) {
+		    urlDec=new UDecoder();   
+		}
+
+		urlDec.convert( tmpNameC );
+		urlDec.convert( tmpValueC );
+
+		if( debug > 0 )
+		    log( tmpNameC + "= " + tmpValueC);
+		
+		addParam( tmpNameC.toString(), tmpValueC.toString() );
+	    } catch( IOException ex ) {
+		ex.printStackTrace();
+	    }
+
+	    tmpNameC.recycle();
+	    tmpValueC.recycle();
+
+	} while( pos<end );
+    }
+    
+    public void processParameters( MessageBytes data ) {
+        processParameters(data, encoding);
+    }
+
+    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());
+	}
+    }
+
+    /** Debug purpose
+     */
+    public String paramsAsString() {
+	StringBuffer sb=new StringBuffer();
+	Enumeration en= paramHashStringArray.keys();
+	while( en.hasMoreElements() ) {
+	    String k=(String)en.nextElement();
+	    sb.append( k ).append("=");
+	    String v[]=(String[])paramHashStringArray.get( k );
+	    for( int i=0; i<v.length; i++ )
+		sb.append( v[i] ).append(",");
+	    sb.append("\n");
+	}
+	return sb.toString();
+    }
+
+    private static int debug=0;
+    private void log(String s ) {
+        if (log.isDebugEnabled())
+            log.debug("Parameters: " + s );
+    }
+   
+    // -------------------- Old code, needs rewrite --------------------
+    
+    /** Used by RequestDispatcher
+     */
+    public void processParameters( String str ) {
+	int end=str.length();
+	int pos=0;
+	if( debug > 0)
+	    log("String: " + str );
+	
+        do {
+	    boolean noEq=false;
+	    int valStart=-1;
+	    int valEnd=-1;
+	    
+	    int nameStart=pos;
+	    int nameEnd=str.indexOf('=', nameStart );
+	    int nameEnd2=str.indexOf('&', nameStart );
+	    if( nameEnd2== -1 ) nameEnd2=end;
+	    if( (nameEnd2!=-1 ) &&
+		( nameEnd==-1 || nameEnd > nameEnd2) ) {
+		nameEnd=nameEnd2;
+		noEq=true;
+		valStart=nameEnd;
+		valEnd=nameEnd;
+		if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + str.substring(nameStart, nameEnd) );
+	    }
+
+	    if( nameEnd== -1 ) nameEnd=end;
+
+	    if( ! noEq ) {
+		valStart=nameEnd+1;
+		valEnd=str.indexOf('&', valStart);
+		if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
+	    }
+	    
+	    pos=valEnd+1;
+	    
+	    if( nameEnd<=nameStart ) {
+		continue;
+	    }
+	    if( debug>0)
+		log( "XXX " + nameStart + " " + nameEnd + " "
+		     + valStart + " " + valEnd );
+	    
+	    try {
+		tmpNameC.append(str, nameStart, nameEnd-nameStart );
+		tmpValueC.append(str, valStart, valEnd-valStart );
+	    
+		if( debug > 0 )
+		    log( tmpNameC + "= " + tmpValueC);
+
+		if( urlDec==null ) {
+		    urlDec=new UDecoder();   
+		}
+
+		urlDec.convert( tmpNameC );
+		urlDec.convert( tmpValueC );
+
+		if( debug > 0 )
+		    log( tmpNameC + "= " + tmpValueC);
+		
+		addParam( tmpNameC.toString(), tmpValueC.toString() );
+	    } catch( IOException ex ) {
+		ex.printStackTrace();
+	    }
+
+	    tmpNameC.recycle();
+	    tmpValueC.recycle();
+
+	} while( pos<end );
+    }
+
+
+}

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ServerCookie.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ServerCookie.java?view=auto&rev=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ServerCookie.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ServerCookie.java Sun Sep 10 23:09:56 2006
@@ -0,0 +1,320 @@
+/*
+ *  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.http;
+
+import java.io.Serializable;
+import java.text.FieldPosition;
+import java.util.Date;
+
+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
+ *  representation ( and thus the byte-> char conversion can be delayed
+ *  until we know the charset ).
+ *
+ *  Tomcat.core uses this recyclable object to represent cookies,
+ *  and the facade will convert it to the external representation.
+ */
+public class ServerCookie implements Serializable {
+    
+    
+    private static org.apache.commons.logging.Log log=
+        org.apache.commons.logging.LogFactory.getLog(ServerCookie.class );
+    
+    private MessageBytes name=MessageBytes.newInstance();
+    private MessageBytes value=MessageBytes.newInstance();
+
+    private MessageBytes comment=MessageBytes.newInstance();    // ;Comment=VALUE
+    private MessageBytes domain=MessageBytes.newInstance();    // ;Domain=VALUE ...
+
+    private int maxAge = -1;	// ;Max-Age=VALUE
+				// ;Discard ... implied by maxAge < 0
+    // RFC2109: maxAge=0 will end a session
+    private MessageBytes path=MessageBytes.newInstance();	// ;Path=VALUE .
+    private boolean secure;	// ;Secure
+    private int version = 0;	// ;Version=1
+
+    //XXX CommentURL, Port -> use notes ?
+    
+    public ServerCookie() {
+
+    }
+
+    public void recycle() {
+        path.recycle();
+    	name.recycle();
+    	value.recycle();
+    	comment.recycle();
+    	maxAge=-1;
+    	path.recycle();
+        domain.recycle();
+    	version=0;
+    	secure=false;
+    }
+
+    public MessageBytes getComment() {
+	return comment;
+    }
+
+    public MessageBytes getDomain() {
+	return domain;
+    }
+
+    public void setMaxAge(int expiry) {
+	maxAge = expiry;
+    }
+
+    public int getMaxAge() {
+	return maxAge;
+    }
+
+
+    public MessageBytes getPath() {
+	return path;
+    }
+
+    public void setSecure(boolean flag) {
+	secure = flag;
+    }
+
+    public boolean getSecure() {
+	return secure;
+    }
+
+    public MessageBytes getName() {
+	return name;
+    }
+
+    public MessageBytes getValue() {
+	return value;
+    }
+
+    public int getVersion() {
+	return version;
+    }
+
+
+    public void setVersion(int v) {
+	version = v;
+    }
+
+
+    // -------------------- utils --------------------
+
+    public String toString() {
+	return "Cookie " + getName() + "=" + getValue() + " ; "
+	    + getVersion() + " " + getPath() + " " + getDomain();
+    }
+    
+    // Note -- disabled for now to allow full Netscape compatibility
+    // from RFC 2068, token special case characters
+    //
+    // private static final String tspecials = "()<>@,;:\\\"/[]?={} \t";
+    private static final String tspecials = ",; ";
+
+    /*
+     * Tests a string and returns true if the string counts as a
+     * reserved token in the Java language.
+     *
+     * @param value		the <code>String</code> to be tested
+     *
+     * @return			<code>true</code> if the <code>String</code> is
+     *				a reserved token; <code>false</code>
+     *				if it is not
+     */
+    public static boolean isToken(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 || tspecials.indexOf(c) != -1)
+		return false;
+	}
+	return true;
+    }
+
+    public static boolean checkName( String name ) {
+	if (!isToken(name)
+		|| name.equalsIgnoreCase("Comment")	// rfc2019
+		|| name.equalsIgnoreCase("Discard")	// 2019++
+		|| name.equalsIgnoreCase("Domain")
+		|| name.equalsIgnoreCase("Expires")	// (old cookies)
+		|| name.equalsIgnoreCase("Max-Age")	// rfc2019
+		|| name.equalsIgnoreCase("Path")
+		|| name.equalsIgnoreCase("Secure")
+		|| name.equalsIgnoreCase("Version")
+	    ) {
+	    return false;
+	}
+	return true;
+    }
+
+    // -------------------- Cookie parsing tools
+
+    
+    /** Return the header name to set the cookie, based on cookie
+     *  version
+     */
+    public String getCookieHeaderName() {
+	return getCookieHeaderName(version);
+    }
+
+    /** Return the header name to set the cookie, based on cookie
+     *  version
+     */
+    public static String getCookieHeaderName(int version) {
+	if( dbg>0 ) log( (version==1) ? "Set-Cookie2" : "Set-Cookie");
+        if (version == 1) {
+	    // RFC2109
+	    return "Set-Cookie";
+	    // XXX RFC2965 is not standard yet, and Set-Cookie2
+	    // is not supported by Netscape 4, 6, IE 3, 5 .
+	    // It is supported by Lynx, and there is hope 
+	    //	    return "Set-Cookie2";
+        } else {
+	    // Old Netscape
+	    return "Set-Cookie";
+        }
+    }
+
+    private static final String ancientDate=DateTool.formatOldCookie(new Date(10000));
+
+    public static void appendCookieValue( StringBuffer buf,
+					  int version,
+					  String name,
+					  String value,
+					  String path,
+					  String domain,
+					  String comment,
+					  int maxAge,
+					  boolean isSecure )
+    {
+        // this part is the same for all cookies
+	buf.append( name );
+        buf.append("=");
+        maybeQuote(version, buf, value);
+
+	// XXX Netscape cookie: "; "
+ 	// add version 1 specific information
+	if (version == 1) {
+	    // Version=1 ... required
+	    buf.append ("; Version=1");
+
+	    // Comment=comment
+	    if ( comment!=null ) {
+		buf.append ("; Comment=");
+		maybeQuote (version, buf, comment);
+	    }
+	}
+	
+	// add domain information, if present
+
+	if (domain!=null) {
+	    buf.append("; Domain=");
+	    maybeQuote (version, buf, domain);
+	}
+
+	// Max-Age=secs/Discard ... or use old "Expires" format
+	if (maxAge >= 0) {
+	    if (version == 0) {
+		// XXX XXX XXX We need to send both, for
+		// interoperatibility (long word )
+		buf.append ("; Expires=");
+		// Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires netscape format )
+		// To expire we need to set the time back in future
+		// ( pfrieden@dChain.com )
+                if (maxAge == 0)
+		    buf.append( ancientDate );
+		else
+                    DateTool.formatOldCookie
+                        (new Date( System.currentTimeMillis() +
+                                   maxAge *1000L), buf,
+                         new FieldPosition(0));
+
+	    } else {
+		buf.append ("; Max-Age=");
+		buf.append (maxAge);
+	    }
+	}
+
+	// Path=path
+	if (path!=null) {
+	    buf.append ("; Path=");
+	    maybeQuote (version, buf, path);
+	}
+
+	// Secure
+	if (isSecure) {
+	  buf.append ("; Secure");
+	}
+	
+	
+    }
+
+    public static void maybeQuote (int version, StringBuffer buf,
+            String value) {
+        // special case - a \n or \r  shouldn't happen in any case
+        if (isToken(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 ) {
+        if (log.isDebugEnabled())
+            log.debug("ServerCookie: " + s);
+    }
+
+
+    /**
+     * Escapes any double quotes in the given string.
+     *
+     * @param s the input string
+     *
+     * @return The (possibly) escaped string
+     */
+    private static String escapeDoubleQuotes(String s) {
+
+        if (s == null || s.length() == 0 || s.indexOf('"') == -1) {
+            return s;
+        }
+
+        StringBuffer b = new StringBuffer();
+        for (int i = 0; i < s.length(); i++) {
+            char c = s.charAt(i);
+            if (c == '"')
+                b.append('\\').append('"');
+            else
+                b.append(c);
+        }
+
+        return b.toString();
+    }
+
+}
+

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/package.html
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/package.html?view=auto&rev=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/package.html (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/package.html Sun Sep 10 23:09:56 2006
@@ -0,0 +1,14 @@
+<html>
+<head>
+<title>util.http</title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+
+<body bgcolor="#FFFFFF">
+Special utils for handling HTTP-specific entities - headers, parameters,
+cookies, etc.
+
+The utils are not specific to tomcat, but use util.MessageBytes.
+
+</body>
+</html>

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java?view=diff&rev=442109&r1=442108&r2=442109
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/loader/Module.java Sun Sep 10 23:09:56 2006
@@ -23,8 +23,6 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 
-import org.apache.catalina.LifecycleException;
-
 // Based on org.apache.catalina.Loader - removed most of the catalina-specific
 
 /**



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message