tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@locus.apache.org
Subject cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util/http Cookies.java Headers.java Parameters.java
Date Thu, 07 Dec 2000 18:34:55 GMT
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 apache@apache.org.
   *
   * 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 dac@eng.sun.com
   * @author James Todd [gonzo@eng.sun.com]
   * @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 apache@apache.org.
   *
   * 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 dac@eng.sun.com
   * @author James Todd [gonzo@eng.sun.com]
   * @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 apache@apache.org.
   *
   * 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 apache@apache.org.
   *
   * 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());
   	}
       }
   
  
  
  

Mime
View raw message