Index: java/org/apache/catalina/connector/CoyoteReader.java =================================================================== --- java/org/apache/catalina/connector/CoyoteReader.java (revision 638800) +++ java/org/apache/catalina/connector/CoyoteReader.java (working copy) @@ -119,7 +119,7 @@ public boolean markSupported() { - return true; + return ib.markSupported(); } Index: java/org/apache/catalina/connector/InputBuffer.java =================================================================== --- java/org/apache/catalina/connector/InputBuffer.java (revision 638800) +++ java/org/apache/catalina/connector/InputBuffer.java (working copy) @@ -342,22 +342,29 @@ if (!gotEnc) setConverter(); + int nRead = 0; if (bb.getLength() <= 0) { - int nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length); - if (nRead < 0) { - return -1; - } + nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length); + // Data may be remaining in the buffer of ReadConverter('s super). + // So we must try to convert whether nRead is positive or not. } - if (markPos == -1) { cb.setOffset(0); cb.setEnd(0); } - conv.convert(bb, cb); - bb.setOffset(bb.getEnd()); + if((markPos >= 0) && (cb.getLimit()-cb.getEnd()) <= 0){ + // markPos will be reset and the status of cb will be modified + // via cb.flushBuffer(), only if more chars exists. + conv.convert(bb, cb, cb.getLimit()); + }else{ + conv.convert(bb, cb, cb.getLimit()-cb.getEnd()); + } state = CHAR_STATE; + if((nRead < 0) && (cb.getLength()==0)){ + return -1; + } return cb.getLength(); } @@ -426,6 +433,9 @@ public void mark(int readAheadLimit) throws IOException { + if (readAheadLimit < 0){ // See BufferedReader#mark(int) JavaDoc + throw new IllegalArgumentException("readAheadLimit value is negative"); + } if (cb.getLength() <= 0) { cb.setOffset(0); cb.setEnd(0); @@ -451,9 +461,7 @@ throws IOException { if (state == CHAR_STATE) { if (markPos < 0) { - cb.recycle(); - markPos = -1; - throw new IOException(); + throw new IOException("The mark is not effective"); } else { cb.setOffset(markPos); } Index: java/org/apache/tomcat/util/buf/B2CConverter.java =================================================================== --- java/org/apache/tomcat/util/buf/B2CConverter.java (revision 638800) +++ java/org/apache/tomcat/util/buf/B2CConverter.java (working copy) @@ -68,22 +68,32 @@ char result[]=new char[BUFFER_SIZE]; /** Convert a buffer of bytes into a chars + * @deprecated */ public void convert( ByteChunk bb, CharChunk cb ) throws IOException { - // Set the ByteChunk as input to the Intermediate reader - iis.setByteChunk( bb ); - convert(cb); + convert(bb, cb, cb.getLimit() - cb.getEnd()); } - private void convert(CharChunk cb) + /** Convert a buffer of bytes into a chars + */ + public void convert( ByteChunk bb, CharChunk cb, int limit) + throws IOException + { + // Set the ByteChunk as input to the Intermediate reader + iis.setByteChunk( bb ); + convert(cb, limit); + } + + private void convert(CharChunk cb, int limit) throws IOException { try { // read from the reader - while( iis.available()>0 ) { // conv.ready() ) { - int cnt=conv.read( result, 0, BUFFER_SIZE ); + while( limit > 0 ) { + int size = limit < BUFFER_SIZE ? limit : BUFFER_SIZE; + int cnt=conv.read( result, 0, size ); if( cnt <= 0 ) { // End of stream ! - we may be in a bad state if( debug>0) @@ -96,6 +106,7 @@ // XXX go directly cb.append( result, 0, cnt ); + limit -= cnt; } } catch( IOException ex) { if( debug>0) @@ -183,18 +194,16 @@ * */ final class ReadConvertor extends InputStreamReader { - // stream with flush() and close(). overriden. - private IntermediateInputStream iis; - // Has a private, internal byte[8192] - + private IntermediateInputStream iis; + /** Create a converter. */ public ReadConvertor( IntermediateInputStream in, String enc ) throws UnsupportedEncodingException { super( in, enc ); - iis=in; + iis=in; } /** Overriden - will do nothing but reset internal state. @@ -211,13 +220,18 @@ return super.read( cbuf, off, len ); } - public final int read() throws IOException { - return super.read(); - } - - /** Reset the buffer + /* + * Reset the buffer */ public final void recycle() { + iis.recycle(); + try{ + // Must clear super's buffer. + while(ready()){ + // InputStreamReader#skip(long) will allocate buffer to skip. + read(); + } + }catch(IOException ioe){} } } @@ -229,10 +243,7 @@ not be called if recycling the converter and if data was not flushed. */ final class IntermediateInputStream extends InputStream { - byte buf[]; - int pos; - int len; - int end; + ByteChunk bc = null; public IntermediateInputStream() { } @@ -243,64 +254,35 @@ } 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; + if(bc == null){ + return -1; + } + return bc.substract(cbuf, off, len); } public final int read() throws IOException { - return (pos < end ) ? (buf[pos++] & 0xff) : -1; + if(bc == null){ + return -1; + } + return bc.substract(); } - // -------------------- Internal methods -------------------- - - void setBuffer( byte b[], int p, int l ) { - buf=b; - pos=p; - len=l; - end=pos+len; - } - - void setByteChunk( ByteChunk mb ) { - buf=mb.getBytes(); - pos=mb.getStart(); - len=mb.getLength(); - end=pos+len; - } - public int available() throws IOException { - return end-pos; + if(bc == null){ + return 0; + } + return bc.getLength(); } - public boolean markSupported() { - return false; - } - public int read(byte[] b) throws IOException { - return read(b,0,b.length); - } + // -------------------- Internal methods -------------------- - /** - * Repositions this stream to the position at the time the mark method was last called on this input - * stream. - * - * @throws IOException if this stream has not been marked or if the mark has been invalidated. - * @todo Implement this java.io.InputStream method - */ - public synchronized void reset() throws IOException { - //not implemented + void recycle(){ + bc = null; } - public long skip(long n) throws IOException { - //not implemented - return 0L; + void setByteChunk( ByteChunk mb ) { + bc = mb; } }