KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > myvietnam > mvncore > servlet > filter > CompressionResponseStream


1 /*
2  * CompressionResponseStream.java
3  * $Header: /cvsroot/mvnforum/myvietnam/src/net/myvietnam/mvncore/servlet/filter/CompressionResponseStream.java,v 1.2 2004/03/16 12:58:46 minhnn Exp $
4  * $Revision: 1.2 $
5  * $Date: 2004/03/16 12:58:46 $
6  *
7  * ====================================================================
8  *
9  * The Apache Software License, Version 1.1
10  *
11  * Copyright (c) 1999 The Apache Software Foundation. All rights
12  * reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  *
18  * 1. Redistributions of source code must retain the above copyright
19  * notice, this list of conditions and the following disclaimer.
20  *
21  * 2. Redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in
23  * the documentation and/or other materials provided with the
24  * distribution.
25  *
26  * 3. The end-user documentation included with the redistribution, if
27  * any, must include the following acknowlegement:
28  * "This product includes software developed by the
29  * Apache Software Foundation (http://www.apache.org/)."
30  * Alternately, this acknowlegement may appear in the software itself,
31  * if and wherever such third-party acknowlegements normally appear.
32  *
33  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
34  * Foundation" must not be used to endorse or promote products derived
35  * from this software without prior written permission. For written
36  * permission, please contact apache@apache.org.
37  *
38  * 5. Products derived from this software may not be called "Apache"
39  * nor may "Apache" appear in their names without prior written
40  * permission of the Apache Group.
41  *
42  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
43  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
45  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
46  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
47  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
48  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
49  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
50  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
51  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
52  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53  * SUCH DAMAGE.
54  * ====================================================================
55  *
56  * This software consists of voluntary contributions made by many
57  * individuals on behalf of the Apache Software Foundation. For more
58  * information on the Apache Software Foundation, please see
59  * <http://www.apache.org/>.
60  *
61  * [Additional notices, if required by prior licensing conditions]
62  *
63  */

64
65 package net.myvietnam.mvncore.servlet.filter;
66
67 import java.io.IOException JavaDoc;
68 import java.util.zip.GZIPOutputStream JavaDoc;
69 import javax.servlet.ServletOutputStream JavaDoc;
70 import javax.servlet.http.HttpServletResponse JavaDoc;
71
72 import org.apache.commons.logging.Log;
73 import org.apache.commons.logging.LogFactory;
74
75
76 /**
77  * Implementation of <b>ServletOutputStream</b> that works with
78  * the CompressionServletResponseWrapper implementation.
79  *
80  * @author Amy Roh
81  * @author Dmitri Valdin
82  * @version $Revision: 1.2 $, $Date: 2004/03/16 12:58:46 $
83  */

84
85 public class CompressionResponseStream extends ServletOutputStream JavaDoc {
86
87     //minhnn : I remove the log because log4j does not support TRACE level
88
private static Log log = LogFactory.getLog(CompressionResponseStream.class);
89
90     // ----------------------------------------------------------- Constructors
91

92
93     /**
94      * Construct a servlet output stream associated with the specified Response.
95      *
96      * @param response The associated response
97      */

98     public CompressionResponseStream(HttpServletResponse JavaDoc response) throws IOException JavaDoc{
99
100         super();
101         closed = false;
102         this.response = response;
103         this.output = response.getOutputStream();
104
105     }
106
107
108     // ----------------------------------------------------- Instance Variables
109

110
111     /**
112      * The threshold number which decides to compress or not.
113      * Users can configure in web.xml to set it to fit their needs.
114      */

115     protected int compressionThreshold = 0;
116
117     /**
118      * Debug level
119      */

120 // private int debug = 0;
121

122     /**
123      * The buffer through which all of our output bytes are passed.
124      */

125     protected byte[] buffer = null;
126
127     /**
128      * The number of data bytes currently in the buffer.
129      */

130     protected int bufferCount = 0;
131
132     /**
133      * The underlying gzip output stream to which we should write data.
134      */

135     protected GZIPOutputStream JavaDoc gzipstream = null;
136
137     /**
138      * Has this stream been closed?
139      */

140     protected boolean closed = false;
141
142     /**
143      * The content length past which we will not write, or -1 if there is
144      * no defined content length.
145      */

146     protected int length = -1;
147
148     /**
149      * The response with which this servlet output stream is associated.
150      */

151     protected HttpServletResponse JavaDoc response = null;
152
153     /**
154      * The underlying servket output stream to which we should write data.
155      */

156     protected ServletOutputStream JavaDoc output = null;
157
158
159     // --------------------------------------------------------- Public Methods
160

161     /**
162      * Set debug level
163      */

164 // public void setDebugLevel(int debug) {
165
// this.debug = debug;
166
// }
167

168
169     /**
170      * Set the compressionThreshold number and create buffer for this size
171      */

172     protected void setBuffer(int threshold) {
173         compressionThreshold = threshold;
174         buffer = new byte[compressionThreshold];
175         //log.trace("buffer is set to " + compressionThreshold);
176
}
177
178     /**
179      * Close this output stream, causing any buffered data to be flushed and
180      * any further output data to throw an IOException.
181      */

182     public void close() throws IOException JavaDoc {
183
184         //log.trace("close() @ CompressionResponseStream", new IOException("tracing"));
185
if (closed) {
186             //minhnn : instead of throw IOException, we should log waring or even
187
// ignore it so that it does not throw exception when close many time
188
throw new IOException JavaDoc("This output stream has already been closed");
189             //log.warn("This output stream has already been closed");
190
}
191
192         if (gzipstream != null) {
193             flushToGZip();
194             gzipstream.close();
195             gzipstream = null;
196         } else {
197             if (bufferCount > 0) {
198                 // minhnn comment
199
/*
200                 if (debug > 2) {
201                     System.out.print("output.write(");
202                     System.out.write(buffer, 0, bufferCount);
203                     System.out.println(")");
204                 }*/

205                 output.write(buffer, 0, bufferCount);
206                 bufferCount = 0;
207             }
208         }
209
210         output.close();
211         closed = true;
212
213     }
214
215
216     /**
217      * Flush any buffered data for this output stream, which also causes the
218      * response to be committed.
219      */

220     public void flush() throws IOException JavaDoc {
221
222         //log.trace("flush() @ CompressionResponseStream");
223
if (closed) {
224             //throw new IOException("Cannot flush a closed output stream");
225
log.warn("Cannot flush a closed output stream");
226         }
227
228         if (gzipstream != null) {
229             gzipstream.flush();
230         }
231
232     }
233
234     public void flushToGZip() throws IOException JavaDoc {
235
236         //log.trace("flushToGZip() @ CompressionResponseStream");
237
if (bufferCount > 0) {
238             //log.trace("flushing out to GZipStream, bufferCount = " + bufferCount);
239
writeToGZip(buffer, 0, bufferCount);
240             bufferCount = 0;
241         }
242
243     }
244
245     /**
246      * Write the specified byte to our output stream.
247      *
248      * @param b The byte to be written
249      *
250      * @exception IOException if an input/output error occurs
251      */

252     public void write(int b) throws IOException JavaDoc {
253
254         //log.trace("write " + b + " in CompressionResponseStream ");
255
if (closed)
256             throw new IOException JavaDoc("Cannot write to a closed output stream");
257
258         if (bufferCount >= buffer.length) {
259             flushToGZip();
260         }
261
262         buffer[bufferCount++] = (byte) b;
263
264     }
265
266
267     /**
268      * Write <code>b.length</code> bytes from the specified byte array
269      * to our output stream.
270      *
271      * @param b The byte array to be written
272      *
273      * @exception IOException if an input/output error occurs
274      */

275     public void write(byte b[]) throws IOException JavaDoc {
276
277         write(b, 0, b.length);
278
279     }
280
281
282     /**
283      * Write <code>len</code> bytes from the specified byte array, starting
284      * at the specified offset, to our output stream.
285      *
286      * @param b The byte array containing the bytes to be written
287      * @param off Zero-relative starting offset of the bytes to be written
288      * @param len The number of bytes to be written
289      *
290      * @exception IOException if an input/output error occurs
291      */

292     public void write(byte b[], int off, int len) throws IOException JavaDoc {
293
294         //log.trace("write, bufferCount = " + bufferCount + " len = " + len + " off = " + off);
295
/* minhnn comment
296         if (debug > 2) {
297             System.out.print("write(");
298             System.out.write(b, off, len);
299             System.out.println(")");
300         }*/

301
302         if (closed)
303             throw new IOException JavaDoc("Cannot write to a closed output stream");
304
305         if (len == 0)
306             return;
307
308         // Can we write into buffer ?
309
if (len <= (buffer.length - bufferCount)) {
310             System.arraycopy(b, off, buffer, bufferCount, len);
311             bufferCount += len;
312             return;
313         }
314
315         // There is not enough space in buffer. Flush it ...
316
flushToGZip();
317
318         // ... and try again. Note, that bufferCount = 0 here !
319
if (len <= (buffer.length - bufferCount)) {
320             System.arraycopy(b, off, buffer, bufferCount, len);
321             bufferCount += len;
322             return;
323         }
324
325         // write direct to gzip
326
writeToGZip(b, off, len);
327     }
328
329     public void writeToGZip(byte b[], int off, int len) throws IOException JavaDoc {
330
331         //log.trace("writeToGZip, len = " + len);
332
/* minhnn comment
333         if (debug > 2) {
334             System.out.print("writeToGZip(");
335             System.out.write(b, off, len);
336             System.out.println(")");
337         }*/

338         if (gzipstream == null) {
339             //log.trace("new GZIPOutputStream");
340
response.addHeader("Content-Encoding", "gzip");
341             gzipstream = new GZIPOutputStream JavaDoc(output);
342         }
343         gzipstream.write(b, off, len);
344
345     }
346
347
348     // -------------------------------------------------------- Package Methods
349

350
351     /**
352      * Has this response stream been closed?
353      */

354     public boolean closed() {
355
356         return (this.closed);
357
358     }
359
360 }
361
Popular Tags