FileDocCategorySizeDatePackage
InputBuffer.javaAPI DocGlassfish v2 API14477Fri May 04 22:32:44 BST 2007org.apache.coyote.tomcat5

InputBuffer

public class InputBuffer extends Reader implements CharChunk.CharInputChannel, CharChunk.CharOutputChannel, ByteChunk.ByteInputChannel
The buffer used by Tomcat request. This is a derivative of the Tomcat 3.3 OutputBuffer, adapted to handle input instead of output. This allows complete recycling of the facade objects (the ServletInputStream and the BufferedReader).
author
Remy Maucherat

Fields Summary
private static com.sun.org.apache.commons.logging.Log
log
public static final String
DEFAULT_ENCODING
public static final int
DEFAULT_BUFFER_SIZE
static final int
debug
public final int
INITIAL_STATE
public final int
CHAR_STATE
public final int
BYTE_STATE
private org.apache.tomcat.util.buf.ByteChunk
bb
The byte buffer.
private org.apache.tomcat.util.buf.CharChunk
cb
The chunk buffer.
private int
state
State of the output buffer.
private int
bytesRead
Number of bytes read.
private int
charsRead
Number of chars read.
private boolean
closed
Flag which indicates if the input buffer is closed.
private org.apache.tomcat.util.buf.ByteChunk
inputChunk
Byte chunk used to input bytes.
private String
enc
Encoding to use.
private boolean
gotEnc
Encoder is set.
protected HashMap
encoders
List of encoders.
protected org.apache.tomcat.util.buf.B2CConverter
conv
Current byte to char converter.
private org.apache.coyote.Request
coyoteRequest
Associated Coyote request.
private int
markPos
Buffer position.
private int
size
Buffer size.
Constructors Summary
public InputBuffer()
Default constructor. Allocate the buffer with the default buffer size.



    // ----------------------------------------------------------- Constructors


                   
      

        this(DEFAULT_BUFFER_SIZE);

    
public InputBuffer(int size)
Alternate constructor which allows specifying the initial buffer size.

param
size Buffer size to use

        
        this.size = size;
        bb = new ByteChunk(size);
        bb.setLimit(size);
        bb.setByteInputChannel(this);
    
Methods Summary
public intavailable()

        if (state == BYTE_STATE) {
            return bb.getLength();
        } else if (state == CHAR_STATE) {
            return cb.getLength();
        } else {
            return 0;
        }
    
public voidcheckConverter()


        if (!gotEnc)
            setConverter();

    
public voidclose()
Close the input buffer.

throws
IOException An underlying IOException occurred

        closed = true;
    
public org.apache.coyote.RequestgetRequest()
Get associated Coyote request.

return
the associated Coyote request

        return this.coyoteRequest;
    
private voidinitChar()

        if (cb != null)
            return;
        cb = new CharChunk(size);
        cb.setLimit(size);
        cb.setOptimizedWrite(false);
        cb.setCharInputChannel(this);
        cb.setCharOutputChannel(this);
    
public voidmark(int readAheadLimit)

        // START OF SJSAS 6231069
        initChar();
        // END OF SJSAS 6231069
        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 booleanmarkSupported()

        return true;
    
public intread(byte[] b, int off, int len)

        return bb.substract(b, off, len);
    
public intread()

        // START OF SJSAS 6231069
        initChar();
        // END OF SJSAS 6231069
        return cb.substract();
    
public intread(char[] cbuf)

        // START OF SJSAS 6231069
        initChar();
        // END OF SJSAS 6231069
        return read(cbuf, 0, cbuf.length);
    
public intread(char[] cbuf, int off, int len)

        // START OF SJSAS 6231069
	initChar();
        // END OF SJSAS 6231069
        return cb.substract(cbuf, off, len);
    
public intreadByte()

        return bb.substract();
    
public booleanready()

        // START OF SJSAS 6231069
        initChar();
        // END OF SJSAS 6231069
        return (cb.getLength() > 0);
    
public intrealReadBytes(byte[] cbuf, int off, int len)
Reads new bytes in the byte chunk.

param
buf Byte buffer to be written to the response
param
off Offset
param
cnt Length
throws
IOException An underlying IOException occurred


        if (log.isDebugEnabled())
            log.debug("realRead() " + coyoteRequest);

        if (closed)
            return -1;
        if (coyoteRequest == null)
            return -1;

        state = BYTE_STATE;

        int result = coyoteRequest.doRead(bb);

        return result;

    
public intrealReadChars(char[] cbuf, int off, int len)


        // START OF SJSAS 6231069
        initChar();
        // END OF SJSAS 6231069
        if (log.isDebugEnabled())
            log.debug("realRead() " + cb.getOffset() + " " + len);

        if (!gotEnc)
            setConverter();

        if (log.isDebugEnabled())
            log.debug("encoder:  " + conv + " " + gotEnc);

        if (bb.getLength() <= 0) {
            int nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length);
            if (nRead < 0) {
                return -1;
            }
        }

        int limit = bb.getLength()+cb.getStart();
        if ( cb.getLimit() < limit )
            cb.setLimit(limit);

        if (markPos == -1) {
            cb.setOffset(0);
            cb.setEnd(0);
        }

        conv.convert(bb, cb);
        bb.setOffset(bb.getEnd());
        state = CHAR_STATE;

        return cb.getLength();

    
public voidrealWriteChars(char[] c, int off, int len)
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.

        // START OF SJSAS 6231069
        initChar();
        // END OF SJSAS 6231069
        markPos = -1;
    
public voidrecycle()
Recycle the output buffer.


        if (log.isTraceEnabled())
            log.trace("recycle()");

        state = INITIAL_STATE;
        bytesRead = 0;
        charsRead = 0;

        // START OF SJSAS 6231069
        /*
        // If usage of mark made the buffer too big, reallocate it
        if (cb.getChars().length > size) {
            cb = new CharChunk(size);
            cb.setLimit(size);
            cb.setCharInputChannel(this);
            cb.setCharOutputChannel(this);
        } else {
            cb.recycle();
        }
        */
        cb = null;
        // END OF SJSAS 6231069

        bb.recycle(); 
        markPos = -1;
        closed = false;

        if (conv != null) {
            conv.recycle();
        }

        gotEnc = false;
        enc = null;

    
public voidreset()

        if (state == CHAR_STATE) {
            if (markPos < 0) {
                cb.recycle();
                markPos = -1;
                throw new IOException();
            } else {
                cb.setOffset(markPos);
            }
        } else {
            bb.recycle();
        }
    
protected voidsetConverter()


        if (coyoteRequest != null)
            enc = coyoteRequest.getCharacterEncoding();

        if (log.isDebugEnabled())
            log.debug("Got encoding: " + enc);

        gotEnc = true;
        if (enc == null)
            enc = DEFAULT_ENCODING;
        conv = (B2CConverter) encoders.get(enc);
        if (conv == null) {
            if (SecurityUtil.isPackageProtectionEnabled()){
                try{
                    conv = (B2CConverter)AccessController.doPrivileged(
                            new PrivilegedExceptionAction(){

                                public Object run() throws IOException{
                                    return new B2CConverter(enc);
                                }

                            }
                    );              
                }catch(PrivilegedActionException ex){
                    Exception e = ex.getException();
                    if (e instanceof IOException)
                        throw (IOException)e; 
                    
                    if (log.isDebugEnabled())
                        log.debug("setConverter: " + ex.getMessage());
                }
            } else {
                conv = new B2CConverter(enc);
            }               
            encoders.put(enc, conv);
        }

    
public voidsetEncoding(java.lang.String s)

        enc = s;
    
public voidsetRequest(org.apache.coyote.Request coyoteRequest)
Associated Coyote request.

param
coyoteRequest Associated Coyote request

	this.coyoteRequest = coyoteRequest;
    
public longskip(long n)


        if (n < 0) {
            throw new IllegalArgumentException();
        }

        // START OF SJSAS 6231069
        initChar();
        // END OF SJSAS 6231069
        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;