tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject svn commit: r534293 [9/11] - in /tomcat/sandbox/tomcat-lite: ./ bin/ external/ java/ java/org/apache/commons/logging/ java/org/apache/tomcat/lite/ java/org/apache/tomcat/lite/ctxmap/ java/org/apache/tomcat/lite/http/ java/org/apache/tomcat/lite/http11/...
Date Wed, 02 May 2007 02:22:50 GMT
Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/ByteChunk.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/ByteChunk.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/ByteChunk.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/ByteChunk.java Tue May  1 19:22:45 2007
@@ -17,7 +17,6 @@
 package org.apache.tomcat.util.buf;
 
 import java.io.IOException;
-import java.io.Serializable;
 import java.nio.ByteBuffer;
 
 /*
@@ -38,68 +37,13 @@
  * This class is used to represent a chunk of bytes, and
  * utilities to manipulate bytes.
  *
- * The buffer can be modified and used for both input and output.
- *
- * There are 3 modes: 
- * 
- * 1. Wrapping a chunk from another buffer. This was the original use and is the
- * most common use - for example in headers. Typically there is an associated
- * CharChunk and MessageBytes for the char[] representation - but many buffers 
- * will not be converted or will be converted just before use. 
- * 
- * 2. For input, associated with a ByteInputChannel ( or ReadableByteChannel ), 
- * which will be called automatically when the buffer is emtpy. This is used for 
- * the input stream and for the header buffer ( which will be later wrapped in many
- * ByteChunks )
- * 
- * 3. For output, associated ( or not ) with a ByteOutputChannel. The buffer
- * can grow up to a limit ( and will stay allocated to that limit ). When the limit
- * is reached, the channel is used.
- *
- * Various search and append method are defined - similar with String and StringBuffer, but
- * operating on bytes.
- * 
- * In addition, append and substract are used in 2 and 3.
- *
- * This is important because it allows processing the http headers directly on the received bytes,
- * without converting to chars and Strings until the strings are needed. In addition, the charset
- * is determined later, from headers or user code.
  *
  * @author dac@sun.com
  * @author James Todd [gonzo@sun.com]
  * @author Costin Manolache
  * @author Remy Maucherat
  */
-public final class ByteChunk implements Cloneable, Serializable {
-
-    /** Input interface, used when the buffer is emptiy
-     *
-     * Same as java.nio.channel.ReadableByteChannel
-     * @deprecated
-     */
-    public static interface ByteInputChannel {
-        /** 
-         * Read new bytes ( usually the internal conversion buffer ).
-         * The implementation is allowed to ignore the parameters, 
-         * and mutate the chunk if it wishes to implement its own buffering.
-         */
-        public int realReadBytes(byte cbuf[], int off, int len)
-            throws IOException;
-    }
-
-    /** Same as java.nio.channel.WrittableByteChannel.
-     * @deprecated
-     */
-    public static interface ByteOutputChannel {
-        /** 
-         * Send the bytes ( usually the internal conversion buffer ).
-         * Expect 8k output if the buffer is full.
-         */
-        public void realWriteBytes(byte cbuf[], int off, int len)
-            throws IOException;
-    }
-
-    // --------------------
+public final class ByteChunk {
 
     /** Default encoding used to convert to strings. It should be UTF8,
 	as most standards seem to converge, but the servlet API requires
@@ -112,10 +56,8 @@
     //
     // So start == 0, end == limit. Position is not used.
     // 
-    // if isOutout==true - the buffer is used for output. It must be released().
+
     private ByteBuffer bb;
-    private boolean isSet=false; // == ! isNull
-    
     
     private int start=0; // used as ByteBuffer.offset and position
     private int end; // used as limit
@@ -123,76 +65,32 @@
     // not sure it's good to have it here, MessageBytes should deal with this
     private String enc;
 
-    // Probably not needed if callers respect the rules - but good to debug.
-    private boolean inUse = false; // direct access to bb
-    private boolean isOutput=false; // byte buffer in output mode
-    private int mode = 0; 
-    //private boolean optimizedWrite=true;
-
-    // How much can it grow, when data is added. Different from the bb limit,
-    // this is how much we can resize the bb before flushing.
-    private int growLimit=-1;
-
-    // maybe a single in/out channel would be better.
-    private ByteInputChannel in = null;
-    private ByteOutputChannel out = null;
-
-    /*
-     
-    // experiment: specific structure for 2. and 3.
-    static class ByteData {
-        Channel channel; // or in, out
-        
-        int growLimit = -1;
-        String enc; // no need to have it in wrapped buffers
-        
-    }
-    private ByteData byteData;
-    */
+
     /**
      * Creates a new, uninitialized ByteChunk object.
      */
     public ByteChunk() {
     }
 
-    //--------------------
-    
-    public ByteBuffer getBuffer(boolean forWrite) {
-        inUse = true;
-        if( forWrite ) {
-            isOutput = true;
-            // all methods except append should throw exceptions !
-            //  start - end are existing data, end is growing on append
-            // also, start is supposed to be 0 ( or offeset ? )
-            bb.position(end);
-            bb.limit(bb.capacity());
-        }
-        return bb;
-    }
 
-    public void releaseBuffer() {
-        if( isOutput ) {
-            isOutput = false;
-            // start remain the same ( probably 0 )
-            end = bb.position();
-            // flip bb for reading
-            bb.limit(bb.position());
-            bb.position(0);
-        }
-        inUse = false;
-    }
-    
-    
-    public ByteChunk getClone() {
-	try {
-	    return (ByteChunk)this.clone();
-	} catch( Exception ex) {
-	    return null;
-	}
+    /**
+     * Sets the message bytes to the specified subarray of bytes.
+     * Used for 1.
+     * 
+     * @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) {
+        //buff = b;
+        bb=ByteBuffer.wrap( b, off, len );
+        start = off; // also offset in bb.
+        // bb.arrayOffset() == off == start;
+        end = start+ len;
     }
 
     public boolean isNull() {
-	return ! isSet; 
+	return end < 0; 
     }
     
     /**
@@ -201,74 +99,15 @@
     public void recycle() {
 	enc=null;
 	start=0;
-	end=0;
-	isSet=false;
+	end=-1;
         if( bb != null) bb.clear();
-        inUse = false;
         // mode remains - it shouldn't change
-        isOutput = false;
     }
 
     public void reset() {
 	bb=null;
     }
 
-    // -------------------- Setup --------------------
-
-    /**
-     * Prealocate a buffer.
-     * Called by C2B, BufferedInputFilter ( mode 2 ), catalina InputBuffer 
-     * and OutputBuffe,  
-     * 
-     * @param initial
-     */
-    public ByteChunk( int initial ) {
-        allocate( initial, -1 );
-    }
-
-    /** Used for 2. and 3. - allocate the buffer.
-     * 
-     * Called by InternalOutputBuffer, C2B ( for out ).
-     *  
-     * Called by MessageBytes ( out mode ) to hold decoded uri, other temp
-     * storages for request ( long, etc ) 
-     */
-    public void allocate( int initial, int limit  ) {
-	isOutput=true;
-	if( bb==null || bb.capacity() < initial ) {
-	    //buff=new byte[initial];
-            bb=ByteBuffer.allocate(initial);
-	}    
-	this.growLimit=limit;
-	start=0;
-	end=0;
-	isSet=true;
-        mode = 4; // will set to 2 or 3 on first op.
-        //new Throwable().printStackTrace();
-    }
-
-    /**
-     * Sets the message bytes to the specified subarray of bytes.
-     * Used for 1.
-     * 
-     * @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) {
-        //buff = b;
-        bb=ByteBuffer.wrap( b, off, len );
-        start = off; // also offset in bb.
-        // bb.arrayOffset() == off == start;
-        end = start+ len;
-        isSet=true;
-        if( mode > 1 ) {
-            System.err.println("Old mode: " + mode);
-            //new Throwable().printStackTrace();
-        }
-        mode = 1;
-    }
-
     // --------------------------------------
     // Doesn't seem to be used - and it shouldn't be
     //public void setOptimizedWrite(boolean optimizedWrite) {
@@ -279,7 +118,7 @@
 	this.enc=enc;
     }
     
-    public String getEncoding() {
+    String getEncoding() {
         if (enc == null)
             enc=DEFAULT_CHARACTER_ENCODING;
         return enc;
@@ -324,37 +163,6 @@
 	return end-start;
     }
 
-    /** Maximum amount of data in this buffer.
-     *
-     *  If -1 or not set, the buffer will grow undefinitely.
-     *  Can be smaller than the current buffer size ( which will not shrink ).
-     *  When the limit is reached, the buffer will be flushed ( if out is set )
-     *  or throw exception.
-     */
-    public void setLimit(int limit) {
-	this.growLimit=limit;
-    }
-    
-    public int getLimit() {
-	return growLimit;
-    }
-
-    /**
-     * When the buffer is empty, read the data from the input channel.
-     */
-    public void setByteInputChannel(ByteInputChannel in) {
-        this.in = in;
-    }
-
-    /** When the buffer is full, write the data to the output channel.
-     * 	Also used when large amount of data is appended.
-     *
-     *  If not set, the buffer will grow to the limit.
-     */
-    public void setByteOutputChannel(ByteOutputChannel out) {
-	this.out=out;
-    }
-
     public int getEnd() {
 	return end;
     }
@@ -363,241 +171,6 @@
 	end=i;
     }
 
-    // -------------------- Adding data to the buffer --------------------
-    // this is mode 3.
-    
-    /** Append a char, by casting it to byte. This IS NOT intended for unicode.
-     *
-     * @param c
-     * @throws IOException
-     */
-    public void append( char c )
-	throws IOException
-    {
-	append( (byte)c);
-    }
-
-    public void append( byte b )
-	throws IOException
-    {
-	makeSpace( 1 );
-
-	// couldn't make space
-	if( growLimit >0 && end >= growLimit ) {
-	    flushBuffer();
-	}
-	//buff[end++]=b;
-        bb.array()[end++] = b;
-    }
-
-    public void append( ByteChunk src )
-	throws IOException
-    {
-	append( src.getBytes(), src.getStart(), src.getLength());
-    }
-
-    /** Add data to the buffer
-     */
-    public void append( byte src[], int off, int len )
-	throws IOException
-    {
-	// will grow, up to limit
-	makeSpace( len );
-
-	// if we don't have limit: makeSpace can grow as it wants
-	if( growLimit < 0 ) {
-	    // assert: makeSpace made enough space
-	    System.arraycopy( src, off, bb.array(), end, len );
-	    end+=len;
-	    return;
-	}
-
-        // Optimize on a common case.
-        // If the buffer is empty and the source is going to fill up all the
-        // space in buffer, may as well write it directly to the output,
-        // and avoid an extra copy
-        if ( /*optimizedWrite &&*/ len == growLimit && end == start) {
-            out.realWriteBytes( src, off, len );
-            return;
-        }
-	// if we have limit and we're below
-	if( len <= growLimit - end ) {
-	    // makeSpace will grow the buffer to the limit,
-	    // so we have space
-	    System.arraycopy( src, off, bb.array(), end, len );
-	    end+=len;
-	    return;
-	}
-
-	// need more space than we can afford, need to flush
-	// buffer
-
-	// the buffer is already at ( or bigger than ) limit
-
-        // We chunk the data into slices fitting in the buffer limit, although
-        // if the data is written directly if it doesn't fit
-
-        int avail=growLimit-end;
-        System.arraycopy(src, off, bb.array(), end, avail);
-        end += avail;
-
-        flushBuffer();
-
-        int remain = len - avail;
-
-        while (remain > (growLimit - end)) {
-            out.realWriteBytes( src, (off + len) - remain, growLimit - end );
-            remain = remain - (growLimit - end);
-        }
-
-        System.arraycopy(src, (off + len) - remain, bb.array(), end, remain);
-        end += remain;
-
-    }
-
-    /** Send the buffer to the sink. Called by append() when the limit is reached.
-     *  You can also call it explicitely to force the data to be written.
-     *
-     * @throws IOException
-     */
-    public void flushBuffer()
-        throws IOException
-    {
-        //assert out!=null
-        if( out==null ) {
-            throw new IOException( "Buffer overflow, no sink " + growLimit + " " +
-                                   bb.capacity()  );
-        }
-        out.realWriteBytes( bb.array(), start, end-start );
-        end=start;
-    }
-
-
-    /** Make space for len chars. If len is small, allocate
-     *  a reserve space too. Never grow bigger than limit.
-     */
-    private void makeSpace(int count)
-    {
-        // all appends call make space
-        if( mode != 3 ) {
-            if( mode == 4 ) {
-                mode = 3;
-            } else { // mode change
-                new Throwable().printStackTrace();
-            }
-            
-        }
-        
-        ByteBuffer tmp = null;
-
-        int newSize;
-        int desiredSize=end + count;
-
-        // Can't grow above the limit
-        if( growLimit > 0 &&
-            desiredSize > growLimit) {
-            desiredSize=growLimit;
-        }
-
-        if( bb==null ) {
-            if( desiredSize < 256 ) desiredSize=256; // take a minimum
-            bb=ByteBuffer.allocate(desiredSize);
-        }
-        
-        // limit < buf.length ( the buffer is already big )
-        // or we already have space XXX
-        if( desiredSize <= bb.capacity() ) {
-            return;
-        }
-        // grow in larger chunks
-        if( desiredSize < 2 * bb.capacity() ) {
-            newSize= bb.capacity() * 2;
-            if( growLimit >0 &&
-                newSize > growLimit ) newSize=growLimit;
-        } else {
-            newSize= bb.capacity() * 2 + count ;
-            if( growLimit > 0 &&
-                newSize > growLimit ) newSize=growLimit;
-        }
-        tmp=ByteBuffer.allocate(newSize);
-        
-        System.arraycopy(bb.array(), start, tmp.array(), 0, end-start);
-        bb = tmp;
-        tmp = null;
-        end=end-start;
-        start=0;
-    }
-
-    // -------------------- Removing data from the buffer --------------------
-    // mode 2.
-    private void checkMode2() {
-        if( mode != 2 ) {
-            if( mode == 4 ) {
-                System.err.println("Mode 2 buffer");
-                mode = 2;
-            } else { // mode change
-               // new Throwable().printStackTrace();
-            }
-        }        
-    }
-    
-    public int substract()
-        throws IOException {
-
-        checkMode2();
-        if ((end - start) == 0) {
-            if (in == null)
-                return -1;
-            int n = in.realReadBytes( bb.array(), 0, bb.capacity() );
-            if (n < 0)
-                return -1;
-        }
-
-        return (bb.array()[start++] & 0xFF);
-
-    }
-
-    public int substract(ByteChunk src)
-        throws IOException {
-
-        checkMode2();
-        if ((end - start) == 0) {
-            if (in == null)
-                return -1;
-            int n = in.realReadBytes( bb.array(), 0, bb.capacity() );
-            if (n < 0)
-                return -1;
-        }
-
-        int len = getLength();
-        src.append(bb.array(), start, len);
-        start = end;
-        return len;
-
-    }
-
-    public int substract( byte src[], int off, int len )
-        throws IOException {
-
-        checkMode2();
-        if ((end - start) == 0) {
-            if (in == null)
-                return -1;
-            int n = in.realReadBytes( bb.array(), 0, bb.capacity() );
-            if (n < 0)
-                return -1;
-        }
-
-        int n = len;
-        if (len > getLength()) {
-            n = getLength();
-        }
-        System.arraycopy(bb.array(), start, src, off, n);
-        start += n;
-        return n;
-    }
-
-    
     // -------------------- Conversion and getters --------------------
     // all modes
     
@@ -793,6 +366,9 @@
 	return true;
     }
 
+    /** 
+     * 
+     */
     public int indexOf( String src, int srcOff, int srcLen, int myOff ) {
 	char first=src.charAt( srcOff );
 
@@ -945,6 +521,81 @@
         }
         return result;
     }
+
+    // -------------------- @deprecated use --------------------
+
+    /** Used for 2. and 3. - allocate the buffer.
+     * 
+     * Called by InternalOutputBuffer, C2B ( for out ).
+     *  
+     * Called by MessageBytes ( out mode ) to hold decoded uri, other temp
+     * storages for request ( long, etc ) 
+     */
+    void allocate( int initial, int limit  ) {
+        if( bb==null || bb.capacity() < initial ) {
+            //buff=new byte[initial];
+            bb=ByteBuffer.allocate(initial);
+        }    
+        start=0;
+        end=-1;
+    }
+
+    // MessageBytes.duplicate
+    void append( ByteChunk src )
+        throws IOException
+    {
+        append( src.getBytes(), src.getStart(), src.getLength());
+    }
+
+    /** Add data to the buffer
+     */
+    private void append( byte src[], int off, int len )
+        throws IOException
+    {
+        // will grow, up to limit
+        makeSpace( len );
+
+        // if we don't have limit: makeSpace can grow as it wants
+        System.arraycopy( src, off, bb.array(), end, len );
+        end+=len;
+
+    }
+
+    /** Make space for len chars. If len is small, allocate
+     *  a reserve space too. Never grow bigger than limit.
+     */
+    private void makeSpace(int count)
+    {
+        ByteBuffer tmp = null;
+
+        int newSize;
+        int desiredSize=end + count;
+
+        if( bb==null ) {
+            if( desiredSize < 256 ) desiredSize=256; // take a minimum
+            bb=ByteBuffer.allocate(desiredSize);
+        }
+        
+        // limit < buf.length ( the buffer is already big )
+        // or we already have space XXX
+        if( desiredSize <= bb.capacity() ) {
+            return;
+        }
+        // grow in larger chunks
+        if( desiredSize < 2 * bb.capacity() ) {
+            newSize= bb.capacity() * 2;
+        } else {
+            newSize= bb.capacity() * 2 + count ;
+        }
+        tmp=ByteBuffer.allocate(newSize);
+        
+        System.arraycopy(bb.array(), start, tmp.array(), 0, end-start);
+        bb = tmp;
+        tmp = null;
+        end=end-start;
+        start=0;
+    }
+
     
     
 }

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/CBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/CBuffer.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/CBuffer.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/CBuffer.java Tue May  1 19:22:45 2007
@@ -0,0 +1,521 @@
+/*
+ *  Copyright 1999-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.tomcat.util.buf;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Serializable;
+
+/**
+ * Growable char buffer, with read/write methods.
+ * 
+ * Used in MessageReader, MessageWriter for tomcat IO.
+ * 
+ * @author Costin Manolache
+ */
+public final class CBuffer implements Cloneable, Serializable, CharSequence {
+
+    // Input interface, used when the buffer is emptied.
+    public static interface CharInputChannel {
+        /** 
+         * Read new bytes ( usually the internal conversion buffer ).
+         * The implementation is allowed to ignore the parameters, 
+         * and mutate the chunk if it wishes to implement its own buffering.
+         */
+        public int realReadChars(char cbuf[], int off, int len)
+            throws IOException;
+    }
+    /**
+     *  When we need more space we'll either
+     *  grow the buffer ( up to the limit ) or send it to a channel.
+     */
+    public static interface CharOutputChannel {
+	/** Send the bytes ( usually the internal conversion buffer ).
+	 *  Expect 8k output if the buffer is full.
+	 */
+        public void realWriteChars(char cbuf[], int off, int len)
+            throws IOException;
+    }
+    
+    // -------------------- 
+    // char[]
+    private char buff[];
+
+    private int start;
+    private int end;
+
+    private boolean isSet=false;  // XXX 
+
+    // -1: grow undefinitely
+    // maximum amount to be cached
+    private int limit=-1;
+
+    private CharInputChannel in = null;
+    private CharOutputChannel out = null;
+    
+    private boolean optimizedWrite=true;
+
+    /**
+     * Creates a new, uninitialized CharChunk object.
+     */
+    public CBuffer() {
+    }
+
+    public CBuffer(int size) {
+	allocate( size, -1 );
+    }
+
+    // --------------------
+    
+    public CBuffer getClone() {
+	try {
+	    return (CBuffer)this.clone();
+	} catch( Exception ex) {
+	    return null;
+	}
+    }
+
+    public boolean isNull() {
+	if( end > 0 ) return false;
+	return !isSet; //XXX 
+    }
+    
+    /**
+     * Resets the message bytes to an uninitialized state.
+     */
+    public void recycle() {
+	//	buff=null;
+	isSet=false; // XXX
+	start=0;
+	end=0;
+    }
+
+    public void reset() {
+	buff=null;
+    }
+
+    // -------------------- Setup --------------------
+
+    public void allocate( int initial, int limit  ) {
+	if( buff==null || buff.length < initial ) {
+	    buff=new char[initial];
+	}
+	this.limit=limit;
+	start=0;
+	end=0;
+	isSet=true;
+    }
+
+
+    public void setOptimizedWrite(boolean optimizedWrite) {
+        this.optimizedWrite = optimizedWrite;
+    }
+
+    public void setChars( char[] c, int off, int len ) {
+        buff=c;
+        start=off;
+        end=start + len;
+        isSet=true;
+    }
+
+    /** Maximum amount of data in this buffer.
+     *
+     *  If -1 or not set, the buffer will grow undefinitely.
+     *  Can be smaller than the current buffer size ( which will not shrink ).
+     *  When the limit is reached, the buffer will be flushed ( if out is set )
+     *  or throw exception.
+     */
+    public void setLimit(int limit) {
+	this.limit=limit;
+    }
+    
+    public int getLimit() {
+	return limit;
+    }
+
+    /**
+     * When the buffer is empty, read the data from the input channel.
+     */
+    public void setCharInputChannel(CharInputChannel in) {
+        this.in = in;
+    }
+
+    /** When the buffer is full, write the data to the output channel.
+     * 	Also used when large amount of data is appended.
+     *
+     *  If not set, the buffer will grow to the limit.
+     */
+    public void setCharOutputChannel(CharOutputChannel out) {
+	this.out=out;
+    }
+
+    // compat 
+    public char[] getChars()
+    {
+	return getBuffer();
+    }
+    
+    public char[] getBuffer()
+    {
+	return buff;
+    }
+    
+    /**
+     * Returns the start offset of the bytes.
+     * For output this is the end of the buffer.
+     */
+    public int getStart() {
+	return start;
+    }
+    
+    public int getOffset() {
+	return start;
+    }
+
+    /**
+     * Returns the start offset of the bytes.
+     */
+    public void setOffset(int off) {
+	start=off;
+    }
+
+    /**
+     * Returns the length of the bytes.
+     */
+    public int getLength() {
+	return end-start;
+    }
+
+
+    public int getEnd() {
+	return end;
+    }
+
+    public void setEnd( int i ) {
+	end=i;
+    }
+
+    // -------------------- Adding data --------------------
+    
+    public void append( char b )
+	throws IOException
+    {
+	makeSpace( 1 );
+
+	// couldn't make space
+	if( limit >0 && end >= limit ) {
+	    flushBuffer();
+	}
+	buff[end++]=b;
+    }
+    
+    public void append( CBuffer src )
+	throws IOException
+    {
+	append( src.getBuffer(), src.getOffset(), src.getLength());
+    }
+    
+    public void append( CharSequence src, int off, int len) 
+        throws IOException {
+      makeSpace(len);
+      for (int i = off; i < len; i++) {
+        append(src.charAt(i));
+      }
+    }
+
+    /** Add data to the buffer
+     */
+    public void append( char src[], int off, int len )
+	throws IOException
+    {
+	// will grow, up to limit
+	makeSpace( len );
+
+	// if we don't have limit: makeSpace can grow as it wants
+	if( limit < 0 ) {
+	    // assert: makeSpace made enough space
+	    System.arraycopy( src, off, buff, end, len );
+	    end+=len;
+	    return;
+	}
+
+        // Optimize on a common case.
+        // If the source is going to fill up all the space in buffer, may
+        // as well write it directly to the output, and avoid an extra copy
+        if ( optimizedWrite && len == limit && end == start) {
+            out.realWriteChars( src, off, len );
+            return;
+        }
+	
+	// if we have limit and we're below
+	if( len <= limit - end ) {
+	    // makeSpace will grow the buffer to the limit,
+	    // so we have space
+	    System.arraycopy( src, off, buff, end, len );
+            
+	    end+=len;
+	    return;
+	}
+
+	// need more space than we can afford, need to flush
+	// buffer
+
+	// the buffer is already at ( or bigger than ) limit
+	
+	// Optimization:
+	// If len-avail < length ( i.e. after we fill the buffer with
+	// what we can, the remaining will fit in the buffer ) we'll just
+	// copy the first part, flush, then copy the second part - 1 write
+	// and still have some space for more. We'll still have 2 writes, but
+	// we write more on the first.
+
+	if( len + end < 2 * limit ) {
+	    /* If the request length exceeds the size of the output buffer,
+	       flush the output buffer and then write the data directly.
+	       We can't avoid 2 writes, but we can write more on the second
+	    */
+	    int avail=limit-end;
+	    System.arraycopy(src, off, buff, end, avail);
+	    end += avail;
+	    
+	    flushBuffer();
+	    
+	    System.arraycopy(src, off+avail, buff, end, len - avail);
+	    end+= len - avail;
+	    
+	} else {	// len > buf.length + avail
+	    // long write - flush the buffer and write the rest
+	    // directly from source
+	    flushBuffer();
+	    
+	    out.realWriteChars( src, off, len );
+	}
+    }
+
+
+    /** Add data to the buffer
+     */
+    public void append( StringBuffer sb )
+	throws IOException
+    {
+	int len=sb.length();
+
+	// will grow, up to limit
+	makeSpace( len );
+
+	// if we don't have limit: makeSpace can grow as it wants
+	if( limit < 0 ) {
+	    // assert: makeSpace made enough space
+	    sb.getChars(0, len, buff, end );
+	    end+=len;
+	    return;
+	}
+
+	int off=0;
+	int sbOff = off;
+	int sbEnd = off + len;
+	while (sbOff < sbEnd) {
+	    int d = min(limit - end, sbEnd - sbOff);
+	    sb.getChars( sbOff, sbOff+d, buff, end);
+	    sbOff += d;
+	    end += d;
+	    if (end >= limit)
+		flushBuffer();
+	}
+    }
+
+    /**  Read from the reader, growing the buffer
+      */
+    public void append(Reader conv) throws IOException {
+      while( true ) { // conv.ready() ) {
+          int cnt=conv.read( buff, end, buff.length - end );
+          if( cnt <= 0 ) {
+              return;
+          }
+          end += cnt;
+          makeSpace(8196);
+      }
+    }
+
+    /** Append a string to the buffer
+     */
+    public void append(String s) throws IOException {
+        append(s, 0, s.length());
+    }
+    
+    /** Append a string to the buffer
+     */
+    public void append(String s, int off, int len) throws IOException {
+	if (s==null) return;
+	
+	// will grow, up to limit
+	makeSpace( len );
+
+	// if we don't have limit: makeSpace can grow as it wants
+	if( limit < 0 ) {
+	    // assert: makeSpace made enough space
+	    s.getChars(off, off+len, buff, end );
+	    end+=len;
+	    return;
+	}
+
+	int sOff = off;
+	int sEnd = off + len;
+	while (sOff < sEnd) {
+	    int d = min(limit - end, sEnd - sOff);
+	    s.getChars( sOff, sOff+d, buff, end);
+	    sOff += d;
+	    end += d;
+	    if (end >= limit)
+		flushBuffer();
+	}
+    }
+    
+    // -------------------- Removing data from the buffer --------------------
+
+    public int substract()
+        throws IOException {
+
+        if ((end - start) == 0) {
+            if (in == null)
+                return -1;
+            int n = in.realReadChars(buff, end, buff.length - end);
+            if (n < 0)
+                return -1;
+        }
+
+        return (buff[start++]);
+
+    }
+
+    public int substract(CBuffer src)
+        throws IOException {
+
+        if ((end - start) == 0) {
+            if (in == null)
+                return -1;
+            int n = in.realReadChars( buff, end, buff.length - end);
+            if (n < 0)
+                return -1;
+        }
+
+        int len = getLength();
+        src.append(buff, start, len);
+        start = end;
+        return len;
+
+    }
+
+    public int substract( char src[], int off, int len )
+        throws IOException {
+
+        if ((end - start) == 0) {
+            if (in == null)
+                return -1;
+            int n = in.realReadChars( buff, end, buff.length - end);
+            if (n < 0)
+                return -1;
+        }
+
+        int n = len;
+        if (len > getLength()) {
+            n = getLength();
+        }
+        System.arraycopy(buff, start, src, off, n);
+        start += n;
+        return n;
+
+    }
+
+
+    public void flushBuffer()
+	throws IOException
+    {
+	//assert out!=null
+	if( out==null ) {
+	    throw new IOException( "Buffer overflow, no sink " + limit + " " +
+				   buff.length  );
+	}
+	out.realWriteChars( buff, start, end - start );
+	end=start;
+    }
+
+    /** Make space for len chars. If len is small, allocate
+     *	a reserve space too. Never grow bigger than limit.
+     */
+    private void makeSpace(int count)
+    {
+	char[] tmp = null;
+
+	int newSize;
+	int desiredSize=end + count;
+
+	// Can't grow above the limit
+	if( limit > 0 &&
+	    desiredSize > limit) {
+	    desiredSize=limit;
+	}
+
+	if( buff==null ) {
+	    if( desiredSize < 256 ) desiredSize=256; // take a minimum
+	    buff=new char[desiredSize];
+	}
+
+	// limit < buf.length ( the buffer is already big )
+	// or we already have space XXX
+	if( desiredSize <= buff.length) {
+	    return;
+	}
+	// grow in larger chunks
+	if( desiredSize < 2 * buff.length ) {
+	    newSize= buff.length * 2;
+	    if( limit >0 &&
+		newSize > limit ) newSize=limit;
+	    tmp=new char[newSize];
+	} else {
+	    newSize= buff.length * 2 + count ;
+	    if( limit > 0 &&
+		newSize > limit ) newSize=limit;
+	    tmp=new char[newSize];
+	}
+	
+	System.arraycopy(buff, start, tmp, start, end-start);
+	buff = tmp;
+	tmp = null;
+    }
+
+    private int min(int a, int b) {
+	if (a < b) return a;
+	return b;
+    }
+
+    public char charAt(int index) {
+      return buff[start + index];
+    }
+
+    public int length() {
+      return getLength();
+    }
+
+    public CharSequence subSequence(int seqstart, int seqend) {
+      // Retrun the char chunk - lighter
+      CharChunk cc = new CharChunk();
+      cc.setChars(buff, start + seqstart, start + seqend);
+      return cc;
+    }
+
+}

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/CharChunk.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/CharChunk.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/CharChunk.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/CharChunk.java Tue May  1 19:22:45 2007
@@ -17,7 +17,6 @@
 package org.apache.tomcat.util.buf;
 
 import java.io.IOException;
-import java.io.Serializable;
 
 /**
  * Utilities to manipluate char chunks. While String is
@@ -25,152 +24,49 @@
  * it is known to not be the most efficient solution - Strings are
  * designed as imutable and secure objects.
  * 
+ * @deprecated - too char[] centric, not needed
  * @author dac@sun.com
  * @author James Todd [gonzo@sun.com]
  * @author Costin Manolache
  * @author Remy Maucherat
  */
-public final class CharChunk implements Cloneable, Serializable {
-
-    // Input interface, used when the buffer is emptied.
-    public static interface CharInputChannel {
-        /** 
-         * Read new bytes ( usually the internal conversion buffer ).
-         * The implementation is allowed to ignore the parameters, 
-         * and mutate the chunk if it wishes to implement its own buffering.
-         */
-        public int realReadChars(char cbuf[], int off, int len)
-            throws IOException;
-    }
-    /**
-     *  When we need more space we'll either
-     *  grow the buffer ( up to the limit ) or send it to a channel.
-     */
-    public static interface CharOutputChannel {
-	/** Send the bytes ( usually the internal conversion buffer ).
-	 *  Expect 8k output if the buffer is full.
-	 */
-        public void realWriteChars(char cbuf[], int off, int len)
-            throws IOException;
-    }
-    
-    // -------------------- 
-    // char[]
+public final class CharChunk implements CharSequence {
+    // Buffer and 2 pointers. 
     private char buff[];
-
     private int start;
-    private int end;
-
-    private boolean isSet=false;  // XXX 
-
-    private boolean isOutput=false;
-
-    // -1: grow undefinitely
-    // maximum amount to be cached
-    private int limit=-1;
-
-    private CharInputChannel in = null;
-    private CharOutputChannel out = null;
-    
-    private boolean optimizedWrite=true;
+    private int end; // negative for 'null'
 
     /**
      * Creates a new, uninitialized CharChunk object.
      */
-    public CharChunk() {
+    CharChunk() {
     }
 
-    public CharChunk(int size) {
-	allocate( size, -1 );
+    /** 
+     * Wrap an existing char[]
+     * Used in MessageBytes, StringCache and Parameters.
+     */
+    void setChars( char[] c, int off, int len ) {
+        buff=c;
+        start=off;
+        end=start + len;
     }
 
     // --------------------
     
-    public CharChunk getClone() {
-	try {
-	    return (CharChunk)this.clone();
-	} catch( Exception ex) {
-	    return null;
-	}
-    }
-
     public boolean isNull() {
-	if( end > 0 ) return false;
-	return !isSet; //XXX 
+      return end < 0;
     }
     
     /**
      * Resets the message bytes to an uninitialized state.
      */
     public void recycle() {
-	//	buff=null;
-	isSet=false; // XXX
-	start=0;
-	end=0;
-    }
-
-    public void reset() {
-	buff=null;
-    }
-
-    // -------------------- Setup --------------------
-
-    public void allocate( int initial, int limit  ) {
-	isOutput=true;
-	if( buff==null || buff.length < initial ) {
-	    buff=new char[initial];
-	}
-	this.limit=limit;
+        buff = null;
 	start=0;
-	end=0;
-	isOutput=true;
-	isSet=true;
-    }
-
-
-    public void setOptimizedWrite(boolean optimizedWrite) {
-        this.optimizedWrite = optimizedWrite;
-    }
-
-    public void setChars( char[] c, int off, int len ) {
-        buff=c;
-        start=off;
-        end=start + len;
-        isSet=true;
-    }
-
-    /** Maximum amount of data in this buffer.
-     *
-     *  If -1 or not set, the buffer will grow undefinitely.
-     *  Can be smaller than the current buffer size ( which will not shrink ).
-     *  When the limit is reached, the buffer will be flushed ( if out is set )
-     *  or throw exception.
-     */
-    public void setLimit(int limit) {
-	this.limit=limit;
-    }
-    
-    public int getLimit() {
-	return limit;
-    }
-
-    /**
-     * When the buffer is empty, read the data from the input channel.
-     */
-    public void setCharInputChannel(CharInputChannel in) {
-        this.in = in;
-    }
-
-    /** When the buffer is full, write the data to the output channel.
-     * 	Also used when large amount of data is appended.
-     *
-     *  If not set, the buffer will grow to the limit.
-     */
-    public void setCharOutputChannel(CharOutputChannel out) {
-	this.out=out;
+	end=-1;
     }
 
-    // compat 
     public char[] getChars()
     {
 	return getBuffer();
@@ -216,273 +112,6 @@
 	end=i;
     }
 
-    // -------------------- Adding data --------------------
-    
-    public void append( char b )
-	throws IOException
-    {
-	makeSpace( 1 );
-
-	// couldn't make space
-	if( limit >0 && end >= limit ) {
-	    flushBuffer();
-	}
-	buff[end++]=b;
-    }
-    
-    public void append( CharChunk src )
-	throws IOException
-    {
-	append( src.getBuffer(), src.getOffset(), src.getLength());
-    }
-
-    /** Add data to the buffer
-     */
-    public void append( char src[], int off, int len )
-	throws IOException
-    {
-	// will grow, up to limit
-	makeSpace( len );
-
-	// if we don't have limit: makeSpace can grow as it wants
-	if( limit < 0 ) {
-	    // assert: makeSpace made enough space
-	    System.arraycopy( src, off, buff, end, len );
-	    end+=len;
-	    return;
-	}
-
-        // Optimize on a common case.
-        // If the source is going to fill up all the space in buffer, may
-        // as well write it directly to the output, and avoid an extra copy
-        if ( optimizedWrite && len == limit && end == start) {
-            out.realWriteChars( src, off, len );
-            return;
-        }
-	
-	// if we have limit and we're below
-	if( len <= limit - end ) {
-	    // makeSpace will grow the buffer to the limit,
-	    // so we have space
-	    System.arraycopy( src, off, buff, end, len );
-            
-	    end+=len;
-	    return;
-	}
-
-	// need more space than we can afford, need to flush
-	// buffer
-
-	// the buffer is already at ( or bigger than ) limit
-	
-	// Optimization:
-	// If len-avail < length ( i.e. after we fill the buffer with
-	// what we can, the remaining will fit in the buffer ) we'll just
-	// copy the first part, flush, then copy the second part - 1 write
-	// and still have some space for more. We'll still have 2 writes, but
-	// we write more on the first.
-
-	if( len + end < 2 * limit ) {
-	    /* If the request length exceeds the size of the output buffer,
-	       flush the output buffer and then write the data directly.
-	       We can't avoid 2 writes, but we can write more on the second
-	    */
-	    int avail=limit-end;
-	    System.arraycopy(src, off, buff, end, avail);
-	    end += avail;
-	    
-	    flushBuffer();
-	    
-	    System.arraycopy(src, off+avail, buff, end, len - avail);
-	    end+= len - avail;
-	    
-	} else {	// len > buf.length + avail
-	    // long write - flush the buffer and write the rest
-	    // directly from source
-	    flushBuffer();
-	    
-	    out.realWriteChars( src, off, len );
-	}
-    }
-
-
-    /** Add data to the buffer
-     */
-    public void append( StringBuffer sb )
-	throws IOException
-    {
-	int len=sb.length();
-
-	// will grow, up to limit
-	makeSpace( len );
-
-	// if we don't have limit: makeSpace can grow as it wants
-	if( limit < 0 ) {
-	    // assert: makeSpace made enough space
-	    sb.getChars(0, len, buff, end );
-	    end+=len;
-	    return;
-	}
-
-	int off=0;
-	int sbOff = off;
-	int sbEnd = off + len;
-	while (sbOff < sbEnd) {
-	    int d = min(limit - end, sbEnd - sbOff);
-	    sb.getChars( sbOff, sbOff+d, buff, end);
-	    sbOff += d;
-	    end += d;
-	    if (end >= limit)
-		flushBuffer();
-	}
-    }
-
-    /** Append a string to the buffer
-     */
-    public void append(String s) throws IOException {
-        append(s, 0, s.length());
-    }
-    
-    /** Append a string to the buffer
-     */
-    public void append(String s, int off, int len) throws IOException {
-	if (s==null) return;
-	
-	// will grow, up to limit
-	makeSpace( len );
-
-	// if we don't have limit: makeSpace can grow as it wants
-	if( limit < 0 ) {
-	    // assert: makeSpace made enough space
-	    s.getChars(off, off+len, buff, end );
-	    end+=len;
-	    return;
-	}
-
-	int sOff = off;
-	int sEnd = off + len;
-	while (sOff < sEnd) {
-	    int d = min(limit - end, sEnd - sOff);
-	    s.getChars( sOff, sOff+d, buff, end);
-	    sOff += d;
-	    end += d;
-	    if (end >= limit)
-		flushBuffer();
-	}
-    }
-    
-    // -------------------- Removing data from the buffer --------------------
-
-    public int substract()
-        throws IOException {
-
-        if ((end - start) == 0) {
-            if (in == null)
-                return -1;
-            int n = in.realReadChars(buff, end, buff.length - end);
-            if (n < 0)
-                return -1;
-        }
-
-        return (buff[start++]);
-
-    }
-
-    public int substract(CharChunk src)
-        throws IOException {
-
-        if ((end - start) == 0) {
-            if (in == null)
-                return -1;
-            int n = in.realReadChars( buff, end, buff.length - end);
-            if (n < 0)
-                return -1;
-        }
-
-        int len = getLength();
-        src.append(buff, start, len);
-        start = end;
-        return len;
-
-    }
-
-    public int substract( char src[], int off, int len )
-        throws IOException {
-
-        if ((end - start) == 0) {
-            if (in == null)
-                return -1;
-            int n = in.realReadChars( buff, end, buff.length - end);
-            if (n < 0)
-                return -1;
-        }
-
-        int n = len;
-        if (len > getLength()) {
-            n = getLength();
-        }
-        System.arraycopy(buff, start, src, off, n);
-        start += n;
-        return n;
-
-    }
-
-
-    public void flushBuffer()
-	throws IOException
-    {
-	//assert out!=null
-	if( out==null ) {
-	    throw new IOException( "Buffer overflow, no sink " + limit + " " +
-				   buff.length  );
-	}
-	out.realWriteChars( buff, start, end - start );
-	end=start;
-    }
-
-    /** Make space for len chars. If len is small, allocate
-     *	a reserve space too. Never grow bigger than limit.
-     */
-    private void makeSpace(int count)
-    {
-	char[] tmp = null;
-
-	int newSize;
-	int desiredSize=end + count;
-
-	// Can't grow above the limit
-	if( limit > 0 &&
-	    desiredSize > limit) {
-	    desiredSize=limit;
-	}
-
-	if( buff==null ) {
-	    if( desiredSize < 256 ) desiredSize=256; // take a minimum
-	    buff=new char[desiredSize];
-	}
-
-	// limit < buf.length ( the buffer is already big )
-	// or we already have space XXX
-	if( desiredSize <= buff.length) {
-	    return;
-	}
-	// grow in larger chunks
-	if( desiredSize < 2 * buff.length ) {
-	    newSize= buff.length * 2;
-	    if( limit >0 &&
-		newSize > limit ) newSize=limit;
-	    tmp=new char[newSize];
-	} else {
-	    newSize= buff.length * 2 + count ;
-	    if( limit > 0 &&
-		newSize > limit ) newSize=limit;
-	    tmp=new char[newSize];
-	}
-	
-	System.arraycopy(buff, start, tmp, start, end-start);
-	buff = tmp;
-	tmp = null;
-    }
     
     // -------------------- Conversion and getters --------------------
 
@@ -689,10 +318,99 @@
 	return -1;
     }
 
-    // -------------------- utils
-    private int min(int a, int b) {
-	if (a < b) return a;
-	return b;
+
+    public char charAt(int index) {
+      return buff[start + index];
+    }
+
+    public int length() {
+      if (end < 0) return 0;
+      return end - start;
+    }
+
+    public CharSequence subSequence(int seqstart, int end) {
+      CharChunk cc = new CharChunk();
+      cc.setChars(buff, start + seqstart, start + end);
+      return cc;
+    }
+    
+    // -------------------- @deprecated uses --------------------
+    
+    // Not wrapping - should be CBuffer. Used in MessageBytes, 
+    void allocate( int initial, int limit  ) {
+        if( buff==null || buff.length < initial ) {
+            buff=new char[initial];
+        }
+        if (limit >= 0) {
+            throw new RuntimeException();
+        }
+        start=0;
+        end=-1;
     }
 
+    // MessageBytes.duplicate()
+    void append( CharChunk src )
+        throws IOException
+    {
+        append( src.getBuffer(), src.getOffset(), src.getLength());
+    }
+
+    private void append( char src[], int off, int len )
+        throws IOException
+    {
+        makeSpace( len );
+
+        System.arraycopy( src, off, buff, end, len );
+        end+=len;
+    }
+
+    // WebappServletMapper
+    public void append(String s, int off, int len) throws IOException {
+        if (s==null) return;
+        
+        makeSpace( len );
+        s.getChars(off, off+len, buff, end );
+        end+=len;
+    }
+
+    // WebappServletMapper 
+    public void append( char b )
+        throws IOException
+    {
+        makeSpace( 1 );
+        buff[end++]=b;
+    }
+    
+    /** Make space for len chars. If len is small, allocate
+     *  a reserve space too. Never grow bigger than limit.
+     */
+    private void makeSpace(int count)
+    {
+        char[] tmp = null;
+
+        int newSize;
+        int desiredSize=end + count;
+
+        if( buff==null ) {
+            if( desiredSize < 256 ) desiredSize=256; // take a minimum
+            buff=new char[desiredSize];
+        }
+
+        if( desiredSize <= buff.length) {
+            return;
+        }
+        // grow in larger chunks
+        if( desiredSize < 2 * buff.length ) {
+            newSize= buff.length * 2;
+            tmp=new char[newSize];
+        } else {
+            newSize= buff.length * 2 + count ;
+            tmp=new char[newSize];
+        }
+        
+        System.arraycopy(buff, start, tmp, start, end-start);
+        buff = tmp;
+        tmp = null;
+    }
+    
 }

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/MessageBytes.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/MessageBytes.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/MessageBytes.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/MessageBytes.java Tue May  1 19:22:45 2007
@@ -16,10 +16,8 @@
 
 package org.apache.tomcat.util.buf;
 
-import java.text.*;
-import java.util.*;
-import java.io.Serializable;
 import java.io.IOException;
+import java.io.Serializable;
 
 /**
  * This class is used to represent a subarray of bytes in an HTTP message.
@@ -44,18 +42,18 @@
  */
 public final class MessageBytes implements Cloneable, Serializable {
     // primary type ( whatever is set as original value )
-    private int type = T_NULL;
+    private byte type = T_NULL;
 
-    public static final int T_NULL = 0;
+    public static final byte T_NULL = 0;
     /** getType() is T_STR if the the object used to create the MessageBytes
         was a String */
-    public static final int T_STR  = 1;
+    public static final byte T_STR  = 1;
     /** getType() is T_STR if the the object used to create the MessageBytes
         was a byte[] */ 
-    public static final int T_BYTES = 2;
+    public static final byte T_BYTES = 2;
     /** getType() is T_STR if the the object used to create the MessageBytes
         was a char[] */ 
-    public static final int T_CHARS = 3;
+    public static final byte T_CHARS = 3;
 
     private int hashCode=0;
     // did we computed the hashcode ? 
@@ -76,8 +74,6 @@
 
     /**
      * Creates a new, uninitialized MessageBytes object.
-     * @deprecated Use static newInstance() in order to allow
-     *   future hooks.
      */
     public MessageBytes() {
     }
@@ -85,7 +81,7 @@
     /** Construct a new MessageBytes instance
      */
     public static MessageBytes newInstance() {
-	return factory.newInstance();
+	return new MessageBytes();
     }
 
     /** Configure the case sensitivity
@@ -103,9 +99,7 @@
     }
 
     public boolean isNull() {
-//		should we check also hasStrValue ???
-		return byteC.isNull() && charC.isNull() && ! hasStrValue;
-	// bytes==null && strValue==null;
+      return byteC.isNull() && charC.isNull() && ! hasStrValue;
     }
     
     /**
@@ -121,21 +115,8 @@
 
 	hasStrValue=false;
 	hasHashCode=false;
-	hasIntValue=false;
-        hasLongValue=false;
-	hasDateValue=false;	
     }
     
-    /** Allocate a byte buffer to use.
-     * 
-     * @param initial
-     * @param limit
-     */
-    public void allocate( int initial, int limit ) {
-       byteC.allocate(initial, limit); 
-    }
-
-
     /**
      * Sets the content to the specified subarray of bytes.
      *
@@ -148,9 +129,6 @@
         type=T_BYTES;
         hasStrValue=false;
         hasHashCode=false;
-        hasIntValue=false;
-        hasLongValue=false;
-        hasDateValue=false; 
     }
 
     /** Set the encoding. If the object was constructed from bytes[]. any
@@ -178,9 +156,6 @@
         type=T_CHARS;
         hasStrValue=false;
         hasHashCode=false;
-        hasIntValue=false;
-        hasLongValue=false;
-        hasDateValue=false; 
     }
 
     /** Remove the cached string value. Use it after a conversion on the
@@ -205,9 +180,6 @@
         strValue=s;
         hasStrValue=true;
         hasHashCode=false;
-        hasIntValue=false;
-        hasLongValue=false;
-        hasDateValue=false; 
         type=T_STR;
     }
 
@@ -229,6 +201,24 @@
 	}
 	return null;
     }
+    
+    public void convertToAscii() {
+        if (getType() != MessageBytes.T_BYTES) {
+            return;
+        }
+        ByteChunk bc = getByteChunk();
+        CharChunk cc = getCharChunk();
+        cc.allocate(bc.getLength(), -1);
+
+        // Default encoding: fast conversion
+        byte[] bbuf = bc.getBuffer();
+        char[] cbuf = cc.getBuffer();
+        int start = bc.getStart();
+        for (int i = 0; i < bc.getLength(); i++) {
+            cbuf[i] = (char) (bbuf[i + start] & 0xff);
+        }
+        setChars(cbuf, 0, bc.getLength());
+    }
 
     //----------------------------------------
     /** Return the type of the original content. Can be
@@ -238,6 +228,18 @@
 	return type;
     }
     
+    /** 
+     * True if the MessageBytes has been converted to or is backed by byte, 
+     * false if backed by chars
+     *
+     * @return
+     */
+    public boolean isBytes() {
+      return type == T_BYTES;
+    }
+    
+    
+    
     /**
      * Returns the byte chunk, representing the byte[] and offset/length.
      * Valid only if T_BYTES or after a conversion was made.
@@ -253,6 +255,17 @@
     public CharChunk getCharChunk() {
 	return charC;
     }
+    
+    public CharSequence getCharSequence() {
+      if (type == T_STR) {
+        return strValue;
+      } else if (type == T_CHARS) {
+        return charC;
+      } else {
+        toChars();
+        return charC;
+      }
+    }
 
     /**
      * Returns the string value.
@@ -504,6 +517,19 @@
 	return indexOf( s, 0 );
     }
     
+    public static int indexOf(CharSequence src, String s, int start) {
+      return 0;
+    }
+    
+    public static int indexOf(CharSequence src, char c, int start) {
+      for (int i = start; i < src.length(); i++) {
+        if (src.charAt(i) == c) {
+          return i;
+        }
+      }
+      return -1;
+    }
+    
     public int indexOfIgnoreCase(String s, int starting) {
 	toString();
 	String upper=strValue.toUpperCase();
@@ -555,110 +581,58 @@
 	}
     }
     
-    // -------------------- Flushing ------------------------- 
-    
-    // -------------------- Adding data -----------------------
-    
-    public void append( byte b ) {
-        
-    }
-    
-    public void append( byte b[], int off, int len ) {
-        
-    }
-    
-    public void append( char c ) {
-        
-    }
-    
-    public void append( char b[], int off, int len ) {
-        
-    }
-    
-    public void append( MessageBytes mb ) {
-        
-    }
-
     // -------------------- Deprecated code --------------------
     // efficient int, long and date
     // XXX used only for headers - shouldn't be
     // stored here.
-    private int intValue;
-    private boolean hasIntValue=false;
-    private long longValue;
-    private boolean hasLongValue=false;
-    private Date dateValue;
-    private boolean hasDateValue=false;
-    
-    /**
-     *  @deprecated The buffer are general purpose, caching for headers should
-     *  be done in headers. The second parameter allows us to pass a date format
-     * instance to avoid synchronization problems.
-     */
-    public void setTime(long t, DateFormat df) {
-	// XXX replace it with a byte[] tool
-	recycle();
-	if( dateValue==null)
-	    dateValue=new Date(t);
-	else
-	    dateValue.setTime(t);
-	if( df==null )
-	    strValue=DateTool.format1123(dateValue);
-	else
-	    strValue=DateTool.format1123(dateValue,df);
-	hasStrValue=true;
-	hasDateValue=true;
-	type=T_STR;   
-    }
-
-    public void setTime(long t) {
-	setTime( t, null );
-    }
-
-    /** Set the buffer to the representation of an int
-     */
-    public void setInt(int i) {
-        byteC.allocate(16, 32);
-        int current = i;
-        byte[] buf = byteC.getBuffer();
-        int start = 0;
-        int end = 0;
-        if (i == 0) {
-            buf[end++] = (byte) '0';
-        }
-        if (i < 0) {
-            current = -i;
-            buf[end++] = (byte) '-';
-        }
-        while (current > 0) {
-            int digit = current % 10;
-            current = current / 10;
-            buf[end++] = HexUtils.HEX[digit];
-        }
-        byteC.setOffset(0);
-        byteC.setEnd(end);
-        // Inverting buffer
-        end--;
-        if (i < 0) {
-            start++;
-        }
-        while (end > start) {
-            byte temp = buf[start];
-            buf[start] = buf[end];
-            buf[end] = temp;
-            start++;
-            end--;
-        }
-        intValue=i;
-        hasStrValue=false;
-        hasHashCode=false;
-        hasIntValue=true;
-        hasLongValue=false;
-        hasDateValue=false; 
-        type=T_BYTES;
-    }
+//    private long longValue;
+//    private boolean hasLongValue=false;
+    
+//    /** Set the buffer to the representation of an int
+//     */
+//    public void setInt(int i) {
+//        byteC.allocate(16, 32);
+//        int current = i;
+//        byte[] buf = byteC.getBuffer();
+//        int start = 0;
+//        int end = 0;
+//        if (i == 0) {
+//            buf[end++] = (byte) '0';
+//        }
+//        if (i < 0) {
+//            current = -i;
+//            buf[end++] = (byte) '-';
+//        }
+//        while (current > 0) {
+//            int digit = current % 10;
+//            current = current / 10;
+//            buf[end++] = HexUtils.HEX[digit];
+//        }
+//        byteC.setOffset(0);
+//        byteC.setEnd(end);
+//        // Inverting buffer
+//        end--;
+//        if (i < 0) {
+//            start++;
+//        }
+//        while (end > start) {
+//            byte temp = buf[start];
+//            buf[start] = buf[end];
+//            buf[end] = temp;
+//            start++;
+//            end--;
+//        }
+//        intValue=i;
+//        hasStrValue=false;
+//        hasHashCode=false;
+//        hasIntValue=true;
+//        hasLongValue=false;
+//        type=T_BYTES;
+//    }
 
-    /** Set the buffer to the representation of an long
+    /** 
+     * Set the buffer to the representation of an long - i.e. format a long
+     * in the buffer. Example use: setContentLength
      */
     public void setLong(long l) {
         byteC.allocate(32, 64);
@@ -692,88 +666,50 @@
             start++;
             end--;
         }
-        longValue=l;
+        //longValue=l;
         hasStrValue=false;
         hasHashCode=false;
-        hasIntValue=false;
-        hasLongValue=true;
-        hasDateValue=false; 
+        //hasLongValue=true;
         type=T_BYTES;
     }
 
-    /**
-     *  @deprecated The buffer are general purpose, caching for headers should
-     *  be done in headers
-     */
-    public  long getTime()
-    {
-     	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;
-    }
-    
 
-    // Used for headers conversion
-    /** Convert the buffer to an int, cache the value
-     */ 
-    public int getInt() 
-    {
-	if( hasIntValue )
-	    return intValue;
-	
-	switch (type) {
-	case T_BYTES:
-	    intValue=byteC.getInt();
-	    break;
-	default:
-	    intValue=Integer.parseInt(toString());
-	}
-	hasIntValue=true;
-	return intValue;
-    }
+//    // Used for headers conversion
+//    /** Convert the buffer to an int, cache the value
+//     */ 
+//    public int getInt() 
+//    {
+//	if( hasIntValue )
+//	    return intValue;
+//	
+//	switch (type) {
+//	case T_BYTES:
+//	    intValue=byteC.getInt();
+//	    break;
+//	default:
+//	    intValue=Integer.parseInt(toString());
+//	}
+//	hasIntValue=true;
+//	return intValue;
+//    }
 
     // Used for headers conversion
     /** Convert the buffer to an long, cache the value
      */ 
-    public long getLong() {
-        if( hasLongValue )
-            return longValue;
-        
-        switch (type) {
-        case T_BYTES:
-            longValue=byteC.getLong();
-            break;
-        default:
-            longValue=Long.parseLong(toString());
-        }
-
-        hasLongValue=true;
-        return longValue;
-
-     }
-
-    // -------------------- Future may be different --------------------
-    
-    private static MessageBytesFactory factory=new MessageBytesFactory();
-
-    public static void setFactory( MessageBytesFactory mbf ) {
-	factory=mbf;
-    }
-    
-    public static class MessageBytesFactory {
-	protected MessageBytesFactory() {
-	}
-        public MessageBytes newInstance() {
-            return new MessageBytes();
-        }
-    }
+//    public long getLong() {
+//        if( hasLongValue )
+//            return longValue;
+//        
+//        switch (type) {
+//        case T_BYTES:
+//            longValue=byteC.getLong();
+//            break;
+//        default:
+//            longValue=Long.parseLong(toString());
+//        }
+//
+//        hasLongValue=true;
+//        return longValue;
+//
+//     }
 }

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/MessageReader.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/MessageReader.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/MessageReader.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/MessageReader.java Tue May  1 19:22:45 2007
@@ -0,0 +1,500 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.apache.tomcat.util.buf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+import org.apache.tomcat.util.buf.CBuffer.CharInputChannel;
+import org.apache.tomcat.util.buf.CBuffer.CharOutputChannel;
+
+/**
+ * Refactored from catalina.connector.InputBuffer. Renamed to avoid conflict
+ * with coyote class.
+ * 
+ * TODO: move to coyote package.
+ */
+
+/**
+ * Reader using a Byte buffer and very aggressive recycling of the byte/char
+ * convertors.
+ * 
+ * This holds 2 buffers, one for chars and one for bytes. You can read both 
+ * bytes and chars, in any order.
+ *
+ * @author Remy Maucherat
+ */
+public class MessageReader extends Reader
+    implements CharInputChannel,
+               CharOutputChannel, ReadableByteChannel {
+
+
+    // -------------------------------------------------------------- Constants
+
+
+    public static final int DEFAULT_BUFFER_SIZE = 8*1024;
+
+    // The buffer can be used for byte[] and char[] reading
+    // ( this is needed to support ServletInputStream and BufferedReader )
+    public final int INITIAL_STATE = 0;
+    public final int CHAR_STATE = 1;
+    public final int BYTE_STATE = 2;
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The byte buffer.
+     */
+    private BBuffer bb;
+
+
+    /**
+     * The chunk buffer.
+     */
+    private CBuffer cb;
+
+
+    /**
+     * State of the output buffer.
+     */
+    private int state = 0;
+
+    /**
+     * Flag which indicates if the input buffer is closed.
+     */
+    private boolean closed = false;
+
+
+
+    /**
+     * Current byte to char converter. 
+     */
+    protected B2CConverter conv;
+
+
+    ReadableByteChannel channel;
+    
+
+    /**
+     * Buffer position.
+     */
+    private int markPos = -1;
+
+
+    /**
+     * Buffer size.
+     */
+    private int size = -1;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Default constructor. Allocate the buffer with the default buffer size.
+     */
+    public MessageReader() {
+        this(DEFAULT_BUFFER_SIZE);
+    }
+
+
+    /**
+     * Alternate constructor which allows specifying the initial buffer size.
+     * 
+     * @param size Buffer size to use
+     */
+    public MessageReader(int size) {
+        this.size = size;
+        bb = new BBuffer(size);
+        bb.setLimit(size);
+        bb.setInputChannel(this);
+
+        cb = new CBuffer(size);
+        cb.setLimit(size);
+        cb.setOptimizedWrite(false);
+        cb.setCharInputChannel(this);
+        cb.setCharOutputChannel(this);
+    }
+
+    public void setChannel(ReadableByteChannel channel) {
+      this.channel = channel;
+    }
+    
+    /**
+     * Recycle the output buffer.
+     */
+    public void recycle() {
+        
+        state = INITIAL_STATE;
+        
+        // If usage of mark made the buffer too big, reallocate it
+        if (cb.getChars().length > size) {
+            cb = new CBuffer(size);
+            cb.setLimit(size);
+            cb.setCharInputChannel(this);
+            cb.setCharOutputChannel(this);
+        } else {
+            cb.recycle();
+        }
+        markPos = -1;
+        bb.recycle(); 
+        closed = false;
+        
+        if (conv != null) {
+            conv.recycle();
+        }
+        
+    }
+
+
+    /**
+     * Close the input buffer.
+     * 
+     * @throws IOException An underlying IOException occurred
+     */
+    public void close()
+           throws IOException {
+        closed = true;
+    }
+
+
+    public int available()
+            throws IOException {
+        if (state == BYTE_STATE) {
+            return bb.getLength();
+        } else if (state == CHAR_STATE) {
+            return cb.getLength();
+        } else {
+            return 0;
+        }
+    }
+
+
+    // ------------------------------------------------- Bytes Handling Methods
+
+
+    /** 
+     * Used internally for the conversion process. Will read data from the 
+     * real stream.
+     */
+    public int read(ByteBuffer dst) throws IOException {
+      if (closed)
+        return -1;
+    
+      state = BYTE_STATE;
+      return channel.read(dst);
+    }
+
+
+    public boolean isOpen() {
+      return channel.isOpen();
+    }
+    
+    public int readByte()
+          throws IOException {
+        return bb.substract();
+    }
+
+
+    public int read(byte[] b, int off, int len)
+          throws IOException {
+        return bb.substract(b, off, len);
+    }
+
+
+    // ------------------------------------------------- Chars Handling Methods
+
+
+    /**
+     * Used internally.
+     * 
+     * Since the converter will use append, it is possible to get chars to
+     * be removed from the buffer for "writing". Since the chars have already
+     * been read before, they are ignored. If a mark was set, then the
+     * mark is lost.
+     */
+    public void realWriteChars(char c[], int off, int len) 
+        throws IOException {
+        markPos = -1;
+    }
+
+    /** 
+     * Internal use
+     */
+    public int realReadChars(char cbuf[], int off, int len)
+        throws IOException {
+
+      if (bb.getLength() <= 0) {
+          ByteBuffer buffer = bb.getBuffer(true);
+          // buffer is in write mode, we can append to it.
+          int nRead = read(buffer); 
+          // pos updated - reflect it into end.
+          bb.releaseBuffer();
+
+          if (nRead < 0) {
+            return -1;
+          }
+        }
+
+        if (markPos == -1) {
+            cb.setOffset(0);
+            cb.setEnd(0);
+        }
+
+        conv.convert(bb, cb);
+        bb.setStart(bb.getEnd());
+        state = CHAR_STATE;
+
+        return cb.getLength();
+    }
+
+
+    public int read()
+        throws IOException {
+        return cb.substract();
+    }
+
+
+    public int read(char[] cbuf)
+        throws IOException {
+        return read(cbuf, 0, cbuf.length);
+    }
+
+
+    public int read(char[] cbuf, int off, int len)
+        throws IOException {
+        return cb.substract(cbuf, off, len);
+    }
+
+
+    public long skip(long n)
+        throws IOException {
+
+        if (n < 0) {
+            throw new IllegalArgumentException();
+        }
+
+        long nRead = 0;
+        while (nRead < n) {
+            if (cb.getLength() >= n) {
+                cb.setOffset(cb.getStart() + (int) n);
+                nRead = n;
+            } else {
+                nRead += cb.getLength();
+                cb.setOffset(cb.getEnd());
+                int toRead = 0;
+                if (cb.getChars().length < (n - nRead)) {
+                    toRead = cb.getChars().length;
+                } else {
+                    toRead = (int) (n - nRead);
+                }
+                int nb = realReadChars(cb.getChars(), 0, toRead);
+                if (nb < 0)
+                    break;
+            }
+        }
+
+        return nRead;
+
+    }
+
+
+    public boolean ready()
+        throws IOException {
+        return (cb.getLength() > 0);
+    }
+
+
+    public boolean markSupported() {
+        return true;
+    }
+
+
+    public void mark(int readAheadLimit)
+        throws IOException {
+        if (cb.getLength() <= 0) {
+            cb.setOffset(0);
+            cb.setEnd(0);
+        } else {
+            if ((cb.getBuffer().length > (2 * size)) 
+                && (cb.getLength()) < (cb.getStart())) {
+                System.arraycopy(cb.getBuffer(), cb.getStart(), 
+                                 cb.getBuffer(), 0, cb.getLength());
+                cb.setEnd(cb.getLength());
+                cb.setOffset(0);
+            }
+        }
+        int offset = readAheadLimit;
+        if (offset < size) {
+            offset = size;
+        }
+        cb.setLimit(cb.getStart() + offset);
+        markPos = cb.getStart();
+    }
+
+
+    public void reset()
+        throws IOException {
+        if (state == CHAR_STATE) {
+            if (markPos < 0) {
+                cb.recycle();
+                markPos = -1;
+                throw new IOException();
+            } else {
+                cb.setOffset(markPos);
+            }
+        } else {
+            bb.recycle();
+        }
+    }
+
+    public void setConverter(B2CConverter conv)
+            throws IOException {
+      this.conv = conv;
+    }
+
+    /** 
+     * Conversion of bytes  to character, reusing the same InputStreamReader
+     */
+    public static class B2CConverter {
+        
+        private IntermediateInputStream iis;
+        private ReadConvertor conv;
+        private String encoding;
+
+        /** Create a converter, with bytes going to a byte buffer
+         */
+        public B2CConverter(String encoding)
+          throws IOException
+        {
+          this.encoding=encoding;
+          reset();
+        }
+
+        
+        /** Reset the internal state, empty the buffers.
+         *  The encoding remain in effect, the internal buffers remain allocated.
+         */
+        public  void recycle() {
+          // Normal use is to convert the entire BB
+        }
+        
+        public  void convert( BBuffer bb, CBuffer cb )
+            throws IOException
+        {
+            // Set the ByteChunk as input to the Intermediate reader
+            iis.setByteChunk( bb );
+            convert(cb);
+        }
+
+        private void convert(CBuffer cb)
+          throws IOException
+        {
+            try {
+              cb.append(conv);
+            } catch( IOException ex) {
+                reset();
+                throw ex;
+            }
+        }
+
+        // Called on exception - to have a good state
+        void reset()
+          throws IOException
+        {
+          iis=new IntermediateInputStream();
+          conv=new ReadConvertor( iis, encoding );
+        }
+    }
+
+    /**
+     * StreamReader with close() overriden - can be used multiple
+     * times without reallocation. Has a private, internal byte[8192]
+     * for the conversion. The intermediary input stream can be re-filled
+     * with multiple byte[]. 
+     * 
+     * You can read char[] and have the Reader do the conversion, with 
+     * little overhead ( compared with creating new objects and buffers
+     * all the time )
+     */
+    final static class  ReadConvertor extends InputStreamReader {
+      ReadConvertor( IntermediateInputStream in, String enc )
+        throws UnsupportedEncodingException
+      {
+        super( in, enc );
+      }
+
+      /** Overriden - will do nothing but reset internal state.
+       */
+      public  final void close() throws IOException {
+      }
+    }
+
+
+    /** Special input stream where close() is overriden, so super.close()
+      *  is never called.
+      *  
+      *  This allows recycling. It can also be disabled, so callbacks will
+      *  not be called if recycling the converter and if data was not flushed.
+      */
+    final static class IntermediateInputStream extends InputStream {
+      byte buf[];
+      int pos;
+      int end;
+
+      IntermediateInputStream() {
+      }
+
+      public  final void close() throws IOException {
+        // shouldn't be called - we filter it out in writer
+        throw new IOException("close() called - shouldn't happen ");
+      }
+
+      public  final  int read(byte cbuf[], int off, int len) 
+          throws IOException {
+        if( pos >= end ) return -1;
+        if (pos + len > end) {
+          len = end - pos;
+        }
+        if (len <= 0) {
+          return 0;
+        }
+        System.arraycopy(buf, pos, cbuf, off, len);
+        pos += len;
+        return len;
+      }
+
+      public  final int read() throws IOException {
+        return (pos < end ) ? (buf[pos++] & 0xff) : -1;
+      }
+
+      /** 
+       * Re-fill the stream
+       */
+      void setByteChunk( BBuffer mb ) {
+        buf=mb.getBytes();
+        pos=mb.getStart();
+        end=mb.getEnd();
+      }
+    }
+}

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/UDecoder.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/UDecoder.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/UDecoder.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/UDecoder.java Tue May  1 19:22:45 2007
@@ -98,7 +98,7 @@
     /** In-buffer processing - the buffer will be modified
      *  Includes converting  '+' to ' '.
      */
-    public void convert( CharChunk mb )
+    public void convert( CBuffer mb )
 	throws IOException
     {
         convert(mb, true);
@@ -108,20 +108,37 @@
      * IMPORTANT: this method doesn't work for UTF or other encodings !!
      * Only the byte[] method works ( since it happens before charset decoding)
      */
-    public void convert( CharChunk mb, boolean query )
-	throws IOException
+    public void convert( CBuffer mb, boolean query )
+    throws IOException
     {
-	//	log( "Converting a char chunk ");
-	int start=mb.getOffset();
-	char buff[]=mb.getBuffer();
-	int cend=mb.getEnd();
+        //      log( "Converting a char chunk ");
+        int start=mb.getOffset();
+        char buff[]=mb.getBuffer();
+        int cend=mb.getEnd();
+        
+        int newEnd = convert(buff, start, cend, query);
+        mb.setEnd(newEnd);
+    }
 
+    public void convert( CharChunk mb, boolean query )
+        throws IOException
+    {
+        //      log( "Converting a char chunk ");
+        int start=mb.getOffset();
+        char buff[]=mb.getBuffer();
+        int cend=mb.getEnd();
+        mb.setEnd(convert(buff, start, cend, query));
+    }
+    
+    public int convert( char[] buff, int start, int cend, boolean query )
+        throws IOException
+    {
 	int idx= CharChunk.indexOf( buff, start, cend, '%' );
         int idx2=-1;
         if( query )
             idx2= CharChunk.indexOf( buff, start, cend, '+' );
 	if( idx<0 && idx2<0 ) {
-	    return;
+	    return cend;
 	}
 	
 	if( idx2 >= 0 && idx2 < idx ) idx=idx2; 
@@ -148,7 +165,8 @@
 		buff[idx]=(char)res;
 	    }
 	}
-	mb.setEnd( idx );
+	//mb.setEnd( idx );
+        return idx;
     }
 
     /** URLDecode, will modify the source

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/UEncoder.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/UEncoder.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/UEncoder.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/buf/UEncoder.java Tue May  1 19:22:45 2007
@@ -98,7 +98,7 @@
 		buf.write((char)c);
 	    } else {
 		//if( debug > 0 ) log("Unsafe:  " + (char)c);
-                cb.append((char)c);
+                cb.put((char)c);
                 cb.flip();
                 c2b.encode(cb, bb, true);
 		//c2b.convert( (char)c );

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ContentType.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ContentType.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ContentType.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/ContentType.java Tue May  1 19:22:45 2007
@@ -0,0 +1,92 @@
+/*
+ *  Copyright 1999-2004 The Apache Software Foundation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.tomcat.util.http;
+
+
+/**
+ * Usefull methods for Content-Type processing
+ * 
+ * @author James Duncan Davidson [duncan@eng.sun.com]
+ * @author James Todd [gonzo@eng.sun.com]
+ * @author Jason Hunter [jch@eng.sun.com]
+ * @author Harish Prabandham
+ * @author costin@eng.sun.com
+ */
+public class ContentType {
+
+    // Basically return everything after ";charset="
+    // If no charset specified, use the HTTP default (ASCII) character set.
+    public static String getCharsetFromContentType(String type) {
+        if (type == null) {
+            return null;
+        }
+        int semi = type.indexOf(";");
+        if (semi == -1) {
+            return null;
+        }
+        int charsetLocation = type.indexOf("charset=", semi);
+        if (charsetLocation == -1) {
+            return null;
+        }
+	String afterCharset = type.substring(charsetLocation + 8);
+        // The charset value in a Content-Type header is allowed to be quoted
+        // and charset values can't contain quotes.  Just convert any quote
+        // chars into spaces and let trim clean things up.
+        afterCharset = afterCharset.replace('"', ' ');
+        String encoding = afterCharset.trim();
+        return encoding;
+    }
+
+
+    /**
+     * Returns true if the given content type contains a charset component,
+     * false otherwise.
+     *
+     * @param type Content type
+     * @return true if the given content type contains a charset component,
+     * false otherwise
+     */
+    public static boolean hasCharset(String type) {
+
+        boolean hasCharset = false;
+
+        int len = type.length();
+        int index = type.indexOf(';');
+        while (index != -1) {
+            index++;
+            while (index < len && Character.isSpace(type.charAt(index))) {
+                index++;
+            }
+            if (index+8 < len
+                    && type.charAt(index) == 'c'
+                    && type.charAt(index+1) == 'h'
+                    && type.charAt(index+2) == 'a'
+                    && type.charAt(index+3) == 'r'
+                    && type.charAt(index+4) == 's'
+                    && type.charAt(index+5) == 'e'
+                    && type.charAt(index+6) == 't'
+                    && type.charAt(index+7) == '=') {
+                hasCharset = true;
+                break;
+            }
+            index = type.indexOf(';', index);
+        }
+
+        return hasCharset;
+    }
+
+}

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/Cookies.java Tue May  1 19:22:45 2007
@@ -32,15 +32,18 @@
  * @author Costin Manolache
  * @author kevin seguin
  */
-public final class Cookies { // extends MultiMap {
+public class Cookies { 
 
     private static org.apache.commons.logging.Log log=
         org.apache.commons.logging.LogFactory.getLog(Cookies.class );
     
     // expected average number of cookies per request
-    public static final int INITIAL_SIZE=4; 
+    public static final int INITIAL_SIZE=8;
+    
     ServerCookie scookies[]=new ServerCookie[INITIAL_SIZE];
+    
     int cookieCount=0;
+    
     boolean unprocessed=true;
 
     MimeHeaders headers;
@@ -167,7 +170,7 @@
             }
 
             // Uncomment to test the new parsing code
-            if( cookieValue.getType() == MessageBytes.T_BYTES ) {
+            if( cookieValue.isBytes() ) {
                 if( dbg>0 ) log( "Parsing b[]: " + cookieValue.toString());
                 ByteChunk bc=cookieValue.getByteChunk();
                 processCookieHeader( bc.getBytes(),
@@ -219,9 +222,9 @@
                 // it's a name-only cookie ( valid in RFC2109 )
                 if( ! isSpecial ) {
                     sc=addCookie();
-                    sc.getName().setBytes( bytes, startName,
+                    sc.getNameBytes().setBytes( bytes, startName,
                                            endName-startName );
-                    sc.getValue().setString("");
+                    sc.setValue("");
                     sc.setVersion( version );
                     if( dbg>0 ) log( "Name only, end: " + startName + " " +
                                      endName);
@@ -234,9 +237,9 @@
             if( cc==';' || cc==',' || pos>=end ) {
                 if( ! isSpecial && startName!= endName ) {
                     sc=addCookie();
-                    sc.getName().setBytes( bytes, startName,
+                    sc.getNameBytes().setBytes( bytes, startName,
                                            endName-startName );
-                    sc.getValue().setString("");
+                    sc.setValue("");
                     sc.setVersion( version );
                     if( dbg>0 ) log( "Name only: " + startName + " " + endName);
                 }
@@ -260,8 +263,8 @@
             // if not $Version, etc
             if( ! isSpecial ) {
                 sc=addCookie();
-                sc.getName().setBytes( bytes, startName, endName-startName );
-                sc.getValue().setBytes( bytes, startValue, endValue-startValue);
+                sc.getNameBytes().setBytes( bytes, startName, endName-startName );
+                sc.getValueBytes().setBytes( bytes, startValue, endValue-startValue);
                 sc.setVersion( version );
                 if( dbg>0 ) {
                     log( "New: " + sc.getName() + "X=X" + sc.getValue());
@@ -285,12 +288,12 @@
                 continue;
             }
             if( equals( "$Path", bytes, startName, endName ) ) {
-                sc.getPath().setBytes( bytes,
+                sc.getPathBytes().setBytes( bytes,
                                        startValue,
                                        endValue-startValue );
             }
             if( equals( "$Domain", bytes, startName, endName ) ) {
-                sc.getDomain().setBytes( bytes,
+                sc.getDomainBytes().setBytes( bytes,
                                          startValue,
                                          endValue-startValue );
             }
@@ -399,8 +402,8 @@
                 value=stripQuote( value );
                 ServerCookie cookie = addCookie();
                 
-                cookie.getName().setString(name);
-                cookie.getValue().setString(value);
+                cookie.setName(name);
+                cookie.setValue(value);
                 if( dbg > 0 ) log( "Add cookie " + name + "=" + value);
             } else {
                 // we have a bad cookie.... just let it go

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/util/http/FastHttpDateFormat.java Tue May  1 19:22:45 2007
@@ -88,15 +88,15 @@
     /**
      * Formatter cache.
      */
-    protected static final HashMap<Long, String> formatCache = 
-        new HashMap<Long, String>(CACHE_SIZE);
+    protected static final HashMap/*<Long, String>*/ formatCache = 
+        new HashMap/*<Long, String>*/(CACHE_SIZE);
 
 
     /**
      * Parser cache.
      */
-    protected static final HashMap<String, Long> parseCache = 
-        new HashMap<String, Long>(CACHE_SIZE);
+    protected static final HashMap/*<String, Long>*/ parseCache = 
+        new HashMap/*<String, Long>*/(CACHE_SIZE);
 
 
     // --------------------------------------------------------- Public Methods
@@ -128,7 +128,7 @@
         (long value, DateFormat threadLocalformat) {
 
         Long longValue = new Long(value);
-        String cachedDate = formatCache.get(longValue);
+        String cachedDate = (String) formatCache.get(longValue);
         if (cachedDate != null)
             return cachedDate;
 
@@ -156,7 +156,7 @@
     public static final long parseDate(String value, 
                                        DateFormat[] threadLocalformats) {
 
-        Long cachedDate = parseCache.get(value);
+        Long cachedDate = (Long) parseCache.get(value);
         if (cachedDate != null)
             return cachedDate.longValue();
 



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


Mime
View raw message