costin      00/12/07 10:34:54

  Modified:    src/share/org/apache/tomcat/util Ascii.java DateTool.java
                        MessageBytes.java
               src/share/org/apache/tomcat/util/http Cookies.java
                        Headers.java Parameters.java
  Added:       src/share/org/apache/tomcat/util ByteChunk.java
                        CharChunk.java
               src/share/org/apache/tomcat/util/collections
                        MultiMapNamesEnumeration.java
                        MultiMapValuesEnumeration.java
  Log:
  First refactoring of MessageBytes.
  
  The byte[] manipulation moved to ByteChunk, char[] to CharChunk. Both act
  as "cursors" in an existing byte/char[] ( they can't resize and don't own
  the buffer ).
  
  The int/date conversion is cached, but it's just a cached value, it's no longer
  "first class". Probably it's better to do the caching and conversion at a
  higher level anyway.
  
  In Headers, removed the Enumerations - as it was a bad choice and confusing.
  It is still possible to enumerate a MultiMap, for use by the upper layer
  ( facade ).
  
  Revision  Changes    Path
  1.6       +0 -7      jakarta-tomcat/src/share/org/apache/tomcat/util/Ascii.java
  
  Index: Ascii.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/Ascii.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Ascii.java        2000/08/11 06:14:18     1.5
  +++ Ascii.java        2000/12/07 18:34:51     1.6
  @@ -221,11 +221,4 @@
        return n;
       }
   
  -    public static boolean equalsIgnoreCase(String str, MessageBytes mB ) {
  -     return mB.equalsIgnoreCase( str );
  -    }
  -
  -
  -    
  -
   }
  
  
  
  1.7       +7 -4      jakarta-tomcat/src/share/org/apache/tomcat/util/DateTool.java
  
  Index: DateTool.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/DateTool.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- DateTool.java     2000/08/28 06:08:18     1.6
  +++ DateTool.java     2000/12/07 18:34:51     1.7
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/DateTool.java,v 1.6 
2000/08/28 06:08:18 costin Exp $
  - * $Revision: 1.6 $
  - * $Date: 2000/08/28 06:08:18 $
  + * $Header: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/DateTool.java,v 1.7 
2000/12/07 18:34:51 costin Exp $
  + * $Revision: 1.7 $
  + * $Date: 2000/12/07 18:34:51 $
    *
    * ====================================================================
    *
  @@ -131,7 +131,10 @@
           StringManager.getManager("org.apache.tomcat.resources");
       
       public static long parseDate( MessageBytes value ) {
  -     String dateString=value.toString();
  +     return parseDate( value.toString());
  +    }
  +
  +    public static long parseDate( String dateString ) {
        Date date=null;
           try {
               date = DateTool.rfc1123Format.parse(dateString);
  
  
  
  1.14      +87 -313   
jakarta-tomcat/src/share/org/apache/tomcat/util/MessageBytes.java
  
  Index: MessageBytes.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MessageBytes.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- MessageBytes.java 2000/11/30 04:58:57     1.13
  +++ MessageBytes.java 2000/12/07 18:34:51     1.14
  @@ -84,35 +84,22 @@
       public static final int T_BYTES = 2;
       public static final int T_CHARS = 3;
   
  -    // support for efficient int and date parsing/formating
  -    public static final int T_INT = 4;
  -    public static final int T_DATE = 5;
  -
       private int hashCode=0;
       private boolean hasHashCode=false;
   
       private boolean caseSensitive=true;
       
  -    // byte[]
  -    private byte[] bytes;
  -    private int bytesOff;
  -    private int bytesLen;
  -    private String enc;
  -    private boolean hasByteValue=false;
  -    
  -    // Caching the result of a conversion
  -
  -    // char[]
  -    private char chars[];
  -    private int charsOff;
  -    private int charsLen;
  -    private boolean hasCharValue=false;
  +    ByteChunk byteC=new ByteChunk();
  +
  +    CharChunk charC=new CharChunk();
       
       // String
       private String strValue;
       private boolean hasStrValue=false;
   
       // efficient int and date
  +    // XXX used only for headers - shouldn't be
  +    // stored here.
       private int intValue;
       private boolean hasIntValue=false;
       private Date dateValue;
  @@ -137,26 +124,22 @@
       }
   
       public boolean isNull() {
  -     return bytes==null && strValue==null;
  +     return byteC.isNull() && charC.isNull() && ! hasStrValue;
  +     // bytes==null && strValue==null;
       }
       
  -    public void reset() {
  -     recycle();
  -    }
       /**
        * Resets the message bytes to an uninitialized state.
        */
       public void recycle() {
        type=T_NULL;
  -     bytes = null;
  +     byteC.recycle();
  +     charC.recycle();
  +
        strValue=null;
  -     //      chars=null;
        caseSensitive=true;
   
  -     enc=null;
  -     hasByteValue=false;
        hasStrValue=false;
  -     hasCharValue=false;
        hasHashCode=false;
        hasIntValue=false;
        hasDateValue=false;     
  @@ -171,28 +154,23 @@
        */
       public void setBytes(byte[] b, int off, int len) {
        recycle(); // a new value is set, cached values must reset
  -     bytes = b;
  -     bytesOff = off;
  -     bytesLen = len;
  +     byteC.setBytes( b, off, len );
        type=T_BYTES;
  -     hasByteValue=true;
       }
   
       public void setEncoding( String enc ) {
  -     if( hasByteValue ) {
  -         hasCharValue=false;
  +     if( !byteC.isNull() ) {
  +         // if the encoding changes we need to reset the converion results
  +         charC.recycle();
            hasStrValue=false;
        }
  -     this.enc=enc;
  +     byteC.setEncoding(enc);
       }
       
       public void setChars( char[] c, int off, int len ) {
        recycle();
  -     chars=c;
  -     charsOff=off;
  -     charsLen=len;
  +     charC.setChars( c, off, len );
        type=T_CHARS;
  -     hasCharValue=true;
       }
   
       public void setString( String s ) {
  @@ -203,97 +181,73 @@
       }
   
       public void setTime(long t) {
  +     // XXX replace it with a byte[] tool
        recycle();
        if( dateValue==null)
            dateValue=new Date(t);
        else
            dateValue.setTime(t);
  -     type = T_DATE;
  +     strValue=DateTool.rfc1123Format.format(dateValue);
  +     hasStrValue=true;
        hasDateValue=true;
  +     type=T_STR;   
       }
   
  +    /** Set the buffer to the representation of an int 
  +     */
       public void setInt(int i) {
  +     // XXX replace it with a byte[] tool
        recycle();
  -     intValue = i;
  -     type = T_INT;
  +     strValue=String.valueOf( i );
  +     intValue=i;
        hasIntValue=true;
  +     hasStrValue=true;
  +     type=T_STR;
       }
   
       // -------------------- Conversion and getters --------------------
       public String toString() {
        if( hasStrValue ) return strValue;
        hasStrValue=true;
  -
  +     
        switch (type) {
        case T_CHARS:
  -         strValue=new String( chars, charsOff, charsLen);
  +         strValue=charC.toString();
            return strValue;
        case T_BYTES:
  -         try {
  -             if( enc==null )
  -                 strValue=toStringUTF8();
  -             else {
  -                 strValue=new String(bytes, bytesOff, bytesLen, enc);
  -                 // this will display when we implement I18N
  -                 System.out.println("Converting from bytes to string using " + enc 
+ ":" + strValue  );
  -             }
  -             return strValue;
  -         } catch (java.io.UnsupportedEncodingException e) {
  -             return null;  // can't happen
  -         }
  -     case T_DATE:
  -         strValue=DateTool.rfc1123Format.format(dateValue);
  -         return strValue;
  -     case T_INT:
  -         strValue=String.valueOf(intValue);
  +         strValue=byteC.toString();
            return strValue;
        }
        return null;
       }
  -
  -    private String toStringUTF8() {
  -        if (null == bytes) {
  -            return null;
  -        }
  -     if( chars==null || bytesLen > chars.length ) {
  -         chars=new char[bytesLen];
  -     }
  -
  -     int j=bytesOff;
  -     for( int i=0; i< bytesLen; i++ ) {
  -         chars[i]=(char)bytes[j++];
  -     }
  -     charsLen=bytesLen;
  -     charsOff=0;
  -     hasCharValue=true;
  -     return new String( chars, 0, bytesLen);
  -    }
  -
  +    
       public long getTime()
       {
  -     if( hasDateValue ) {
  +             if( hasDateValue ) {
            if( dateValue==null) return -1;
            return dateValue.getTime();
  -     }
  -
  -     long l=DateTool.parseDate( this );
  -     if( dateValue==null)
  -         dateValue=new Date(l);
  -     else
  -         dateValue.setTime(l);
  -     hasDateValue=true;
  -     return l;
  +             }
  +     
  +             long l=DateTool.parseDate( this );
  +             if( dateValue==null)
  +                 dateValue=new Date(l);
  +             else
  +                 dateValue.setTime(l);
  +             hasDateValue=true;
  +             return l;
       }
  +    
   
  -    public int getInt()
  +    /** Convert the buffer to an int, cache the value
  +     */ 
  +    public int getInt() 
       {
        if( hasIntValue )
            return intValue;
        
        switch (type) {
        case T_BYTES:
  -         intValue=Ascii.parseInt(bytes, bytesOff,
  -                                 bytesLen);
  +         intValue=byteC.getInt();
            break;
        default:
            intValue=Integer.parseInt(toString());
  @@ -310,47 +264,38 @@
       /**
        * Returns the message bytes.
        */
  -    public byte[] getBytes() {
  -     return bytes;
  +    public ByteChunk getByteChunk() {
  +     return byteC;
       }
   
  -    public char[] getChars()
  -    {
  -     if( hasCharValue ) {
  -         return chars;
  +    public CharChunk getCharChunk() {
  +     return charC;
  +    }
  +
  +    // Convert to bytes !!!
  +    public void toBytes() {
  +     // XXX todo - not used 
  +    }
  +
  +    public void toChars() {
  +     if( ! charC.isNull() ) {
  +         return;
        }
  +     // inefficient
        toString();
  -     hasCharValue=true;
  -     chars=strValue.toCharArray();
  -     charsLen=chars.length;
  -     charsOff=0;
  -     return chars;
  +     char cc[]=strValue.toCharArray();
  +     charC.setChars(cc, 0, cc.length);
       }
       
  -    /**
  -     * Returns the start offset of the bytes.
  -     */
  -    public int getOffset() {
  -     if(type==T_BYTES)
  -         return bytesOff;
  -     if(type==T_CHARS) {
  -         if( ! hasCharValue )
  -             getChars();
  -         return charsOff;
  -     }
  -     return 0;
  -    }
   
       /**
  -     * Returns the length of the bytes.
  +     * Returns the length of the buffer.
        */
       public int getLength() {
        if(type==T_BYTES)
  -         return bytesLen;
  +         return byteC.getLength();
        if(type==T_CHARS) {
  -         if( ! hasCharValue )
  -             getChars();
  -         return charsLen;
  +         return charC.getLength();
        }
        if(type==T_STR)
            return strValue.length();
  @@ -369,39 +314,13 @@
        if( ! caseSensitive )
            return equalsIgnoreCase( s );
        switch (type) {
  -     case T_INT:
  -     case T_DATE:
  -         toString();
  -         // now strValue is valid
        case T_STR:
            if( strValue==null && s!=null) return false;
            return strValue.equals( s );
        case T_CHARS:
  -         char[] c = chars;
  -         int len = charsLen;
  -         if (c == null || len != s.length()) {
  -             return false;
  -         }
  -         int off = charsOff;
  -         for (int i = 0; i < len; i++) {
  -             if (c[off++] != s.charAt(i)) {
  -                 return false;
  -             }
  -         }
  -         return true;
  +         return charC.equals( s );
        case T_BYTES:
  -         byte[] b = bytes;
  -         int blen = bytesLen;
  -         if (b == null || blen != s.length()) {
  -             return false;
  -         }
  -         int boff = bytesOff;
  -         for (int i = 0; i < blen; i++) {
  -             if (b[boff++] != s.charAt(i)) {
  -                 return false;
  -             }
  -         }
  -         return true;
  +         return byteC.equals( s );
        default:
            return false;
        }
  @@ -414,38 +333,13 @@
        */
       public boolean equalsIgnoreCase(String s) {
        switch (type) {
  -     case T_INT:
  -     case T_DATE:
  -         toString(); // now strValue is set
        case T_STR:
            if( strValue==null && s!=null) return false;
            return strValue.equalsIgnoreCase( s );
        case T_CHARS:
  -         char[] c = chars;
  -         int len = charsLen;
  -         if (c == null || len != s.length()) {
  -             return false;
  -         }
  -         int off = charsOff;
  -         for (int i = 0; i < len; i++) {
  -             if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) {
  -                 return false;
  -             }
  -         }
  -         return true;
  +         return charC.equalsIgnoreCase( s );
        case T_BYTES:
  -         byte[] b = bytes;
  -         int blen = bytesLen;
  -         if (b == null || blen != s.length()) {
  -             return false;
  -         }
  -         int boff = bytesOff;
  -         for (int i = 0; i < blen; i++) {
  -             if (Ascii.toLower(b[boff++]) != Ascii.toLower(s.charAt(i))) {
  -                 return false;
  -             }
  -         }
  -         return true;
  +         return byteC.equalsIgnoreCase( s );
        default:
            return false;
        }
  @@ -453,9 +347,6 @@
   
       public boolean equals(MessageBytes mb) {
        switch (type) {
  -     case T_INT:
  -     case T_DATE:
  -         toString(); // now strValue is set
        case T_STR:
            return mb.equals( strValue );
        }
  @@ -471,61 +362,18 @@
        // Deal with the 4 cases ( in fact 3, one is simetric)
        
        if( mb.type == T_CHARS && type==T_CHARS ) {
  -         char b1[]=chars;
  -         char b2[]=mb.chars;
  -         if (b1== null || b2==null || mb.charsLen != charsLen) {
  -             return false;
  -         }
  -         int off1 = charsOff;
  -         int off2 = mb.charsOff;
  -         int len=charsLen;
  -         while ( len-- > 0) {
  -             if (b1[off1++] != b2[off2++]) {
  -                 return false;
  -             }
  -         }
  -         return true;
  -     }
  +         return charC.equals( mb.charC );
  +     } 
        if( mb.type==T_BYTES && type== T_BYTES ) {
  -         byte b1[]=bytes;
  -         byte b2[]=mb.bytes;
  -         if (b1== null || b2==null || mb.bytesLen != bytesLen) {
  -             return false;
  -         }
  -         int off1 = bytesOff;
  -         int off2 = mb.bytesOff;
  -         int len=bytesLen;
  -         while ( len-- > 0) {
  -             if (b1[off1++] != b2[off2++]) {
  -                 return false;
  -             }
  -         }
  -         return true;
  +         return byteC.equals( mb.byteC );
        }
  -
  -     // char/byte or byte/char
  -     MessageBytes mbB=this;
  -     MessageBytes mbC=mb;
  -     
  -     if( type == T_CHARS && mb.type==T_BYTES  ) {
  -         mbB=mb;
  -         mbC=this;
  +     if( mb.type== T_CHARS && type== T_BYTES ) {
  +         return byteC.equals( mb.charC );
        }
  -
  -     byte b1[]=mbB.bytes;
  -     char b2[]=mbC.chars;
  -     if (b1== null || b2==null || mbB.bytesLen != mbC.charsLen) {
  -         return false;
  +     if( mb.type== T_BYTES && type== T_CHARS ) {
  +         return mb.byteC.equals( charC );
        }
  -     int off1 = mbB.bytesOff;
  -     int off2 = mbC.charsOff;
  -     int len=mbB.bytesLen;
  -     
  -     while ( len-- > 0) {
  -         if ( (char)b1[off1++] != b2[off2++]) {
  -             return false;
  -         }
  -     }
  +     // can't happen
        return true;
       }
   
  @@ -539,36 +387,9 @@
        case T_STR:
            return strValue.startsWith( s );
        case T_CHARS:
  -         char[] c = chars;
  -         int len = s.length();
  -         if (c == null || len > charsLen) {
  -             return false;
  -         }
  -         int off = charsOff;
  -         for (int i = 0; i < len; i++) {
  -             if (c[off++] != s.charAt(i)) {
  -                 return false;
  -             }
  -         }
  -         return true;
  +         return charC.startsWith( s );
        case T_BYTES:
  -         byte[] b = bytes;
  -         int blen = s.length();
  -         if (b == null || blen > bytesLen) {
  -             return false;
  -         }
  -         int boff = bytesOff;
  -         for (int i = 0; i < blen; i++) {
  -             if (b[boff++] != s.charAt(i)) {
  -                 return false;
  -             }
  -         }
  -         return true;
  -     case T_INT:
  -     case T_DATE:
  -         String s1=toString();
  -         if( s1==null && s!=null) return false;
  -         return s1.startsWith( s );
  +         return byteC.startsWith( s );
        default:
            return false;
        }
  @@ -594,22 +415,16 @@
       private int hash() {
        int code=0;
        switch (type) {
  -     case T_INT:
  -     case T_DATE:
  -         String s1=toString();
  -         // continue with T_STR - it now have a strValue
        case T_STR:
  +         // We need to use the same hash function
            for (int i = 0; i < strValue.length(); i++) {
                code = code * 37 + strValue.charAt( i );
            }
            return code;
        case T_CHARS:
  -         for (int i = charsOff; i < charsOff + charsLen; i++) {
  -             code = code * 37 + chars[i];
  -         }
  -         return code;
  +         return charC.hash();
        case T_BYTES:
  -         return hashBytes( bytes, bytesOff, bytesLen);
  +         return byteC.hash();
        default:
            return 0;
        }
  @@ -619,49 +434,20 @@
       private int hashIgnoreCase() {
        int code=0;
        switch (type) {
  -     case T_INT:
  -     case T_DATE:
  -         String s1=toString();
  -         // continue with T_STR - it now have a strValue
        case T_STR:
            for (int i = 0; i < strValue.length(); i++) {
                code = code * 37 + Ascii.toLower(strValue.charAt( i ));
            }
            return code;
        case T_CHARS:
  -         for (int i = charsOff; i < charsOff + charsLen; i++) {
  -             code = code * 37 + Ascii.toLower(chars[i]);
  -         }
  -         return code;
  +         return charC.hashIgnoreCase();
        case T_BYTES:
  -         return hashBytesIC( bytes, bytesOff, bytesLen );
  +         return byteC.hashIgnoreCase();
        default:
            return 0;
        }
       }
   
  -    private static int hashBytes( byte bytes[], int bytesOff, int bytesLen ) {
  -     int max=bytesOff+bytesLen;
  -     byte bb[]=bytes;
  -     int code=0;
  -     for (int i = bytesOff; i < max ; i++) {
  -         code = code * 37 + bb[i];
  -     }
  -     return code;
  -    }
  -
  -    private static int hashBytesIC( byte bytes[], int bytesOff,
  -                                 int bytesLen )
  -    {
  -     int max=bytesOff+bytesLen;
  -     byte bb[]=bytes;
  -     int code=0;
  -     for (int i = bytesOff; i < max ; i++) {
  -         code = code * 37 + Ascii.toLower(bb[i]);
  -     }
  -     return code;
  -    }
  -
       public int indexOf(char c) {
        return indexOf( c, 0);
       }
  @@ -672,24 +458,12 @@
        */
       public int indexOf(char c, int starting) {
        switch (type) {
  -     case T_INT:
  -     case T_DATE:
  -         String s1=toString();
  -         // continue with T_STR - it now have a strValue
        case T_STR:
            return strValue.indexOf( c, starting );
        case T_CHARS:
  -         for (int i = charsOff+starting; i < charsOff + charsLen; i++) {
  -             if( c == chars[i] ) return i;
  -         }
  -         return -1;
  +         return charC.indexOf( c, starting);
        case T_BYTES:
  -         int max=bytesOff+bytesLen;
  -         byte bb[]=bytes;
  -         for (int i = bytesOff+starting; i < max ; i++) {
  -             if( (byte)c == bb[i]) return i;
  -         }
  -         return -1;
  +         return byteC.indexOf( c, starting );
        default:
            return -1;
        }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/util/ByteChunk.java
  
  Index: ByteChunk.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.tomcat.util;
  
  import java.text.*;
  import java.util.*;
  import java.io.Serializable;
  
  /**
   * This class is used to represent a chunk of bytes, and
   * utilities to manipulate byte[].
   *
   * In a server it is very important to be able to operate on
   * the original byte[] without converting everything to chars.
   * Some protocols are ASCII only, and some allow different
   * non-UNICODE encodings. The encoding is not known beforehand,
   * and can even change during the execution of the protocol.
   * ( for example a multipart message may have parts with different
   *  encoding )
   *
   * For HTTP it is not very clear how the encoding of RequestURI
   * and mime values can be determined, but it is a great advantage
   * to be able to parse the request without converting to string.
   *
   * @author [EMAIL PROTECTED]
   * @author James Todd [[EMAIL PROTECTED]]
   * @author Costin Manolache
   */
  public final class ByteChunk implements Cloneable, Serializable {
      // byte[]
      private byte[] bytes;
      private int bytesOff;
      private int bytesLen;
      private String enc;
      private boolean isSet=false;
      
      /**
       * Creates a new, uninitialized ByteChunk object.
       */
      public ByteChunk() {
      }
  
      public ByteChunk getClone() {
        try {
            return (ByteChunk)this.clone();
        } catch( Exception ex) {
            return null;
        }
      }
  
      public boolean isNull() {
        return ! isSet; // bytes==null;
      }
      
      /**
       * Resets the message bytes to an uninitialized state.
       */
      public void recycle() {
        bytes = null;
        enc=null;
        isSet=false;
      }
  
      /**
       * Sets the message bytes to the specified subarray of bytes.
       * 
       * @param b the ascii bytes
       * @param off the start offset of the bytes
       * @param len the length of the bytes
       */
      public void setBytes(byte[] b, int off, int len) {
        bytes = b;
        bytesOff = off;
        bytesLen = len;
        isSet=true;
      }
  
      public void setEncoding( String enc ) {
        this.enc=enc;
      }
  
      // convert an int to byte[]
      public void setInt(int i) {
        // XXX TODO
      }
      // -------------------- Conversion and getters --------------------
      public static boolean isUTF8Compatible(String enc) {
        if( enc==null ) return true;
        // add known encodings
        return false;
      }
      
      public String toString() {
        if (null == bytes) {
            return null;
        }
        String strValue=null;
        try {
            if( enc==null )
                strValue=toStringUTF8();
            else {
                strValue=new String(bytes, bytesOff, bytesLen, enc);
                // this will display when we implement I18N
                System.out.println("Converting from bytes to string using " +
                                   enc + ":" + strValue  );
            }
            return strValue;
        } catch (java.io.UnsupportedEncodingException e) {
            return null;  // can't happen
        }
      }
  
      private char[] conversionBuff;
      
      private String toStringUTF8() {
        if( conversionBuff==null || bytesLen > conversionBuff.length ) {
            conversionBuff=new char[bytesLen];
        }
  
        int j=bytesOff;
        for( int i=0; i< bytesLen; i++ ) {
            conversionBuff[i]=(char)bytes[j++];
        }
        return new String( conversionBuff, 0, bytesLen);
      }
  
      public int getInt()
      {
        return Ascii.parseInt(bytes, bytesOff,bytesLen);
      }
  
      // --------------------
      
      /**
       * Returns the message bytes.
       */
      public byte[] getBytes() {
        return bytes;
      }
  
      /**
       * Returns the start offset of the bytes.
       */
      public int getOffset() {
        return bytesOff;
      }
  
      /**
       * Returns the length of the bytes.
       */
      public int getLength() {
        return bytesLen;
      }
  
      // -------------------- equals --------------------
  
      /**
       * Compares the message bytes to the specified String object.
       * @param s the String to compare
       * @return true if the comparison succeeded, false otherwise
       */
      public boolean equals(String s) {
        // XXX ENCODING - this only works if encoding is UTF8-compat
        // ( ok for tomcat, where we compare ascii - header names, etc )!!!
        
        byte[] b = bytes;
        int blen = bytesLen;
        if (b == null || blen != s.length()) {
            return false;
        }
        int boff = bytesOff;
        for (int i = 0; i < blen; i++) {
            if (b[boff++] != s.charAt(i)) {
                return false;
            }
        }
        return true;
      }
  
      /**
       * Compares the message bytes to the specified String object.
       * @param s the String to compare
       * @return true if the comparison succeeded, false otherwise
       */
      public boolean equalsIgnoreCase(String s) {
        byte[] b = bytes;
        int blen = bytesLen;
        if (b == null || blen != s.length()) {
            return false;
        }
        int boff = bytesOff;
        for (int i = 0; i < blen; i++) {
            if (Ascii.toLower(b[boff++]) != Ascii.toLower(s.charAt(i))) {
                return false;
            }
        }
        return true;
      }
  
      public boolean equals( ByteChunk bb ) {
        return equals( bb.getBytes(), bb.getOffset(), bb.getLength());
      }
      
      public boolean equals( byte b2[], int off2, int len2) {
        byte b1[]=bytes;
        if( b1==null && b2==null ) return true;
  
        int len=bytesLen;
        if ( len2 != len || b1==null || b2==null ) 
            return false;
                
        int off1 = bytesOff;
  
        while ( len-- > 0) {
            if (b1[off1++] != b2[off2++]) {
                return false;
            }
        }
        return true;
      }
  
      public boolean equals( CharChunk cc ) {
        return equals( cc.getChars(), cc.getOffset(), cc.getLength());
      }
      
      public boolean equals( char c2[], int off2, int len2) {
        // XXX works only for enc compatible with ASCII/UTF !!!
        byte b1[]=bytes;
        if( c2==null && b1==null ) return true;
        
        if (b1== null || c2==null || bytesLen != len2 ) {
            return false;
        }
        int off1 = bytesOff;
        int len=bytesLen;
        
        while ( len-- > 0) {
            if ( (char)b1[off1++] != c2[off2++]) {
                return false;
            }
        }
        return true;
      }
  
      /**
       * Returns true if the message bytes starts with the specified string.
       * @param s the string
       */
      public boolean startsWith(String s) {
        // Works only if enc==UTF
        byte[] b = bytes;
        int blen = s.length();
        if (b == null || blen > bytesLen) {
            return false;
        }
        int boff = bytesOff;
        for (int i = 0; i < blen; i++) {
            if (b[boff++] != s.charAt(i)) {
                return false;
            }
        }
        return true;
      }
  
      
  
      // -------------------- Hash code  --------------------
  
      // normal hash. 
      public int hash() {
        return hashBytes( bytes, bytesOff, bytesLen);
      }
  
      // hash ignoring case
      public int hashIgnoreCase() {
        return hashBytesIC( bytes, bytesOff, bytesLen );
      }
  
      private static int hashBytes( byte bytes[], int bytesOff, int bytesLen ) {
        int max=bytesOff+bytesLen;
        byte bb[]=bytes;
        int code=0;
        for (int i = bytesOff; i < max ; i++) {
            code = code * 37 + bb[i];
        }
        return code;
      }
  
      private static int hashBytesIC( byte bytes[], int bytesOff,
                                    int bytesLen )
      {
        int max=bytesOff+bytesLen;
        byte bb[]=bytes;
        int code=0;
        for (int i = bytesOff; i < max ; i++) {
            code = code * 37 + Ascii.toLower(bb[i]);
        }
        return code;
      }
  
      /**
       * Returns true if the message bytes starts with the specified string.
       * @param s the string
       */
      public int indexOf(char c, int starting) {
        // Works only for UTF 
        int max=bytesOff+bytesLen;
        byte bb[]=bytes;
        for (int i = bytesOff+starting; i < max ; i++) {
            if( (byte)c == bb[i]) return i;
        }
        return -1;
      }
  
          /** Find a character, no side effects.
       *  @returns index of char if found, -1 if not
       */
      public static int findChar( byte buf[], int start, int end, char c ) {
        byte b=(byte)c;
        int offset = start;
        while (offset < end) {
            if (buf[offset] == b) {
                return offset;
            }
            offset++;
        }
        return -1;
      }
  
      /** Find a character, no side effects.
       *  @returns index of char if found, -1 if not
       */
      public static int findChars( byte buf[], int start, int end, byte c[] ) {
        int clen=c.length;
        int offset = start;
        while (offset < end) {
            for( int i=0; i<clen; i++ ) 
                if (buf[offset] == c[i]) {
                    return offset;
                }
            offset++;
        }
        return -1;
      }
  
      /** Find the first character != c 
       *  @returns index of char if found, -1 if not
       */
      public static int findNotChars( byte buf[], int start, int end, byte c[] )
      {
        int clen=c.length;
        int offset = start;
        boolean found;
                
        while (offset < end) {
            found=true;
            for( int i=0; i<clen; i++ ) {
                if (buf[offset] == c[i]) {
                    found=false;
                    break;
                }
            }
            if( found ) { // buf[offset] != c[0..len]
                return offset;
            }
            offset++;
        }
        return -1;
      }
  
  
  }
  
  
  
  1.1                  jakarta-tomcat/src/share/org/apache/tomcat/util/CharChunk.java
  
  Index: CharChunk.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.tomcat.util;
  
  import java.text.*;
  import java.util.*;
  import java.io.Serializable;
  
  /**
   * Utilities to manipluate char chunks. While String is
   * the easiest way to manipulate chars ( search, substrings, etc),
   * it is known to not be the most efficient solution - Strings are
   * designed as imutable and secure objects.
   * 
   * @author [EMAIL PROTECTED]
   * @author James Todd [[EMAIL PROTECTED]]
   * @author Costin Manolache
   */
  public final class CharChunk implements Cloneable, Serializable {
      // char[]
      private char chars[];
      private int charsOff;
      private int charsLen;
      private boolean isSet=false;    
      /**
       * Creates a new, uninitialized CharChunk object.
       */
      public CharChunk() {
      }
  
      public CharChunk getClone() {
        try {
            return (CharChunk)this.clone();
        } catch( Exception ex) {
            return null;
        }
      }
  
      public boolean isNull() {
        return !isSet;
      }
      
      /**
       * Resets the message bytes to an uninitialized state.
       */
      public void recycle() {
        //      chars=null;
        isSet=false;
      }
  
      public void setChars( char[] c, int off, int len ) {
        recycle();
        chars=c;
        charsOff=off;
        charsLen=len;
      }
  
      // -------------------- Conversion and getters --------------------
  
      public String toString() {
        if( chars==null ) return null;
        return new String( chars, charsOff, charsLen);
      }
  
      public int getInt()
      {
        return Ascii.parseInt(chars, charsOff,
                                charsLen);
      }
      
      public char[] getChars()
      {
        return chars;
      }
      
      /**
       * Returns the start offset of the bytes.
       */
      public int getOffset() {
        return charsOff;
      }
  
      /**
       * Returns the length of the bytes.
       */
      public int getLength() {
        return charsLen;
      }
  
      // -------------------- equals --------------------
  
      /**
       * Compares the message bytes to the specified String object.
       * @param s the String to compare
       * @return true if the comparison succeeded, false otherwise
       */
      public boolean equals(String s) {
        char[] c = chars;
        int len = charsLen;
        if (c == null || len != s.length()) {
            return false;
        }
        int off = charsOff;
        for (int i = 0; i < len; i++) {
            if (c[off++] != s.charAt(i)) {
                return false;
            }
        }
        return true;
      }
  
      /**
       * Compares the message bytes to the specified String object.
       * @param s the String to compare
       * @return true if the comparison succeeded, false otherwise
       */
      public boolean equalsIgnoreCase(String s) {
        char[] c = chars;
        int len = charsLen;
        if (c == null || len != s.length()) {
            return false;
        }
        int off = charsOff;
        for (int i = 0; i < len; i++) {
            if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) {
                return false;
            }
        }
        return true;
      }
  
      public boolean equals(CharChunk cc) {
        return equals( cc.getChars(), cc.getOffset(), cc.getLength());
      }
  
      public boolean equals(char b2[], int off2, int len2) {
        char b1[]=chars;
        if( b1==null && b2==null ) return true;
        
        if (b1== null || b2==null || charsLen != len2) {
            return false;
        }
        int off1 = charsOff;
        int len=charsLen;
        while ( len-- > 0) {
            if (b1[off1++] != b2[off2++]) {
                return false;
            }
        }
        return true;
      }
  
      public boolean equals(byte b2[], int off2, int len2) {
        char b1[]=chars;
        if( b2==null && b1==null ) return true;
  
        if (b1== null || b2==null || charsLen != len2) {
            return false;
        }
        int off1 = charsOff;
        int len=charsLen;
        
        while ( len-- > 0) {
            if ( b1[off1++] != (char)b2[off2++]) {
                return false;
            }
        }
        return true;
      }
      
      /**
       * Returns true if the message bytes starts with the specified string.
       * @param s the string
       */
      public boolean startsWith(String s) {
        char[] c = chars;
        int len = s.length();
        if (c == null || len > charsLen) {
            return false;
        }
        int off = charsOff;
        for (int i = 0; i < len; i++) {
            if (c[off++] != s.charAt(i)) {
                return false;
            }
        }
        return true;
      }
      
  
      // -------------------- Hash code  --------------------
  
      // normal hash. 
      public int hash() {
        int code=0;
        for (int i = charsOff; i < charsOff + charsLen; i++) {
            code = code * 37 + chars[i];
        }
        return code;
      }
  
      // hash ignoring case
      public int hashIgnoreCase() {
        int code=0;
        for (int i = charsOff; i < charsOff + charsLen; i++) {
            code = code * 37 + Ascii.toLower(chars[i]);
        }
        return code;
      }
  
      public int indexOf(char c) {
        return indexOf( c, charsOff);
      }
      
      /**
       * Returns true if the message bytes starts with the specified string.
       * @param s the string
       */
      public int indexOf(char c, int starting) {
        for (int i = charsOff+starting; i < charsOff + charsLen; i++) {
            if( c == chars[i] ) return i;
        }
        return -1;
      }
  
  
  }
  
  
  
  1.1                  
jakarta-tomcat/src/share/org/apache/tomcat/util/collections/MultiMapNamesEnumeration.java
  
  Index: MultiMapNamesEnumeration.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.tomcat.util.collections;
  
  import org.apache.tomcat.util.collections.*;
  import org.apache.tomcat.util.MessageBytes;
  
  import java.io.*;
  import java.util.*;
  import java.text.*;
  
  /** 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).
  */
  public final class MultiMapNamesEnumeration implements Enumeration {
      int pos;
      int size;
      String next;
      MultiMap headers;
  
      // toString and unique options are not implemented -
      // we allways to toString and unique.
      
      /** Create a new multi-map enumeration.
       * @param  headers the collection to enumerate 
       * @param  toString convert each name to string 
       * @param  unique return only unique names
       */
      MultiMapNamesEnumeration(MultiMap headers, boolean toString,
                             boolean unique) {
        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;
      }
  }
  
  
  
  1.1                  
jakarta-tomcat/src/share/org/apache/tomcat/util/collections/MultiMapValuesEnumeration.java
  
  Index: MultiMapValuesEnumeration.java
  ===================================================================
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.tomcat.util.collections;
  
  import org.apache.tomcat.util.collections.*;
  import org.apache.tomcat.util.MessageBytes;
  
  import java.io.*;
  import java.util.*;
  import java.text.*;
  
  /** Enumerate the values for a (possibly ) multiple
   *    value element.
   */
  class MultiMapValuesEnumeration implements Enumeration {
      int pos;
      int size;
      MessageBytes next;
      MultiMap headers;
      String name;
  
      MultiMapValuesEnumeration(MultiMap headers, String name,
                              boolean toString) {
          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();
      }
  }
  
  
  
  1.6       +5 -3      
jakarta-tomcat/src/share/org/apache/tomcat/util/http/Cookies.java
  
  Index: Cookies.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/http/Cookies.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Cookies.java      2000/12/01 21:39:21     1.5
  +++ Cookies.java      2000/12/07 18:34:53     1.6
  @@ -61,6 +61,7 @@
   
   import org.apache.tomcat.util.collections.*;
   import org.apache.tomcat.util.MessageBytes;
  +import org.apache.tomcat.util.ByteChunk;
   import org.apache.tomcat.util.MimeHeaders;
   import org.apache.tomcat.util.DateTool;
   
  @@ -167,9 +168,10 @@
            // Uncomment to test the new parsing code
            if( cookieValue.getType() == MessageBytes.T_BYTES ) {
                if( dbg>0 ) log( "Parsing b[]: " + cookieValue.toString());
  -             processCookieHeader( cookieValue.getBytes(),
  -                                  cookieValue.getOffset(),
  -                                  cookieValue.getLength());
  +             ByteChunk bc=cookieValue.getByteChunk();
  +             processCookieHeader( bc.getBytes(),
  +                                  bc.getOffset(),
  +                                  bc.getLength());
            } else {
                if( dbg>0 ) log( "Parsing S: " + cookieValue.toString());
                processCookieHeader( cookieValue.toString() );
  
  
  
  1.2       +1 -138    
jakarta-tomcat/src/share/org/apache/tomcat/util/http/Headers.java
  
  Index: Headers.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/http/Headers.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Headers.java      2000/11/30 17:42:49     1.1
  +++ Headers.java      2000/12/07 18:34:53     1.2
  @@ -104,21 +104,6 @@
        return super.findIgnoreCase( name, starting );
       }
       
  -    // -------------------- --------------------
  -
  -    /**
  -     * 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 --------------------
       
       /** Create a new named header , return the MessageBytes
  @@ -168,6 +153,7 @@
   
       // bad shortcut - it'll convert to string ( too early probably,
       // encoding is guessed very late )
  +    
       public String getHeader(String name) {
        int pos=findIgnoreCase( name, 0 );
        if( pos <0 ) return null;
  @@ -190,126 +176,3 @@
       }
   }
   
  -/** 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;
  -    MultiMap headers;
  -
  -    NamesEnumerator(MultiMap 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;
  -    MultiMap headers;
  -    String name;
  -
  -    ValuesEnumerator(MultiMap 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 = new MessageBytes();
  -    protected final MessageBytes valueB = new MessageBytes();
  -
  -    /**
  -     * 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;
  -    }
  -}
  
  
  
  1.3       +8 -4      
jakarta-tomcat/src/share/org/apache/tomcat/util/http/Parameters.java
  
  Index: Parameters.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/http/Parameters.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Parameters.java   2000/12/02 08:27:03     1.2
  +++ Parameters.java   2000/12/07 18:34:54     1.3
  @@ -182,11 +182,15 @@
        if( data==null || data.getLength() <= 0 ) return;
   
        if( data.getType() == MessageBytes.T_BYTES ) {
  -         processParameters( data.getBytes(), data.getOffset(),
  -                            data.getLength());
  +         ByteChunk bc=data.getByteChunk();
  +         processParameters( bc.getBytes(), bc.getOffset(),
  +                            bc.getLength());
        } else {
  -         processParameters( data.getChars(), data.getOffset(),
  -                            data.getLength());
  +         if (data.getType()!= MessageBytes.T_CHARS ) 
  +             data.toChars();
  +         CharChunk cc=data.getCharChunk();
  +         processParameters( cc.getChars(), cc.getOffset(),
  +                            cc.getLength());
        }
       }
   
  
  
  

Reply via email to