KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > compressionFilters > CompressionResponseStream


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  *
21  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
22  *
23  * Portions Copyright Apache Software Foundation.
24  */

25
26 package compressionFilters;
27
28 import java.io.IOException JavaDoc;
29 import java.io.OutputStream JavaDoc;
30 import java.util.zip.GZIPOutputStream JavaDoc;
31 import javax.servlet.ServletOutputStream JavaDoc;
32 import javax.servlet.http.HttpServletResponse JavaDoc;
33
34
35 /**
36  * Implementation of <b>ServletOutputStream</b> that works with
37  * the CompressionServletResponseWrapper implementation.
38  *
39  * @author Amy Roh
40  * @author Dmitri Valdin
41  * @version $Revision: 1.2 $, $Date: 2005/12/08 01:13:47 $
42  */

43
44 public class CompressionResponseStream
45     extends ServletOutputStream JavaDoc {
46
47
48     // ----------------------------------------------------------- Constructors
49

50
51     /**
52      * Construct a servlet output stream associated with the specified Response.
53      *
54      * @param response The associated response
55      */

56     public CompressionResponseStream(HttpServletResponse JavaDoc response) throws IOException JavaDoc{
57
58         super();
59         closed = false;
60         this.response = response;
61         this.output = response.getOutputStream();
62
63     }
64
65
66     // ----------------------------------------------------- Instance Variables
67

68
69     /**
70      * The threshold number which decides to compress or not.
71      * Users can configure in web.xml to set it to fit their needs.
72      */

73     protected int compressionThreshold = 0;
74
75     /**
76      * Debug level
77      */

78     private int debug = 0;
79
80     /**
81      * The buffer through which all of our output bytes are passed.
82      */

83     protected byte[] buffer = null;
84
85     /**
86      * The number of data bytes currently in the buffer.
87      */

88     protected int bufferCount = 0;
89
90     /**
91      * The underlying gzip output stream to which we should write data.
92      */

93     protected GZIPOutputStream JavaDoc gzipstream = null;
94
95     /**
96      * Has this stream been closed?
97      */

98     protected boolean closed = false;
99
100     /**
101      * The content length past which we will not write, or -1 if there is
102      * no defined content length.
103      */

104     protected int length = -1;
105
106     /**
107      * The response with which this servlet output stream is associated.
108      */

109     protected HttpServletResponse JavaDoc response = null;
110
111     /**
112      * The underlying servket output stream to which we should write data.
113      */

114     protected ServletOutputStream JavaDoc output = null;
115
116
117     // --------------------------------------------------------- Public Methods
118

119     /**
120      * Set debug level
121      */

122     public void setDebugLevel(int debug) {
123         this.debug = debug;
124     }
125
126
127     /**
128      * Set the compressionThreshold number and create buffer for this size
129      */

130     protected void setBuffer(int threshold) {
131         compressionThreshold = threshold;
132         buffer = new byte[compressionThreshold];
133         if (debug > 1) {
134             System.out.println("buffer is set to "+compressionThreshold);
135         }
136     }
137
138     /**
139      * Close this output stream, causing any buffered data to be flushed and
140      * any further output data to throw an IOException.
141      */

142     public void close() throws IOException JavaDoc {
143
144         if (debug > 1) {
145             System.out.println("close() @ CompressionResponseStream");
146         }
147         if (closed)
148             throw new IOException JavaDoc("This output stream has already been closed");
149
150         if (gzipstream != null) {
151             flushToGZip();
152             gzipstream.close();
153             gzipstream = null;
154         } else {
155             if (bufferCount > 0) {
156                 if (debug > 2) {
157                     System.out.print("output.write(");
158                     System.out.write(buffer, 0, bufferCount);
159                     System.out.println(")");
160                 }
161                 output.write(buffer, 0, bufferCount);
162                 bufferCount = 0;
163             }
164         }
165
166         output.close();
167         closed = true;
168
169     }
170
171
172     /**
173      * Flush any buffered data for this output stream, which also causes the
174      * response to be committed.
175      */

176     public void flush() throws IOException JavaDoc {
177
178         if (debug > 1) {
179             System.out.println("flush() @ CompressionResponseStream");
180         }
181         if (closed) {
182             throw new IOException JavaDoc("Cannot flush a closed output stream");
183         }
184
185         if (gzipstream != null) {
186             gzipstream.flush();
187         }
188
189     }
190
191     public void flushToGZip() throws IOException JavaDoc {
192
193         if (debug > 1) {
194             System.out.println("flushToGZip() @ CompressionResponseStream");
195         }
196         if (bufferCount > 0) {
197             if (debug > 1) {
198                 System.out.println("flushing out to GZipStream, bufferCount = " + bufferCount);
199             }
200             writeToGZip(buffer, 0, bufferCount);
201             bufferCount = 0;
202         }
203
204     }
205
206     /**
207      * Write the specified byte to our output stream.
208      *
209      * @param b The byte to be written
210      *
211      * @exception IOException if an input/output error occurs
212      */

213     public void write(int b) throws IOException JavaDoc {
214
215         if (debug > 1) {
216             System.out.println("write "+b+" in CompressionResponseStream ");
217         }
218         if (closed)
219             throw new IOException JavaDoc("Cannot write to a closed output stream");
220
221         if (bufferCount >= buffer.length) {
222             flushToGZip();
223         }
224
225         buffer[bufferCount++] = (byte) b;
226
227     }
228
229
230     /**
231      * Write <code>b.length</code> bytes from the specified byte array
232      * to our output stream.
233      *
234      * @param b The byte array to be written
235      *
236      * @exception IOException if an input/output error occurs
237      */

238     public void write(byte b[]) throws IOException JavaDoc {
239
240         write(b, 0, b.length);
241
242     }
243
244
245     /**
246      * Write <code>len</code> bytes from the specified byte array, starting
247      * at the specified offset, to our output stream.
248      *
249      * @param b The byte array containing the bytes to be written
250      * @param off Zero-relative starting offset of the bytes to be written
251      * @param len The number of bytes to be written
252      *
253      * @exception IOException if an input/output error occurs
254      */

255     public void write(byte b[], int off, int len) throws IOException JavaDoc {
256
257         if (debug > 1) {
258             System.out.println("write, bufferCount = " + bufferCount + " len = " + len + " off = " + off);
259         }
260         if (debug > 2) {
261             System.out.print("write(");
262             System.out.write(b, off, len);
263             System.out.println(")");
264         }
265
266         if (closed)
267             throw new IOException JavaDoc("Cannot write to a closed output stream");
268
269         if (len == 0)
270             return;
271
272         // Can we write into buffer ?
273
if (len <= (buffer.length - bufferCount)) {
274             System.arraycopy(b, off, buffer, bufferCount, len);
275             bufferCount += len;
276             return;
277         }
278
279         // There is not enough space in buffer. Flush it ...
280
flushToGZip();
281
282         // ... and try again. Note, that bufferCount = 0 here !
283
if (len <= (buffer.length - bufferCount)) {
284             System.arraycopy(b, off, buffer, bufferCount, len);
285             bufferCount += len;
286             return;
287         }
288
289         // write direct to gzip
290
writeToGZip(b, off, len);
291     }
292
293     public void writeToGZip(byte b[], int off, int len) throws IOException JavaDoc {
294
295         if (debug > 1) {
296             System.out.println("writeToGZip, len = " + len);
297         }
298         if (debug > 2) {
299             System.out.print("writeToGZip(");
300             System.out.write(b, off, len);
301             System.out.println(")");
302         }
303         if (gzipstream == null) {
304             if (debug > 1) {
305                 System.out.println("new GZIPOutputStream");
306             }
307             response.addHeader("Content-Encoding", "gzip");
308             gzipstream = new GZIPOutputStream JavaDoc(output);
309         }
310         gzipstream.write(b, off, len);
311
312     }
313
314
315     // -------------------------------------------------------- Package Methods
316

317
318     /**
319      * Has this response stream been closed?
320      */

321     public boolean closed() {
322
323         return (this.closed);
324
325     }
326
327 }
328
Popular Tags