KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > http > server22 > HttpOutputStream


1 package com.quadcap.http.server22;
2
3 /* Copyright 1998 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.ByteArrayOutputStream JavaDoc;
42 import java.io.BufferedOutputStream JavaDoc;
43 import java.io.IOException JavaDoc;
44 import java.io.OutputStream JavaDoc;
45
46 import javax.servlet.ServletOutputStream JavaDoc;
47
48 import com.quadcap.net.server.WorkerOutputStream;
49
50 import com.quadcap.util.Debug;
51
52 /**
53  * An output stream for writing servlet responses. This is an
54  * abstract class, to be implemented by a network services
55  * implementor. Servlet writers use the output stream to return data
56  * to clients. They access it via the ServletResponse's
57  * getOutputStream method, available from within the servlet's service
58  * method. Subclasses of ServletOutputStream must provide an
59  * implementation of the write(int) method.
60  * <p>
61  *
62  * This implementation is friendly to servlets which return "small"
63  * responses and don't compute Content-Length -- it will compute this
64  * header for them automatically.
65  *
66  * @author Stan Bailes
67  */

68 public class HttpOutputStream extends ServletOutputStream JavaDoc {
69     WorkerOutputStream os;
70     HttpResponse res;
71     ByteArrayOutputStream JavaDoc bos = new ByteArrayOutputStream JavaDoc();
72     boolean committed = false;
73     boolean autoFlush = true;
74
75     int bufferSize = 32 * 1024;
76
77     /**
78      * Construct a new http output stream, attached to the specified
79      * worker output stream.
80      *
81      * @param os the output stream.
82      */

83     public void reset(WorkerOutputStream os) {
84         this.os = os;
85     this.bos.reset();
86         this.committed = false;
87     }
88
89     /**
90      * Write a byte to the stream
91      *
92      * @param b the byte
93      */

94     public void write(int b) throws IOException JavaDoc {
95         if (committed) {
96             os.write(b);
97         } else if (bos.size() >= bufferSize) {
98             res.writeHeaders();
99             bos.writeTo(os);
100             committed = true;
101             os.write(b);
102         } else {
103             bos.write(b);
104         }
105     }
106
107     /**
108      * Write a bunch of bytes in one shot.
109      *
110      * @param buf a buffer where those bytes live
111      * @param off the position in the buffer of the first byte to write
112      * @param len the number of bytes to write
113      *
114      * @exception IOException may be thrown
115      */

116     public void write(byte[] buf, int off, int len) throws IOException JavaDoc {
117         if (committed) {
118             os.write(buf, off, len);
119         } else if (bos.size() + len >= bufferSize) {
120             res.writeHeaders();
121             bos.writeTo(os);
122             committed = true;
123             os.write(buf, off, len);
124         } else {
125             bos.write(buf, off, len);
126         }
127     }
128
129     /**
130      * Flush any buffered output to tht client
131      */

132     public final void flushBuffered() throws IOException JavaDoc {
133         if (!committed) {
134             int len = bos.size();
135             if (len > 0) {
136                 res.maybeSetContentLength(len);
137             }
138             res.writeHeaders();
139             bos.writeTo(os);
140             committed = true;
141     }
142     os.flush();
143     }
144
145     /**
146      * Flush the underlying stream
147      */

148     public final void flush() throws IOException JavaDoc {
149         flushBuffered();
150     }
151
152     /**
153      * Close does nothing, to prevent clients from closing streams when they
154      * really don't want to
155      */

156     public final void close() throws IOException JavaDoc {
157         flushBuffered();
158     }
159
160     public final void reallyClose() throws IOException JavaDoc {
161         os.close();
162     }
163         
164     /**
165      * Discard any bytes written so far if possible, and return true if
166      * we were able to do so.
167      */

168     public boolean discard() {
169     if (!committed) {
170         bos.reset();
171         return true;
172     }
173     return false;
174     }
175     
176     /**
177      * Set up the connection with the http response object so we can
178      * control flushing the headers when we've reached our buffered
179      * limit.
180      *
181      * @param res the http response object associated with this request
182      */

183     void setResponse(HttpResponse res) {
184         this.res = res;
185     }
186
187     /**
188      * Return the underlying output stream
189      */

190     WorkerOutputStream getOutputStream() { return os; }
191
192     final void setBufferSize(int size) throws IllegalStateException JavaDoc {
193         if (committed) {
194             throw new IllegalStateException JavaDoc("Response already committed");
195         }
196         this.bufferSize = size;
197     }
198
199     final int getBufferSize() {
200         return bufferSize;
201     }
202
203     final boolean isCommitted() {
204         return committed;
205     }
206
207     final void reset() throws IllegalStateException JavaDoc {
208         if (committed) {
209             throw new IllegalStateException JavaDoc("Response already committed");
210         }
211         bos.reset();
212     }
213
214     final boolean getAutoFlush() {
215         return autoFlush;
216     }
217
218     final void setAutoFlush(boolean autoFlush) {
219         this.autoFlush = autoFlush;
220     }
221
222     public int getRemaining() {
223         return bufferSize - bos.size();
224     }
225 }
226
Popular Tags