KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > winstone > WinstoneOutputStream


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

7 package winstone;
8
9 import java.io.ByteArrayOutputStream JavaDoc;
10 import java.io.IOException JavaDoc;
11 import java.io.OutputStream JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.Stack JavaDoc;
14
15 import javax.servlet.http.Cookie JavaDoc;
16
17 /**
18  * Matches the socket output stream to the servlet output.
19  *
20  * @author <a HREF="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
21  * @version $Id: WinstoneOutputStream.java,v 1.18 2006/08/11 16:14:59 rickknowles Exp $
22  */

23 public class WinstoneOutputStream extends javax.servlet.ServletOutputStream JavaDoc {
24     private static final int DEFAULT_BUFFER_SIZE = 8192;
25     private static final byte[] CR_LF = "\r\n".getBytes();
26     protected OutputStream JavaDoc outStream;
27     protected int bufferSize;
28     protected int bufferPosition;
29     protected int bytesCommitted;
30     protected ByteArrayOutputStream JavaDoc buffer;
31     protected boolean committed;
32     protected boolean bodyOnly;
33     protected WinstoneResponse owner;
34     protected boolean disregardMode = false;
35     protected boolean closed = false;
36     protected Stack JavaDoc includeByteStreams;
37     
38     /**
39      * Constructor
40      */

41     public WinstoneOutputStream(OutputStream JavaDoc out, boolean bodyOnlyForInclude) {
42         this.outStream = out;
43         this.bodyOnly = bodyOnlyForInclude;
44         this.bufferSize = DEFAULT_BUFFER_SIZE;
45         this.committed = false;
46         // this.headersWritten = false;
47
this.buffer = new ByteArrayOutputStream JavaDoc();
48     }
49
50     public void setResponse(WinstoneResponse response) {
51         this.owner = response;
52     }
53
54     public int getBufferSize() {
55         return this.bufferSize;
56     }
57
58     public void setBufferSize(int bufferSize) {
59         if (this.owner.isCommitted()) {
60             throw new IllegalStateException JavaDoc(Launcher.RESOURCES.getString(
61                     "WinstoneOutputStream.AlreadyCommitted"));
62         }
63         this.bufferSize = bufferSize;
64     }
65
66     public boolean isCommitted() {
67         return this.committed;
68     }
69
70     public int getOutputStreamLength() {
71         return this.bytesCommitted + this.bufferPosition;
72     }
73
74     public int getBytesCommitted() {
75         return this.bytesCommitted;
76     }
77     
78     public void setDisregardMode(boolean disregard) {
79         this.disregardMode = disregard;
80     }
81     
82     public void setClosed(boolean closed) {
83         this.closed = closed;
84     }
85
86     public void write(int oneChar) throws IOException JavaDoc {
87         if (this.disregardMode || this.closed) {
88             return;
89         }
90         String JavaDoc contentLengthHeader = this.owner.getHeader(WinstoneResponse.CONTENT_LENGTH_HEADER);
91         if ((contentLengthHeader != null) &&
92                 (this.bytesCommitted >= Integer.parseInt(contentLengthHeader))) {
93             return;
94         }
95 // System.out.println("Out: " + this.bufferPosition + " char=" + (char)oneChar);
96
this.buffer.write(oneChar);
97         this.bufferPosition++;
98         // if (this.headersWritten)
99
if (this.bufferPosition >= this.bufferSize) {
100             commit();
101         } else if ((contentLengthHeader != null) &&
102                 ((this.bufferPosition + this.bytesCommitted)
103                         >= Integer.parseInt(contentLengthHeader))) {
104             commit();
105         }
106     }
107
108     public void commit() throws IOException JavaDoc {
109         this.buffer.flush();
110
111         // If we haven't written the headers yet, write them out
112
if (!this.committed && !this.bodyOnly) {
113             this.owner.validateHeaders();
114             this.committed = true;
115
116             Logger.log(Logger.DEBUG, Launcher.RESOURCES, "WinstoneOutputStream.CommittingOutputStream");
117             
118             String JavaDoc statusLine = this.owner.getProtocol() + " " + this.owner.getStatus();
119             this.outStream.write(statusLine.getBytes("8859_1"));
120             this.outStream.write(CR_LF);
121             Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
122                     "WinstoneOutputStream.ResponseStatus", statusLine);
123
124             // Write headers and cookies
125
for (Iterator JavaDoc i = this.owner.getHeaders().iterator(); i.hasNext();) {
126                 String JavaDoc header = (String JavaDoc) i.next();
127                 this.outStream.write(header.getBytes("8859_1"));
128                 this.outStream.write(CR_LF);
129                 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
130                         "WinstoneOutputStream.Header", header);
131             }
132
133             if (!this.owner.getHeaders().isEmpty()) {
134                 for (Iterator JavaDoc i = this.owner.getCookies().iterator(); i.hasNext();) {
135                     Cookie JavaDoc cookie = (Cookie JavaDoc) i.next();
136                     String JavaDoc cookieText = this.owner.writeCookie(cookie);
137                     this.outStream.write(cookieText.getBytes("8859_1"));
138                     this.outStream.write(CR_LF);
139                     Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
140                             "WinstoneOutputStream.Header", cookieText);
141                 }
142             }
143             this.outStream.write(CR_LF);
144             this.outStream.flush();
145             // Logger.log(Logger.FULL_DEBUG,
146
// Launcher.RESOURCES.getString("HttpProtocol.OutHeaders") + out.toString());
147
}
148         byte content[] = this.buffer.toByteArray();
149 // winstone.ajp13.Ajp13Listener.packetDump(content, content.length);
150
// this.buffer.writeTo(this.outStream);
151
int commitLength = content.length;
152         String JavaDoc contentLengthHeader = this.owner.getHeader(WinstoneResponse.CONTENT_LENGTH_HEADER);
153         if (contentLengthHeader != null) {
154             commitLength = Math.min(Integer.parseInt(contentLengthHeader)
155                     - this.bytesCommitted, content.length);
156         }
157         if (commitLength > 0) {
158             this.outStream.write(content, 0, commitLength);
159         }
160         this.outStream.flush();
161
162         Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
163                 "WinstoneOutputStream.CommittedBytes",
164                 "" + (this.bytesCommitted + commitLength));
165
166         this.bytesCommitted += commitLength;
167         this.buffer.reset();
168         this.bufferPosition = 0;
169     }
170
171     public void reset() {
172         if (isCommitted())
173             throw new IllegalStateException JavaDoc(Launcher.RESOURCES
174                     .getString("WinstoneOutputStream.AlreadyCommitted"));
175         else {
176             Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
177                     "WinstoneOutputStream.ResetBuffer", this.bufferPosition
178                             + "");
179             this.buffer.reset();
180             this.bufferPosition = 0;
181             this.bytesCommitted = 0;
182         }
183     }
184
185     public void finishResponse() throws IOException JavaDoc {
186         this.outStream.flush();
187         this.outStream = null;
188     }
189
190     public void flush() throws IOException JavaDoc {
191         if (this.disregardMode) {
192             return;
193         }
194         Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "WinstoneOutputStream.Flushing");
195         this.buffer.flush();
196         this.commit();
197     }
198
199     public void close() throws IOException JavaDoc {
200         if (!isCommitted() && !this.disregardMode && !this.closed &&
201                 (this.owner.getHeader(WinstoneResponse.CONTENT_LENGTH_HEADER) == null)) {
202             if ((this.owner != null) && !this.bodyOnly) {
203                 this.owner.setContentLength(getOutputStreamLength());
204             }
205         }
206         flush();
207     }
208
209     // Include related buffering
210
public boolean isIncluding() {
211         return (this.includeByteStreams != null && !this.includeByteStreams.isEmpty());
212     }
213     
214     public void startIncludeBuffer() {
215         synchronized (this.buffer) {
216             if (this.includeByteStreams == null) {
217                 this.includeByteStreams = new Stack JavaDoc();
218             }
219         }
220         this.includeByteStreams.push(new ByteArrayOutputStream JavaDoc());
221     }
222     
223     public void finishIncludeBuffer() throws IOException JavaDoc {
224         if (isIncluding()) {
225             ByteArrayOutputStream JavaDoc body = (ByteArrayOutputStream JavaDoc) this.includeByteStreams.pop();
226             OutputStream JavaDoc topStream = this.outStream;
227             if (!this.includeByteStreams.isEmpty()) {
228                 topStream = (OutputStream JavaDoc) this.includeByteStreams.peek();
229             }
230             byte bodyArr[] = body.toByteArray();
231             if (bodyArr.length > 0) {
232                 topStream.write(bodyArr);
233             }
234             body.close();
235         }
236     }
237     
238     public void clearIncludeStackForForward() throws IOException JavaDoc {
239         if (isIncluding()) {
240             for (Iterator JavaDoc i = this.includeByteStreams.iterator(); i.hasNext(); ) {
241                 ((ByteArrayOutputStream JavaDoc) i.next()).close();
242             }
243             this.includeByteStreams.clear();
244         }
245     }
246 }
247
Popular Tags