FileDocCategorySizeDatePackage
OutputBuffer.javaAPI DocApache Tomcat 6.0.1413409Fri Jul 20 04:20:36 BST 2007org.apache.catalina.connector

OutputBuffer

public class OutputBuffer extends Writer implements ByteChunk.ByteOutputChannel
The buffer used by Tomcat response. This is a derivative of the Tomcat 3.3 OutputBuffer, with the removal of some of the state handling (which in Coyote is mostly the Processor's responsability).
author
Costin Manolache
author
Remy Maucherat

Fields Summary
public static final String
DEFAULT_ENCODING
public static final int
DEFAULT_BUFFER_SIZE
private org.apache.tomcat.util.buf.ByteChunk
bb
The byte buffer.
private boolean
initial
State of the output buffer.
private int
bytesWritten
Number of bytes written.
private int
charsWritten
Number of chars written.
private boolean
closed
Flag which indicates if the output buffer is closed.
private boolean
doFlush
Do a flush on the next operation.
private org.apache.tomcat.util.buf.ByteChunk
outputChunk
Byte chunk used to output 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.C2BConverter
conv
Current char to byte converter.
private org.apache.coyote.Response
coyoteResponse
Associated Coyote response.
private boolean
suspended
Suspended flag. All output bytes will be swallowed if this is true.
Constructors Summary
public OutputBuffer()
Default constructor. Allocate the buffer with the default buffer size.



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


                   
      

        this(DEFAULT_BUFFER_SIZE);

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

param
size Buffer size to use


        bb = new ByteChunk(size);
        bb.setLimit(size);
        bb.setByteOutputChannel(this);

    
Methods Summary
public voidcheckConverter()


        if (!gotEnc)
            setConverter();

    
public voidclearEncoders()
Clear cached encoders (to save memory for Comet requests).

        encoders.clear();
    
public voidclose()
Close the output buffer. This tries to calculate the response size if the response has not been committed yet.

throws
IOException An underlying IOException occurred


        if (closed)
            return;
        if (suspended)
            return;

        if ((!coyoteResponse.isCommitted()) 
            && (coyoteResponse.getContentLengthLong() == -1)) {
            // If this didn't cause a commit of the response, the final content
            // length can be calculated
            if (!coyoteResponse.isCommitted()) {
                coyoteResponse.setContentLength(bb.getLength());
            }
        }

        doFlush(false);
        closed = true;

        coyoteResponse.finish();

    
protected voiddoFlush(boolean realFlush)
Flush bytes or chars contained in the buffer.

throws
IOException An underlying IOException occurred


        if (suspended)
            return;

        doFlush = true;
        if (initial) {
            coyoteResponse.sendHeaders();
            initial = false;
        }
        if (bb.getLength() > 0) {
            bb.flushBuffer();
        }
        doFlush = false;

        if (realFlush) {
            coyoteResponse.action(ActionCode.ACTION_CLIENT_FLUSH, 
                                  coyoteResponse);
            // If some exception occurred earlier, or if some IOE occurred
            // here, notify the servlet with an IOE
            if (coyoteResponse.isExceptionPresent()) {
                throw new ClientAbortException
                    (coyoteResponse.getErrorException());
            }
        }

    
public voidflush()
Flush bytes or chars contained in the buffer.

throws
IOException An underlying IOException occurred

        doFlush(true);
    
public voidflushBytes()
Real write - this buffer will be sent to the client


        bb.flushBuffer();

    
public intgetBufferSize()

        return bb.getLimit();
    
public intgetBytesWritten()

        return bytesWritten;
    
public intgetCharsWritten()

        return charsWritten;
    
public intgetContentWritten()

        return bytesWritten + charsWritten;
    
public org.apache.coyote.ResponsegetResponse()
Get associated Coyote response.

return
the associated Coyote response

        return this.coyoteResponse;
    
public booleanisClosed()
Is the response output closed ?

return
closed flag value

        return this.closed;
    
public booleanisNew()
True if this buffer hasn't been used ( since recycle() ) - i.e. no chars or bytes have been added to the buffer.

        return (bytesWritten == 0) && (charsWritten == 0);
    
public booleanisSuspended()
Is the response output suspended ?

return
suspended flag value

        return this.suspended;
    
public voidrealWriteBytes(byte[] buf, int off, int cnt)
Sends the buffer data to the client output, checking the state of Response and calling the right interceptors.

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


        if (closed)
            return;
        if (coyoteResponse == null)
            return;

        // If we really have something to write
        if (cnt > 0) {
            // real write to the adapter
            outputChunk.setBytes(buf, off, cnt);
            try {
                coyoteResponse.doWrite(outputChunk);
            } catch (IOException e) {
                // An IOException on a write is almost always due to
                // the remote client aborting the request.  Wrap this
                // so that it can be handled better by the error dispatcher.
                throw new ClientAbortException(e);
            }
        }

    
public voidrecycle()
Recycle the output buffer.

        
        initial = true;
        bytesWritten = 0;
        charsWritten = 0;
        
        bb.recycle(); 
        closed = false;
        suspended = false;
        
        if (conv!= null) {
            conv.recycle();
        }
        
        gotEnc = false;
        enc = null;
        
    
public voidreset()


        bb.recycle();
        bytesWritten = 0;
        charsWritten = 0;
        gotEnc = false;
        enc = null;
        initial = true;
        
    
public voidsetBufferSize(int size)

        if (size > bb.getLimit()) {// ??????
            bb.setLimit(size);
        }
    
protected voidsetConverter()


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

        gotEnc = true;
        if (enc == null)
            enc = DEFAULT_ENCODING;
        conv = (C2BConverter) encoders.get(enc);
        if (conv == null) {
            
            if (Globals.IS_SECURITY_ENABLED){
                try{
                    conv = (C2BConverter)AccessController.doPrivileged(
                            new PrivilegedExceptionAction(){

                                public Object run() throws IOException{
                                    return new C2BConverter(bb, enc);
                                }

                            }
                    );              
                }catch(PrivilegedActionException ex){
                    Exception e = ex.getException();
                    if (e instanceof IOException)
                        throw (IOException)e; 
                }
            } else {
                conv = new C2BConverter(bb, enc);
            }
            
            encoders.put(enc, conv);

        }
    
public voidsetEncoding(java.lang.String s)

        enc = s;
    
public voidsetResponse(org.apache.coyote.Response coyoteResponse)
Associated Coyote response.

param
coyoteResponse Associated Coyote response

	this.coyoteResponse = coyoteResponse;
    
public voidsetSuspended(boolean suspended)
Set the suspended flag.

param
suspended New suspended flag value

        this.suspended = suspended;
    
public voidwrite(byte[] b, int off, int len)


        if (suspended)
            return;

        writeBytes(b, off, len);

    
public voidwrite(int c)


        if (suspended)
            return;

        conv.convert((char) c);
        conv.flushBuffer();
        charsWritten++;
        
    
public voidwrite(char[] c)


        if (suspended)
            return;

        write(c, 0, c.length);

    
public voidwrite(char[] c, int off, int len)


        if (suspended)
            return;

        conv.convert(c, off, len);
        conv.flushBuffer();
        charsWritten += len;

    
public voidwrite(java.lang.String s, int off, int len)
Append a string to the buffer


        if (suspended)
            return;

        charsWritten += len;
        if (s == null)
            s = "null";
        conv.convert(s, off, len);
        conv.flushBuffer();

    
public voidwrite(java.lang.String s)


        if (suspended)
            return;

        if (s == null)
            s = "null";
        conv.convert(s);
        conv.flushBuffer();

    
public voidwriteByte(int b)


        if (suspended)
            return;

        bb.append((byte) b);
        bytesWritten++;

    
private voidwriteBytes(byte[] b, int off, int len)


        if (closed)
            return;

        bb.append(b, off, len);
        bytesWritten += len;

        // if called from within flush(), then immediately flush
        // remaining bytes
        if (doFlush) {
            bb.flushBuffer();
        }