tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject svn commit: r534293 [10/11] - in /tomcat/sandbox/tomcat-lite: ./ bin/ external/ java/ java/org/apache/commons/logging/ java/org/apache/tomcat/lite/ java/org/apache/tomcat/lite/ctxmap/ java/org/apache/tomcat/lite/http/ java/org/apache/tomcat/lite/http11...
Date Wed, 02 May 2007 02:22:50 GMT
Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocaleParser.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocaleParser.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocaleParser.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/LocaleParser.java Tue May  1 19:22:45 2007
@@ -0,0 +1,393 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Locale;
+import java.util.TreeMap;
+
+
+/**
+ * Utility class for string parsing that is higher performance than
+ * StringParser for simple delimited text cases.  Parsing is performed
+ * by setting the string, and then using the <code>findXxxx()</code> and
+ * <code>skipXxxx()</code> families of methods to remember significant
+ * offsets.  To retrieve the parsed substrings, call the <code>extract()</code>
+ * method with the appropriate saved offset values.
+ *
+ * @author Craig R. McClanahan
+ */
+public final class LocaleParser {
+
+    public LocaleParser() {
+        this(null);
+    }
+
+    public LocaleParser(String string) {
+        setString(string);
+    }
+
+    public TreeMap parseLocale(String value) {
+      // Store the accumulated languages that have been requested in
+      // a local collection, sorted by the quality value (so we can
+      // add Locales in descending order).  The values will be ArrayLists
+      // containing the corresponding Locales to be added
+      TreeMap locales = new TreeMap();
+
+      // Preprocess the value to remove all whitespace
+      int white = value.indexOf(' ');
+      if (white < 0)
+          white = value.indexOf('\t');
+      if (white >= 0) {
+          StringBuffer sb = new StringBuffer();
+          int len = value.length();
+          for (int i = 0; i < len; i++) {
+              char ch = value.charAt(i);
+              if ((ch != ' ') && (ch != '\t'))
+                  sb.append(ch);
+          }
+          value = sb.toString();
+      }
+
+      LocaleParser parser = this;
+      // Process each comma-delimited language specification
+      parser.setString(value);        // ASSERT: parser is available to us
+      int length = parser.getLength();
+      while (true) {
+
+          // Extract the next comma-delimited entry
+          int start = parser.getIndex();
+          if (start >= length)
+              break;
+          int end = parser.findChar(',');
+          String entry = parser.extract(start, end).trim();
+          parser.advance();   // For the following entry
+
+          // Extract the quality factor for this entry
+          double quality = 1.0;
+          int semi = entry.indexOf(";q=");
+          if (semi >= 0) {
+              try {
+                  quality = Double.parseDouble(entry.substring(semi + 3));
+              } catch (NumberFormatException e) {
+                  quality = 0.0;
+              }
+              entry = entry.substring(0, semi);
+          }
+
+          // Skip entries we are not going to keep track of
+          if (quality < 0.00005)
+              continue;       // Zero (or effectively zero) quality factors
+          if ("*".equals(entry))
+              continue;       // FIXME - "*" entries are not handled
+
+          // Extract the language and country for this entry
+          String language = null;
+          String country = null;
+          String variant = null;
+          int dash = entry.indexOf('-');
+          if (dash < 0) {
+              language = entry;
+              country = "";
+              variant = "";
+          } else {
+              language = entry.substring(0, dash);
+              country = entry.substring(dash + 1);
+              int vDash = country.indexOf('-');
+              if (vDash > 0) {
+                  String cTemp = country.substring(0, vDash);
+                  variant = country.substring(vDash + 1);
+                  country = cTemp;
+              } else {
+                  variant = "";
+              }
+          }
+
+          // Add a new Locale to the list of Locales for this quality level
+          Locale locale = new Locale(language, country, variant);
+          Double key = new Double(-quality);  // Reverse the order
+          ArrayList values = (ArrayList) locales.get(key);
+          if (values == null) {
+              values = new ArrayList();
+              locales.put(key, values);
+          }
+          values.add(locale);
+
+      }
+
+      return locales;
+    }
+    
+    /**
+     * The characters of the current string, as a character array.  Stored
+     * when the string is first specified to speed up access to characters
+     * being compared during parsing.
+     */
+    private char chars[] = null;
+
+
+    /**
+     * The zero-relative index of the current point at which we are
+     * positioned within the string being parsed.  <strong>NOTE</strong>:
+     * the value of this index can be one larger than the index of the last
+     * character of the string (i.e. equal to the string length) if you
+     * parse off the end of the string.  This value is useful for extracting
+     * substrings that include the end of the string.
+     */
+    private int index = 0;
+
+
+    /**
+     * The length of the String we are currently parsing.  Stored when the
+     * string is first specified to avoid repeated recalculations.
+     */
+    private int length = 0;
+
+
+    /**
+     * The String we are currently parsing.
+     */
+    private String string = null;
+
+
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * Return the zero-relative index of our current parsing position
+     * within the string being parsed.
+     */
+    public int getIndex() {
+
+        return (this.index);
+
+    }
+
+
+    /**
+     * Return the length of the string we are parsing.
+     */
+    public int getLength() {
+
+        return (this.length);
+
+    }
+
+
+    /**
+     * Return the String we are currently parsing.
+     */
+    public String getString() {
+
+        return (this.string);
+
+    }
+
+
+    /**
+     * Set the String we are currently parsing.  The parser state is also reset
+     * to begin at the start of this string.
+     *
+     * @param string The string to be parsed.
+     */
+    public void setString(String string) {
+
+        this.string = string;
+        if (string != null) {
+            this.length = string.length();
+            chars = this.string.toCharArray();
+        } else {
+            this.length = 0;
+            chars = new char[0];
+        }
+        reset();
+
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Advance the current parsing position by one, if we are not already
+     * past the end of the string.
+     */
+    public void advance() {
+
+        if (index < length)
+            index++;
+
+    }
+
+
+    /**
+     * Extract and return a substring that starts at the specified position,
+     * and extends to the end of the string being parsed.  If this is not
+     * possible, a zero-length string is returned.
+     *
+     * @param start Starting index, zero relative, inclusive
+     */
+    public String extract(int start) {
+
+        if ((start < 0) || (start >= length))
+            return ("");
+        else
+            return (string.substring(start));
+
+    }
+
+
+    /**
+     * Extract and return a substring that starts at the specified position,
+     * and ends at the character before the specified position.  If this is
+     * not possible, a zero-length string is returned.
+     *
+     * @param start Starting index, zero relative, inclusive
+     * @param end Ending index, zero relative, exclusive
+     */
+    public String extract(int start, int end) {
+
+        if ((start < 0) || (start >= end) || (end > length))
+            return ("");
+        else
+            return (string.substring(start, end));
+
+    }
+
+
+    /**
+     * Return the index of the next occurrence of the specified character,
+     * or the index of the character after the last position of the string
+     * if no more occurrences of this character are found.  The current
+     * parsing position is updated to the returned value.
+     *
+     * @param ch Character to be found
+     */
+    public int findChar(char ch) {
+
+        while ((index < length) && (ch != chars[index]))
+            index++;
+        return (index);
+
+    }
+
+
+    /**
+     * Return the index of the next occurrence of a non-whitespace character,
+     * or the index of the character after the last position of the string
+     * if no more non-whitespace characters are found.  The current
+     * parsing position is updated to the returned value.
+     */
+    public int findText() {
+
+        while ((index < length) && isWhite(chars[index]))
+            index++;
+        return (index);
+
+    }
+
+
+    /**
+     * Return the index of the next occurrence of a whitespace character,
+     * or the index of the character after the last position of the string
+     * if no more whitespace characters are found.  The current parsing
+     * position is updated to the returned value.
+     */
+    public int findWhite() {
+
+        while ((index < length) && !isWhite(chars[index]))
+            index++;
+        return (index);
+
+    }
+
+
+    /**
+     * Reset the current state of the parser to the beginning of the
+     * current string being parsed.
+     */
+    public void reset() {
+
+        index = 0;
+
+    }
+
+
+    /**
+     * Advance the current parsing position while it is pointing at the
+     * specified character, or until it moves past the end of the string.
+     * Return the final value.
+     *
+     * @param ch Character to be skipped
+     */
+    public int skipChar(char ch) {
+
+        while ((index < length) && (ch == chars[index]))
+            index++;
+        return (index);
+
+    }
+
+
+    /**
+     * Advance the current parsing position while it is pointing at a
+     * non-whitespace character, or until it moves past the end of the string.
+     * Return the final value.
+     */
+    public int skipText() {
+
+        while ((index < length) && !isWhite(chars[index]))
+            index++;
+        return (index);
+
+    }
+
+
+    /**
+     * Advance the current parsing position while it is pointing at a
+     * whitespace character, or until it moves past the end of the string.
+     * Return the final value.
+     */
+    public int skipWhite() {
+
+        while ((index < length) && isWhite(chars[index]))
+            index++;
+        return (index);
+
+    }
+
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * Is the specified character considered to be whitespace?
+     *
+     * @param ch Character to be checked
+     */
+    protected boolean isWhite(char ch) {
+
+        if ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'))
+            return (true);
+        else
+            return (false);
+
+    }
+
+
+}

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MIME2Java.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MIME2Java.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MIME2Java.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/MIME2Java.java Tue May  1 19:22:45 2007
@@ -0,0 +1,601 @@
+/*
+ * 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.util.*;
+
+/**
+ * MIME2Java is a convenience class which handles conversions between MIME charset names
+ * and Java encoding names.
+ * <p>The supported XML encodings are the intersection of XML-supported code sets and those
+ * supported in JDK 1.1.
+ * <p>MIME charset names are used on <var>xmlEncoding</var> parameters to methods such
+ * as <code>TXDocument#setEncoding</code> and <code>DTD#setEncoding</code>.
+ * <p>Java encoding names are used on <var>encoding</var> parameters to
+ * methods such as <code>TXDocument#printWithFormat</code> and <code>DTD#printExternal</code>.
+ * <P>
+ * <TABLE BORDER="0" WIDTH="100%">
+ *  <TR>
+ *      <TD WIDTH="33%">
+ *          <P ALIGN="CENTER"><B>Common Name</B>
+ *      </TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER"><B>Use this name in XML files</B>
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER"><B>Name Type</B>
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER"><B>Xerces converts to this Java Encoder Name</B>
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">8 bit Unicode</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">UTF-8
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">UTF8
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin 1</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-1
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-1
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin 2</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-2
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-2
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin 3</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-3
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-3
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin 4</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-4
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-4
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin Cyrillic</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-5
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-5
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin Arabic</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-6
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-6
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin Greek</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-7
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-7
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin Hebrew</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-8
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-8
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">ISO Latin 5</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ISO-8859-9
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">ISO-8859-9
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: US</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-us
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp037
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Canada</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-ca
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp037
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Netherlands</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-nl
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp037
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Denmark</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-dk
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp277
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Norway</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-no
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp277
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Finland</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-fi
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp278
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Sweden</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-se
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp278
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Italy</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-it
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp280
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Spain, Latin America</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-es
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp284
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Great Britain</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-gb
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp285
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: France</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-fr
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp297
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Arabic</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-ar1
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp420
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Hebrew</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-he
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp424
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Switzerland</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-ch
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp500
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Roece</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-roece
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp870
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Yogoslavia</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-yu
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp870
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Iceland</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-is
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp871
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">EBCDIC: Urdu</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">ebcdic-cp-ar2
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">IANA
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">cp918
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">Chinese for PRC, mixed 1/2 byte</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">gb2312
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">GB2312
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">Extended Unix Code, packed for Japanese</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">euc-jp
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">eucjis
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">Japanese: iso-2022-jp</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">iso-2020-jp
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">JIS
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">Japanese: Shift JIS</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">Shift_JIS
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">SJIS
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">Chinese: Big5</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">Big5
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">Big5
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">Extended Unix Code, packed for Korean</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">euc-kr
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">iso2022kr
+ *      </TD>
+ *  </TR>
+ *  <TR>
+ *      <TD WIDTH="33%">Cyrillic</TD>
+ *      <TD WIDTH="15%">
+ *          <P ALIGN="CENTER">koi8-r
+ *      </TD>
+ *      <TD WIDTH="12%">
+ *          <P ALIGN="CENTER">MIME
+ *      </TD>
+ *      <TD WIDTH="31%">
+ *          <P ALIGN="CENTER">koi8-r
+ *      </TD>
+ *  </TR>
+ * </TABLE>
+ *
+ * @author TAMURA Kent &lt;kent@trl.ibm.co.jp&gt;
+ */
+public class MIME2Java {
+
+    static private Hashtable s_enchash;
+    static private Hashtable s_revhash;
+
+    static {
+        s_enchash = new Hashtable();
+        //    <preferred MIME name>, <Java encoding name>
+        s_enchash.put("UTF-8", "UTF8");
+        s_enchash.put("US-ASCII",        "8859_1");    // ?
+        s_enchash.put("ISO-8859-1",      "8859_1");
+        s_enchash.put("ISO-8859-2",      "8859_2");
+        s_enchash.put("ISO-8859-3",      "8859_3");
+        s_enchash.put("ISO-8859-4",      "8859_4");
+        s_enchash.put("ISO-8859-5",      "8859_5");
+        s_enchash.put("ISO-8859-6",      "8859_6");
+        s_enchash.put("ISO-8859-7",      "8859_7");
+        s_enchash.put("ISO-8859-8",      "8859_8");
+        s_enchash.put("ISO-8859-9",      "8859_9");
+        s_enchash.put("ISO-2022-JP",     "JIS");
+        s_enchash.put("SHIFT_JIS",       "SJIS");
+        s_enchash.put("EUC-JP",          "EUCJIS");
+        s_enchash.put("GB2312",          "GB2312");
+        s_enchash.put("BIG5",            "Big5");
+        s_enchash.put("EUC-KR",          "KSC5601");
+        s_enchash.put("ISO-2022-KR",     "ISO2022KR");
+        s_enchash.put("KOI8-R",          "KOI8_R");
+
+        s_enchash.put("EBCDIC-CP-US",    "CP037");
+        s_enchash.put("EBCDIC-CP-CA",    "CP037");
+        s_enchash.put("EBCDIC-CP-NL",    "CP037");
+        s_enchash.put("EBCDIC-CP-DK",    "CP277");
+        s_enchash.put("EBCDIC-CP-NO",    "CP277");
+        s_enchash.put("EBCDIC-CP-FI",    "CP278");
+        s_enchash.put("EBCDIC-CP-SE",    "CP278");
+        s_enchash.put("EBCDIC-CP-IT",    "CP280");
+        s_enchash.put("EBCDIC-CP-ES",    "CP284");
+        s_enchash.put("EBCDIC-CP-GB",    "CP285");
+        s_enchash.put("EBCDIC-CP-FR",    "CP297");
+        s_enchash.put("EBCDIC-CP-AR1",   "CP420");
+        s_enchash.put("EBCDIC-CP-HE",    "CP424");
+        s_enchash.put("EBCDIC-CP-CH",    "CP500");
+        s_enchash.put("EBCDIC-CP-ROECE", "CP870");
+        s_enchash.put("EBCDIC-CP-YU",    "CP870");
+        s_enchash.put("EBCDIC-CP-IS",    "CP871");
+        s_enchash.put("EBCDIC-CP-AR2",   "CP918");
+
+                                                // j:CNS11643 -> EUC-TW?
+                                                // ISO-2022-CN? ISO-2022-CN-EXT?
+
+        s_revhash = new Hashtable();
+        //    <Java encoding name>, <preferred MIME name>
+        s_revhash.put("UTF8", "UTF-8");
+        //s_revhash.put("8859_1", "US-ASCII");    // ?
+        s_revhash.put("8859_1", "ISO-8859-1");
+        s_revhash.put("8859_2", "ISO-8859-2");
+        s_revhash.put("8859_3", "ISO-8859-3");
+        s_revhash.put("8859_4", "ISO-8859-4");
+        s_revhash.put("8859_5", "ISO-8859-5");
+        s_revhash.put("8859_6", "ISO-8859-6");
+        s_revhash.put("8859_7", "ISO-8859-7");
+        s_revhash.put("8859_8", "ISO-8859-8");
+        s_revhash.put("8859_9", "ISO-8859-9");
+        s_revhash.put("JIS", "ISO-2022-JP");
+        s_revhash.put("SJIS", "Shift_JIS");
+        s_revhash.put("EUCJIS", "EUC-JP");
+        s_revhash.put("GB2312", "GB2312");
+        s_revhash.put("BIG5", "Big5");
+        s_revhash.put("KSC5601", "EUC-KR");
+        s_revhash.put("ISO2022KR", "ISO-2022-KR");
+        s_revhash.put("KOI8_R", "KOI8-R");
+
+        s_revhash.put("CP037", "EBCDIC-CP-US");
+        s_revhash.put("CP037", "EBCDIC-CP-CA");
+        s_revhash.put("CP037", "EBCDIC-CP-NL");
+        s_revhash.put("CP277", "EBCDIC-CP-DK");
+        s_revhash.put("CP277", "EBCDIC-CP-NO");
+        s_revhash.put("CP278", "EBCDIC-CP-FI");
+        s_revhash.put("CP278", "EBCDIC-CP-SE");
+        s_revhash.put("CP280", "EBCDIC-CP-IT");
+        s_revhash.put("CP284", "EBCDIC-CP-ES");
+        s_revhash.put("CP285", "EBCDIC-CP-GB");
+        s_revhash.put("CP297", "EBCDIC-CP-FR");
+        s_revhash.put("CP420", "EBCDIC-CP-AR1");
+        s_revhash.put("CP424", "EBCDIC-CP-HE");
+        s_revhash.put("CP500", "EBCDIC-CP-CH");
+        s_revhash.put("CP870", "EBCDIC-CP-ROECE");
+        s_revhash.put("CP870", "EBCDIC-CP-YU");
+        s_revhash.put("CP871", "EBCDIC-CP-IS");
+        s_revhash.put("CP918", "EBCDIC-CP-AR2");
+    }
+
+    private MIME2Java() {
+    }
+
+    /**
+     * Convert a MIME charset name, also known as an XML encoding name, to a Java encoding name.
+     * @param   mimeCharsetName Case insensitive MIME charset name: <code>UTF-8, US-ASCII, ISO-8859-1,
+     *                          ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6,
+     *                          ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-2022-JP, Shift_JIS,
+     *                          EUC-JP, GB2312, Big5, EUC-KR, ISO-2022-KR, KOI8-R,
+     *                          EBCDIC-CP-US, EBCDIC-CP-CA, EBCDIC-CP-NL, EBCDIC-CP-DK,
+     *                          EBCDIC-CP-NO, EBCDIC-CP-FI, EBCDIC-CP-SE, EBCDIC-CP-IT,
+     *                          EBCDIC-CP-ES, EBCDIC-CP-GB, EBCDIC-CP-FR, EBCDIC-CP-AR1,
+     *                          EBCDIC-CP-HE, EBCDIC-CP-CH, EBCDIC-CP-ROECE, EBCDIC-CP-YU,
+     *                          EBCDIC-CP-IS and EBCDIC-CP-AR2</code>.
+     * @return                  Java encoding name, or <var>null</var> if <var>mimeCharsetName</var>
+     *                          is unknown.
+     * @see #reverse
+     */
+    public static String convert(String mimeCharsetName) {
+        return (String)s_enchash.get(mimeCharsetName.toUpperCase());
+    }
+
+    /**
+     * Convert a Java encoding name to MIME charset name.
+     * Available values of <i>encoding</i> are "UTF8", "8859_1", "8859_2", "8859_3", "8859_4",
+     * "8859_5", "8859_6", "8859_7", "8859_8", "8859_9", "JIS", "SJIS", "EUCJIS",
+     * "GB2312", "BIG5", "KSC5601", "ISO2022KR",  "KOI8_R", "CP037", "CP277", "CP278",
+     * "CP280", "CP284", "CP285", "CP297", "CP420", "CP424", "CP500", "CP870", "CP871" and "CP918".
+     * @param   encoding    Case insensitive Java encoding name: <code>UTF8, 8859_1, 8859_2, 8859_3,
+     *                      8859_4, 8859_5, 8859_6, 8859_7, 8859_8, 8859_9, JIS, SJIS, EUCJIS,
+     *                      GB2312, BIG5, KSC5601, ISO2022KR, KOI8_R, CP037, CP277, CP278,
+     *                      CP280, CP284, CP285, CP297, CP420, CP424, CP500, CP870, CP871
+     *                      and CP918</code>.
+     * @return              MIME charset name, or <var>null</var> if <var>encoding</var> is unknown.
+     * @see #convert
+     */
+    public static String reverse(String encoding) {
+        return (String)s_revhash.get(encoding.toUpperCase());
+    }
+}

Modified: 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=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Parameters.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Parameters.java Tue May  1 19:22:45 2007
@@ -21,21 +21,16 @@
 import java.util.Hashtable;
 
 import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.CBuffer;
 import org.apache.tomcat.util.buf.MessageBytes;
 import org.apache.tomcat.util.buf.UDecoder;
-import org.apache.tomcat.util.collections.MultiMap;
 
 /**
+ * Used for request parameters - deal with the weird dispatcher requirements
  * 
  * @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 );
-    
+public final class Parameters {
     // 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
@@ -43,14 +38,19 @@
     private boolean didQueryParameters=false;
     private boolean didMerge=false;
     
+    // The original query string
     MessageBytes queryMB;
+
+    // orginal headers
     MimeHeaders  headers;
 
+    // used internally to decode the params
     UDecoder urlDec;
+    
+    // Duplicated query - we modify this in-place, need to save the original
+    // value for getQueryString().
     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,
@@ -62,13 +62,10 @@
     private Parameters currentChild=null;
 
     String encoding=null;
+    
     String queryStringEncoding=null;
     
-    /**
-     * 
-     */
     public Parameters() {
-	super( INITIAL_SIZE );
     }
 
     public void setQuery( MessageBytes queryMB ) {
@@ -81,16 +78,13 @@
 
     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;
@@ -209,10 +203,6 @@
      */
     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();
 
@@ -227,8 +217,6 @@
 	Hashtable parentProps=parent.paramHashStringArray;
 	merge2( paramHashStringArray , parentProps);
 	didMerge=true;
-	if(debug > 0 )
-	    log("After " + paramsAsString());
     }
 
 
@@ -242,29 +230,7 @@
 	    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.
@@ -329,28 +295,48 @@
 
     // -------------------- Parameter parsing --------------------
 
-    // This code is not used right now - it's the optimized version
-    // of the above.
+    // -------------------- Parsing --------------------
+
+    /** Process the query string into parameters
+     * Used in ServletRequestImpl
+     */
+    public void handleQueryParameters() {
+        if( didQueryParameters ) return;
+
+        didQueryParameters=true;
+
+        if( queryMB==null || queryMB.isNull() )
+            return;
+
+        try {
+            decodedQuery.duplicate( queryMB );
+        } catch (IOException e) {
+            // Can't happen, as decodedQuery can't overflow
+            e.printStackTrace();
+        }
+        processParameters( decodedQuery, queryStringEncoding );
+    }
 
     // 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);
-    
+
+    CBuffer tmpNameC=new CBuffer(1024);
+    CBuffer tmpValueC=new CBuffer(1024);
+
+    /** 
+     * From ServletRequestImpl, parse the parameters
+     */
     public void processParameters( byte bytes[], int start, int len ) {
         processParameters(bytes, start, len, encoding);
     }
 
-    public void processParameters( byte bytes[], int start, int len, 
+    private 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;
@@ -366,7 +352,6 @@
 		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;
@@ -398,19 +383,22 @@
 
 	} while( pos<end );
     }
-
+    
     private String urlDecode(ByteChunk bc, String enc)
         throws IOException {
         if( urlDec==null ) {
             urlDec=new UDecoder();   
         }
+        // decode %xx bytes
         urlDec.convert(bc);
+        // Now convert the bytes to chars 
         String result = null;
+        
         if (enc != null) {
             bc.setEncoding(enc);
             result = bc.toString();
         } else {
-            CharChunk cc = tmpNameC;
+            CBuffer cc = tmpNameC;
             cc.allocate(bc.getLength(), -1);
             // Default encoding: fast conversion
             byte[] bbuf = bc.getBuffer();
@@ -426,89 +414,17 @@
         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 ) {
+    private void processParameters( MessageBytes data, String encoding ) {
 	if( data==null || data.isNull() || data.getLength() <= 0 ) return;
 
-	if( data.getType() == MessageBytes.T_BYTES ) {
+	if( data.isBytes() ) {
 	    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());
+	    processParameters( data.getCharSequence());
 	}
     }
 
@@ -527,22 +443,12 @@
 	}
 	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
+    /** Used by RequestDispatcher and to process CharChunk data
      */
-    public void processParameters( String str ) {
+    public void processParameters( CharSequence str ) {
 	int end=str.length();
 	int pos=0;
-	if( debug > 0)
-	    log("String: " + str );
 	
         do {
 	    boolean noEq=false;
@@ -550,8 +456,8 @@
 	    int valEnd=-1;
 	    
 	    int nameStart=pos;
-	    int nameEnd=str.indexOf('=', nameStart );
-	    int nameEnd2=str.indexOf('&', nameStart );
+	    int nameEnd= MessageBytes.indexOf(str, '=', nameStart );
+	    int nameEnd2= MessageBytes.indexOf(str, '&', nameStart );
 	    if( nameEnd2== -1 ) nameEnd2=end;
 	    if( (nameEnd2!=-1 ) &&
 		( nameEnd==-1 || nameEnd > nameEnd2) ) {
@@ -559,14 +465,13 @@
 		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);
+		valEnd= MessageBytes.indexOf(str, '&', valStart);
 		if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart;
 	    }
 	    
@@ -575,28 +480,16 @@
 	    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() );
+                addParam( tmpNameC.toString(), tmpValueC.toString() );
 	    } catch( IOException ex ) {
 		ex.printStackTrace();
 	    }

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Range.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Range.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Range.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Range.java Tue May  1 19:22:45 2007
@@ -0,0 +1,146 @@
+/**
+ * 
+ */
+package org.apache.tomcat.util.http;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+/** 
+ * Utils to process HTTP/1.1 ranges. Used by default servlet, could 
+ * be used by any servlet that needs to deal with ranges.
+ * 
+ * It is very good to support ranges if you have large content. In most
+ * cases supporting one range is enough - getting multiple ranges doesn't
+ * seem very common, and it's complex (multipart response).
+ * 
+ * @author Costin Manolache
+ * @author Remy Maucherat 
+ * @author - see DefaultServlet in Catalin for other contributors
+ */
+public class Range {
+
+    public long start;
+    public long end;
+    public long length;
+
+    /**
+     * Validate range.
+     */
+    public boolean validate() {
+        if (end >= length)
+            end = length - 1;
+        return ( (start >= 0) && (end >= 0) && (start <= end)
+                 && (length > 0) );
+    }
+
+    public void recycle() {
+        start = 0;
+        end = 0;
+        length = 0;
+    }
+    
+    /** Parse ranges. 
+     * 
+     * @return null if the range is invalid or can't be parsed
+     */
+    public static ArrayList parseRanges(long fileLength, 
+                                        String rangeHeader) throws IOException {
+        ArrayList result = new ArrayList();
+        StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ",");
+
+        // Parsing the range list
+        while (commaTokenizer.hasMoreTokens()) {
+            String rangeDefinition = commaTokenizer.nextToken().trim();
+
+            Range currentRange = new Range();
+            currentRange.length = fileLength;
+
+            int dashPos = rangeDefinition.indexOf('-');
+
+            if (dashPos == -1) {
+                return null;
+            }
+
+            if (dashPos == 0) {
+                try {
+                    long offset = Long.parseLong(rangeDefinition);
+                    currentRange.start = fileLength + offset;
+                    currentRange.end = fileLength - 1;
+                } catch (NumberFormatException e) {
+                    return null;
+                }
+            } else {
+
+                try {
+                    currentRange.start = Long.parseLong
+                        (rangeDefinition.substring(0, dashPos));
+                    if (dashPos < rangeDefinition.length() - 1)
+                        currentRange.end = Long.parseLong
+                            (rangeDefinition.substring
+                             (dashPos + 1, rangeDefinition.length()));
+                    else
+                        currentRange.end = fileLength - 1;
+                } catch (NumberFormatException e) {
+                    return null;
+                }
+
+            }
+            if (!currentRange.validate()) {
+                return null;
+            }
+            result.add(currentRange);
+        }
+        return result;
+    }
+
+
+    /**
+     * Parse the Content-Range header. Used with PUT or in response.
+     * 
+     * @return Range
+     */
+    public static Range parseContentRange(String rangeHeader)
+            throws IOException {
+        if (rangeHeader == null)
+            return null;
+
+        // bytes is the only range unit supported
+        if (!rangeHeader.startsWith("bytes")) {
+            return null;
+        }
+
+        rangeHeader = rangeHeader.substring(6).trim();
+
+        int dashPos = rangeHeader.indexOf('-');
+        int slashPos = rangeHeader.indexOf('/');
+
+        if (dashPos == -1) {
+            return null;
+        }
+
+        if (slashPos == -1) {
+            return null;
+        }
+
+        Range range = new Range();
+
+        try {
+            range.start = Long.parseLong(rangeHeader.substring(0, dashPos));
+            range.end =
+                Long.parseLong(rangeHeader.substring(dashPos + 1, slashPos));
+            range.length = Long.parseLong
+                (rangeHeader.substring(slashPos + 1, rangeHeader.length()));
+        } catch (NumberFormatException e) {
+            return null;
+        }
+
+        if (!range.validate()) {
+            return null;
+        }
+
+        return range;
+    }
+
+}
\ No newline at end of file

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/RequestUtil.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/RequestUtil.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/RequestUtil.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/RequestUtil.java Tue May  1 19:22:45 2007
@@ -0,0 +1,509 @@
+/*
+ * 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.UnsupportedEncodingException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.TimeZone;
+
+import javax.servlet.http.Cookie;
+
+
+/**
+ * General purpose request parsing and encoding utility methods.
+ *
+ * @author Craig R. McClanahan
+ * @author Tim Tye
+ * @version $Revision: 302905 $ $Date: 2004-05-26 18:41:54 +0200 (mer., 26 mai 2004) $
+ */
+
+public final class RequestUtil {
+
+
+    /**
+     * The DateFormat to use for generating readable dates in cookies.
+     */
+    private static SimpleDateFormat format =
+        new SimpleDateFormat(" EEEE, dd-MMM-yy kk:mm:ss zz");
+
+    static {
+        format.setTimeZone(TimeZone.getTimeZone("GMT"));
+    }
+
+
+    /**
+     * Encode a cookie as per RFC 2109.  The resulting string can be used
+     * as the value for a <code>Set-Cookie</code> header.
+     *
+     * @param cookie The cookie to encode.
+     * @return A string following RFC 2109.
+     */
+    public static String encodeCookie(Cookie cookie) {
+
+        StringBuffer buf = new StringBuffer( cookie.getName() );
+        buf.append("=");
+        buf.append(cookie.getValue());
+
+        if (cookie.getComment() != null) {
+            buf.append("; Comment=\"");
+            buf.append(cookie.getComment());
+            buf.append("\"");
+        }
+
+        if (cookie.getDomain() != null) {
+            buf.append("; Domain=\"");
+            buf.append(cookie.getDomain());
+            buf.append("\"");
+        }
+
+        long age = cookie.getMaxAge();
+        if (cookie.getMaxAge() >= 0) {
+            buf.append("; Max-Age=\"");
+            buf.append(cookie.getMaxAge());
+            buf.append("\"");
+        }
+
+        if (cookie.getPath() != null) {
+            buf.append("; Path=\"");
+            buf.append(cookie.getPath());
+            buf.append("\"");
+        }
+
+        if (cookie.getSecure()) {
+            buf.append("; Secure");
+        }
+
+        if (cookie.getVersion() > 0) {
+            buf.append("; Version=\"");
+            buf.append(cookie.getVersion());
+            buf.append("\"");
+        }
+
+        return (buf.toString());
+    }
+
+
+    /**
+     * 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());
+
+    }
+
+
+    /**
+     * Normalize a relative URI path that may have relative values ("/./",
+     * "/../", and so on ) it it.  <strong>WARNING</strong> - This method is
+     * useful only for normalizing application-generated paths.  It does not
+     * try to perform security checks for malicious input.
+     *
+     * @param path Relative path to be normalized
+     */
+    public static String normalize(String path) {
+
+        if (path == null)
+            return null;
+
+        // Create a place for the normalized path
+        String normalized = path;
+
+        if (normalized.equals("/."))
+            return "/";
+
+        // Add a leading "/" if necessary
+        if (!normalized.startsWith("/"))
+            normalized = "/" + normalized;
+
+        // Resolve occurrences of "//" in the normalized path
+        while (true) {
+            int index = normalized.indexOf("//");
+            if (index < 0)
+                break;
+            normalized = normalized.substring(0, index) +
+                normalized.substring(index + 1);
+        }
+
+        // Resolve occurrences of "/./" in the normalized path
+        while (true) {
+            int index = normalized.indexOf("/./");
+            if (index < 0)
+                break;
+            normalized = normalized.substring(0, index) +
+                normalized.substring(index + 2);
+        }
+
+        // Resolve occurrences of "/../" in the normalized path
+        while (true) {
+            int index = normalized.indexOf("/../");
+            if (index < 0)
+                break;
+            if (index == 0)
+                return (null);  // Trying to go outside our context
+            int index2 = normalized.lastIndexOf('/', index - 1);
+            normalized = normalized.substring(0, index2) +
+                normalized.substring(index + 3);
+        }
+
+        // Return the normalized path that we have completed
+        return (normalized);
+
+    }
+
+
+    /**
+     * Parse the character encoding from the specified content type header.
+     * If the content type is null, or there is no explicit character encoding,
+     * <code>null</code> is returned.
+     *
+     * @param contentType a content type header
+     */
+    public static String parseCharacterEncoding(String contentType) {
+
+        if (contentType == null)
+            return (null);
+        int start = contentType.indexOf("charset=");
+        if (start < 0)
+            return (null);
+        String encoding = contentType.substring(start + 8);
+        int end = encoding.indexOf(';');
+        if (end >= 0)
+            encoding = encoding.substring(0, end);
+        encoding = encoding.trim();
+        if ((encoding.length() > 2) && (encoding.startsWith("\""))
+            && (encoding.endsWith("\"")))
+            encoding = encoding.substring(1, encoding.length() - 1);
+        return (encoding.trim());
+
+    }
+
+
+    /**
+     * Parse a cookie header into an array of cookies according to RFC 2109.
+     *
+     * @param header Value of an HTTP "Cookie" header
+     */
+    public static Cookie[] parseCookieHeader(String header) {
+
+        if ((header == null) || (header.length() < 1))
+            return (new Cookie[0]);
+
+        ArrayList cookies = new ArrayList();
+        while (header.length() > 0) {
+            int semicolon = header.indexOf(';');
+            if (semicolon < 0)
+                semicolon = header.length();
+            if (semicolon == 0)
+                break;
+            String token = header.substring(0, semicolon);
+            if (semicolon < header.length())
+                header = header.substring(semicolon + 1);
+            else
+                header = "";
+            try {
+                int equals = token.indexOf('=');
+                if (equals > 0) {
+                    String name = token.substring(0, equals).trim();
+                    String value = token.substring(equals+1).trim();
+                    cookies.add(new Cookie(name, value));
+                }
+            } catch (Throwable e) {
+                ;
+            }
+        }
+
+        return ((Cookie[]) cookies.toArray(new Cookie[cookies.size()]));
+
+    }
+
+
+    /**
+     * Append request parameters from the specified String to the specified
+     * Map.  It is presumed that the specified Map is not accessed from any
+     * other thread, so no synchronization is performed.
+     * <p>
+     * <strong>IMPLEMENTATION NOTE</strong>:  URL decoding is performed
+     * individually on the parsed name and value elements, rather than on
+     * the entire query string ahead of time, to properly deal with the case
+     * where the name or value includes an encoded "=" or "&" character
+     * that would otherwise be interpreted as a delimiter.
+     *
+     * @param map Map that accumulates the resulting parameters
+     * @param data Input string containing request parameters
+     *
+     * @exception IllegalArgumentException if the data is malformed
+     */
+    public static void parseParameters(Map map, String data, String encoding)
+        throws UnsupportedEncodingException {
+
+        if ((data != null) && (data.length() > 0)) {
+
+            // use the specified encoding to extract bytes out of the
+            // given string so that the encoding is not lost. If an
+            // encoding is not specified, let it use platform default
+            byte[] bytes = null;
+            try {
+                if (encoding == null) {
+                    bytes = data.getBytes();
+                } else {
+                    bytes = data.getBytes(encoding);
+                }
+            } catch (UnsupportedEncodingException uee) {
+            }
+
+            parseParameters(map, bytes, encoding);
+        }
+
+    }
+
+
+    /**
+     * Decode and return the specified URL-encoded String.
+     * When the byte array is converted to a string, the system default
+     * character encoding is used...  This may be different than some other
+     * servers.
+     *
+     * @param str The url-encoded string
+     *
+     * @exception IllegalArgumentException if a '%' character is not followed
+     * by a valid 2-digit hexadecimal number
+     */
+    public static String URLDecode(String str) {
+
+        return URLDecode(str, null);
+
+    }
+
+
+    /**
+     * Decode and return the specified URL-encoded String.
+     *
+     * @param str The url-encoded string
+     * @param enc The encoding to use; if null, the default encoding is used
+     * @exception IllegalArgumentException if a '%' character is not followed
+     * by a valid 2-digit hexadecimal number
+     */
+    public static String URLDecode(String str, String enc) {
+
+        if (str == null)
+            return (null);
+
+        // use the specified encoding to extract bytes out of the
+        // given string so that the encoding is not lost. If an
+        // encoding is not specified, let it use platform default
+        byte[] bytes = null;
+        try {
+            if (enc == null) {
+                bytes = str.getBytes();
+            } else {
+                bytes = str.getBytes(enc);
+            }
+        } catch (UnsupportedEncodingException uee) {}
+
+        return URLDecode(bytes, enc);
+
+    }
+
+
+    /**
+     * Decode and return the specified URL-encoded byte array.
+     *
+     * @param bytes The url-encoded byte array
+     * @exception IllegalArgumentException if a '%' character is not followed
+     * by a valid 2-digit hexadecimal number
+     */
+    public static String URLDecode(byte[] bytes) {
+        return URLDecode(bytes, null);
+    }
+
+
+    /**
+     * Decode and return the specified URL-encoded byte array.
+     *
+     * @param bytes The url-encoded byte array
+     * @param enc The encoding to use; if null, the default encoding is used
+     * @exception IllegalArgumentException if a '%' character is not followed
+     * by a valid 2-digit hexadecimal number
+     */
+    public static String URLDecode(byte[] bytes, String enc) {
+
+        if (bytes == null)
+            return (null);
+
+        int len = bytes.length;
+        int ix = 0;
+        int ox = 0;
+        while (ix < len) {
+            byte b = bytes[ix++];     // Get byte to test
+            if (b == '+') {
+                b = (byte)' ';
+            } else if (b == '%') {
+                b = (byte) ((convertHexDigit(bytes[ix++]) << 4)
+                            + convertHexDigit(bytes[ix++]));
+            }
+            bytes[ox++] = b;
+        }
+        if (enc != null) {
+            try {
+                return new String(bytes, 0, ox, enc);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return new String(bytes, 0, ox);
+
+    }
+
+
+    /**
+     * Convert a byte character value to hexidecimal digit value.
+     *
+     * @param b the character value byte
+     */
+    private static byte convertHexDigit( byte b ) {
+        if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
+        if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
+        if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
+        return 0;
+    }
+
+
+    /**
+     * Put name and value pair in map.  When name already exist, add value
+     * to array of values.
+     *
+     * @param map The map to populate
+     * @param name The parameter name
+     * @param value The parameter value
+     */
+    private static void putMapEntry( Map map, String name, String value) {
+        String[] newValues = null;
+        String[] oldValues = (String[]) map.get(name);
+        if (oldValues == null) {
+            newValues = new String[1];
+            newValues[0] = value;
+        } else {
+            newValues = new String[oldValues.length + 1];
+            System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
+            newValues[oldValues.length] = value;
+        }
+        map.put(name, newValues);
+    }
+
+
+    /**
+     * Append request parameters from the specified String to the specified
+     * Map.  It is presumed that the specified Map is not accessed from any
+     * other thread, so no synchronization is performed.
+     * <p>
+     * <strong>IMPLEMENTATION NOTE</strong>:  URL decoding is performed
+     * individually on the parsed name and value elements, rather than on
+     * the entire query string ahead of time, to properly deal with the case
+     * where the name or value includes an encoded "=" or "&" character
+     * that would otherwise be interpreted as a delimiter.
+     *
+     * NOTE: byte array data is modified by this method.  Caller beware.
+     *
+     * @param map Map that accumulates the resulting parameters
+     * @param data Input string containing request parameters
+     * @param encoding Encoding to use for converting hex
+     *
+     * @exception UnsupportedEncodingException if the data is malformed
+     */
+    public static void parseParameters(Map map, byte[] data, String encoding)
+        throws UnsupportedEncodingException {
+
+        if (data != null && data.length > 0) {
+            int    pos = 0;
+            int    ix = 0;
+            int    ox = 0;
+            String key = null;
+            String value = null;
+            while (ix < data.length) {
+                byte c = data[ix++];
+                switch ((char) c) {
+                case '&':
+                    value = new String(data, 0, ox, encoding);
+                    if (key != null) {
+                        putMapEntry(map, key, value);
+                        key = null;
+                    }
+                    ox = 0;
+                    break;
+                case '=':
+                    if (key == null) {
+                        key = new String(data, 0, ox, encoding);
+                        ox = 0;
+                    } else {
+                        data[ox++] = c;
+                    }                   
+                    break;  
+                case '+':
+                    data[ox++] = (byte)' ';
+                    break;
+                case '%':
+                    data[ox++] = (byte)((convertHexDigit(data[ix++]) << 4)
+                                    + convertHexDigit(data[ix++]));
+                    break;
+                default:
+                    data[ox++] = c;
+                }
+            }
+            //The last value does not end in '&'.  So save it now.
+            if (key != null) {
+                value = new String(data, 0, ox, encoding);
+                putMapEntry(map, key, value);
+            }
+        }
+
+    }
+
+
+
+}

Modified: 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=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ServerCookie.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ServerCookie.java Tue May  1 19:22:45 2007
@@ -16,11 +16,15 @@
 
 package org.apache.tomcat.util.http;
 
-import java.io.Serializable;
+import java.text.DateFormat;
 import java.text.FieldPosition;
+import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import javax.servlet.http.Cookie;
 
-import org.apache.tomcat.util.buf.DateTool;
 import org.apache.tomcat.util.buf.MessageBytes;
 
 
@@ -33,31 +37,51 @@
  *  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 );
+public class ServerCookie extends Cookie {
+   
+    /** Pattern used for old cookies
+     */
+    private final static String OLD_COOKIE_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
     
+    /** DateFormat to be used to format old netscape cookies
+        Called from ServerCookie
+     */
+    private final static DateFormat oldCookieFormat =
+        new SimpleDateFormat(OLD_COOKIE_PATTERN, Locale.US);
+
+    private static final String ancientDate = formatOldCookie(new Date(10000));
+    public final static TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT");
+
+    static {
+        oldCookieFormat.setTimeZone(GMT_ZONE);
+    }
+
     private MessageBytes name=MessageBytes.newInstance();
     private MessageBytes value=MessageBytes.newInstance();
 
-    private MessageBytes comment=MessageBytes.newInstance();    // ;Comment=VALUE
-    private MessageBytes domain=MessageBytes.newInstance();    // ;Domain=VALUE ...
+    //  ;Comment=VALUE
+    private MessageBytes comment=MessageBytes.newInstance();    
+
+    // ;Domain=VALUE ...
+    private MessageBytes domain=MessageBytes.newInstance();   
 
+    // RFC2109: maxAge=0 will end a session
     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 .
+    
+    // ;Path=VALUE .
+    private MessageBytes path=MessageBytes.newInstance();	
+
     private boolean secure;	// ;Secure
+    
     private int version = 0;	// ;Version=1
 
-    //XXX CommentURL, Port -> use notes ?
-    
     public ServerCookie() {
-
+      // To make super happy, since it's not extend 
+      // friendly. This avoids duplicating each cookie, 
+      super("Dummy", "Dummy");
     }
-
+    
     public void recycle() {
         path.recycle();
     	name.recycle();
@@ -70,12 +94,29 @@
     	secure=false;
     }
 
-    public MessageBytes getComment() {
-	return comment;
+
+    public String getComment() {
+        return comment.toString();
+    }
+
+    public String getDomain() {
+        return domain.toString();
+    }
+
+    public String getPath() {
+        return path.toString();
     }
 
-    public MessageBytes getDomain() {
-	return domain;
+    public void setComment(String purpose) {
+        comment.setString(purpose);
+    }
+
+    public void setDomain(String pattern) {
+        domain.setString(pattern);
+    }
+
+    public void setPath(String uri) {
+        path.setString(uri);
     }
 
     public void setMaxAge(int expiry) {
@@ -86,11 +127,6 @@
 	return maxAge;
     }
 
-
-    public MessageBytes getPath() {
-	return path;
-    }
-
     public void setSecure(boolean flag) {
 	secure = flag;
     }
@@ -99,24 +135,54 @@
 	return secure;
     }
 
-    public MessageBytes getName() {
-	return name;
+    public String getName() {
+        return name.toString();
     }
 
-    public MessageBytes getValue() {
-	return value;
+    public void setName(String v) {
+        name.setString(v);
+    }
+
+    public String getValue() { 
+        return value.toString();
     }
 
+    public void setValue(String v) {
+        value.setString(v);
+    }
+    
     public int getVersion() {
-	return version;
+        return version;
     }
 
 
     public void setVersion(int v) {
-	version = v;
+        version = v;
+    }
+
+    // Access to bytes
+    
+    public MessageBytes getCommentBytes() {
+        return comment;
     }
 
+    public MessageBytes getDomainBytes() {
+        return domain;
+    }
+
+    public MessageBytes getPathBytes() {
+        return path;
+    }
+
+    public MessageBytes getNameBytes() {
+	return name;
+    }
+    
 
+    public MessageBytes getValueBytes() {
+	return value;
+    }
+    
     // -------------------- utils --------------------
 
     public String toString() {
@@ -183,8 +249,7 @@
      *  version
      */
     public static String getCookieHeaderName(int version) {
-	if( dbg>0 ) log( (version==1) ? "Set-Cookie2" : "Set-Cookie");
-        if (version == 1) {
+       if (version == 1) {
 	    // RFC2109
 	    return "Set-Cookie";
 	    // XXX RFC2965 is not standard yet, and Set-Cookie2
@@ -197,8 +262,24 @@
         }
     }
 
-    private static final String ancientDate=DateTool.formatOldCookie(new Date(10000));
-
+    static String formatOldCookie( Date d )
+    {
+        String ocf=null;
+        synchronized(oldCookieFormat) {
+            ocf= oldCookieFormat.format( d );
+        }
+        return ocf;
+    }
+    
+    static void formatOldCookie( Date d, StringBuffer sb,
+                                 FieldPosition fp )
+    {
+        synchronized(oldCookieFormat) {
+            oldCookieFormat.format( d, sb, fp );
+        }
+    }
+    
+    
     public static void appendCookieValue( StringBuffer buf,
 					  int version,
 					  String name,
@@ -246,7 +327,7 @@
                 if (maxAge == 0)
 		    buf.append( ancientDate );
 		else
-                    DateTool.formatOldCookie
+                    formatOldCookie
                         (new Date( System.currentTimeMillis() +
                                    maxAge *1000L), buf,
                          new FieldPosition(0));
@@ -282,14 +363,6 @@
             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.



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


Mime
View raw message