Package winstone

Source Code of winstone.WinstoneOutputStream

/*
* Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
* Distributed under the terms of either:
* - the common development and distribution license (CDDL), v1.0; or
* - the GNU Lesser General Public License, v2.1 or later
*/
package winstone;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Stack;

import javax.servlet.http.Cookie;

/**
* Matches the socket output stream to the servlet output.
*
* @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
* @version $Id: WinstoneOutputStream.java,v 1.19 2007/10/14 14:48:14 rickknowles Exp $
*/
public class WinstoneOutputStream extends javax.servlet.ServletOutputStream {
    private static final int DEFAULT_BUFFER_SIZE = 8192;
    private static final byte[] CR_LF = "\r\n".getBytes();
    protected OutputStream outStream;
    protected int bufferSize;
    protected int bufferPosition;
    protected int bytesCommitted;
    protected ByteArrayOutputStream buffer;
    protected boolean committed;
    protected boolean bodyOnly;
    protected WinstoneResponse owner;
    protected boolean disregardMode = false;
    protected boolean closed = false;
    protected Stack includeByteStreams;
   
    /**
     * Constructor
     */
    public WinstoneOutputStream(OutputStream out, boolean bodyOnlyForInclude) {
        this.outStream = out;
        this.bodyOnly = bodyOnlyForInclude;
        this.bufferSize = DEFAULT_BUFFER_SIZE;
        this.committed = false;
        // this.headersWritten = false;
        this.buffer = new ByteArrayOutputStream();
    }

    public void setResponse(WinstoneResponse response) {
        this.owner = response;
    }

    public int getBufferSize() {
        return this.bufferSize;
    }

    public void setBufferSize(int bufferSize) {
        if (this.owner.isCommitted()) {
            throw new IllegalStateException(Launcher.RESOURCES.getString(
                    "WinstoneOutputStream.AlreadyCommitted"));
        }
        this.bufferSize = bufferSize;
    }

    public boolean isCommitted() {
        return this.committed;
    }

    public int getOutputStreamLength() {
        return this.bytesCommitted + this.bufferPosition;
    }

    public int getBytesCommitted() {
        return this.bytesCommitted;
    }
   
    public void setDisregardMode(boolean disregard) {
        this.disregardMode = disregard;
    }
   
    public void setClosed(boolean closed) {
        this.closed = closed;
    }

    public void write(int oneChar) throws IOException {
        if (this.disregardMode || this.closed) {
            return;
        }
        String contentLengthHeader = this.owner.getHeader(WinstoneResponse.CONTENT_LENGTH_HEADER);
        if ((contentLengthHeader != null) &&
                (this.bytesCommitted >= Integer.parseInt(contentLengthHeader))) {
            return;
        }
//        System.out.println("Out: " + this.bufferPosition + " char=" + (char)oneChar);
        this.buffer.write(oneChar);
        this.bufferPosition++;
        // if (this.headersWritten)
        if (this.bufferPosition >= this.bufferSize) {
            commit();
        } else if ((contentLengthHeader != null) &&
                ((this.bufferPosition + this.bytesCommitted)
                        >= Integer.parseInt(contentLengthHeader))) {
            commit();
        }
    }

    public void commit() throws IOException {
        this.buffer.flush();

        // If we haven't written the headers yet, write them out
        if (!this.committed && !this.bodyOnly) {
            this.owner.validateHeaders();
            this.committed = true;

            Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneOutputStream.CommittingOutputStream");
           
            int statusCode = this.owner.getStatus();
            String reason = Launcher.RESOURCES.getString("WinstoneOutputStream.reasonPhrase." + statusCode);
            String statusLine = this.owner.getProtocol() + " " + statusCode + " " +
                    (reason == null ? "No reason" : reason);
            this.outStream.write(statusLine.getBytes("8859_1"));
            this.outStream.write(CR_LF);
            Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
                    "WinstoneOutputStream.ResponseStatus", statusLine);

            // Write headers and cookies
            for (Iterator i = this.owner.getHeaders().iterator(); i.hasNext();) {
                String header = (String) i.next();
                this.outStream.write(header.getBytes("8859_1"));
                this.outStream.write(CR_LF);
                Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
                        "WinstoneOutputStream.Header", header);
            }

            if (!this.owner.getHeaders().isEmpty()) {
                for (Iterator i = this.owner.getCookies().iterator(); i.hasNext();) {
                    Cookie cookie = (Cookie) i.next();
                    String cookieText = this.owner.writeCookie(cookie);
                    this.outStream.write(cookieText.getBytes("8859_1"));
                    this.outStream.write(CR_LF);
                    Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
                            "WinstoneOutputStream.Header", cookieText);
                }
            }
            this.outStream.write(CR_LF);
            this.outStream.flush();
            // Logger.log(Logger.FULL_DEBUG,
            // Launcher.RESOURCES.getString("HttpProtocol.OutHeaders") + out.toString());
        }
        byte content[] = this.buffer.toByteArray();
//        winstone.ajp13.Ajp13Listener.packetDump(content, content.length);
//        this.buffer.writeTo(this.outStream);
        int commitLength = content.length;
        String contentLengthHeader = this.owner.getHeader(WinstoneResponse.CONTENT_LENGTH_HEADER);
        if (contentLengthHeader != null) {
            commitLength = Math.min(Integer.parseInt(contentLengthHeader)
                    - this.bytesCommitted, content.length);
        }
        if (commitLength > 0) {
            this.outStream.write(content, 0, commitLength);
        }
        this.outStream.flush();

        Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
                "WinstoneOutputStream.CommittedBytes",
                "" + (this.bytesCommitted + commitLength));

        this.bytesCommitted += commitLength;
        this.buffer.reset();
        this.bufferPosition = 0;
    }

    public void reset() {
        if (isCommitted())
            throw new IllegalStateException(Launcher.RESOURCES
                    .getString("WinstoneOutputStream.AlreadyCommitted"));
        else {
            Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
                    "WinstoneOutputStream.ResetBuffer", this.bufferPosition
                            + "");
            this.buffer.reset();
            this.bufferPosition = 0;
            this.bytesCommitted = 0;
        }
    }

    public void finishResponse() throws IOException {
        this.outStream.flush();
        this.outStream = null;
    }

    public void flush() throws IOException {
        if (this.disregardMode) {
            return;
        }
        Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneOutputStream.Flushing");
        this.buffer.flush();
        this.commit();
    }

    public void close() throws IOException {
        if (!isCommitted() && !this.disregardMode && !this.closed &&
                (this.owner.getHeader(WinstoneResponse.CONTENT_LENGTH_HEADER) == null)) {
            if ((this.owner != null) && !this.bodyOnly) {
                this.owner.setContentLength(getOutputStreamLength());
            }
        }
        flush();
    }

    // Include related buffering
    public boolean isIncluding() {
        return (this.includeByteStreams != null && !this.includeByteStreams.isEmpty());
    }
   
    public void startIncludeBuffer() {
        synchronized (this.buffer) {
            if (this.includeByteStreams == null) {
                this.includeByteStreams = new Stack();
            }
        }
        this.includeByteStreams.push(new ByteArrayOutputStream());
    }
   
    public void finishIncludeBuffer() throws IOException {
        if (isIncluding()) {
            ByteArrayOutputStream body = (ByteArrayOutputStream) this.includeByteStreams.pop();
            OutputStream topStream = this.outStream;
            if (!this.includeByteStreams.isEmpty()) {
                topStream = (OutputStream) this.includeByteStreams.peek();
            }
            byte bodyArr[] = body.toByteArray();
            if (bodyArr.length > 0) {
                topStream.write(bodyArr);
            }
            body.close();
        }
    }
   
    public void clearIncludeStackForForward() throws IOException {
        if (isIncluding()) {
            for (Iterator i = this.includeByteStreams.iterator(); i.hasNext(); ) {
                ((ByteArrayOutputStream) i.next()).close();
            }
            this.includeByteStreams.clear();
        }
    }
}
TOP

Related Classes of winstone.WinstoneOutputStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.