source: nutchez-0.1/tomcat/webapps/examples/WEB-INF/classes/compressionFilters/CompressionResponseStream.java @ 66

Last change on this file since 66 was 66, checked in by waue, 15 years ago

NutchEz - an easy way to nutch

File size: 8.8 KB
Line 
1/*
2* Licensed to the Apache Software Foundation (ASF) under one or more
3* contributor license agreements.  See the NOTICE file distributed with
4* this work for additional information regarding copyright ownership.
5* The ASF licenses this file to You under the Apache License, Version 2.0
6* (the "License"); you may not use this file except in compliance with
7* the License.  You may obtain a copy of the License at
8*
9*     http://www.apache.org/licenses/LICENSE-2.0
10*
11* Unless required by applicable law or agreed to in writing, software
12* distributed under the License is distributed on an "AS IS" BASIS,
13* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14* See the License for the specific language governing permissions and
15* limitations under the License.
16*/
17package compressionFilters;
18
19import java.io.IOException;
20import java.io.OutputStream;
21import java.util.zip.GZIPOutputStream;
22import javax.servlet.ServletOutputStream;
23import javax.servlet.http.HttpServletResponse;
24
25
26/**
27 * Implementation of <b>ServletOutputStream</b> that works with
28 * the CompressionServletResponseWrapper implementation.
29 *
30 * @author Amy Roh
31 * @author Dmitri Valdin
32 * @version $Revision: 500668 $, $Date: 2007-01-28 00:07:51 +0100 (Sun, 28 Jan 2007) $
33 */
34
35public class CompressionResponseStream
36    extends ServletOutputStream {
37
38
39    // ----------------------------------------------------------- Constructors
40
41
42    /**
43     * Construct a servlet output stream associated with the specified Response.
44     *
45     * @param response The associated response
46     */
47    public CompressionResponseStream(HttpServletResponse response) throws IOException{
48
49        super();
50        closed = false;
51        this.response = response;
52        this.output = response.getOutputStream();
53
54    }
55
56
57    // ----------------------------------------------------- Instance Variables
58
59
60    /**
61     * The threshold number which decides to compress or not.
62     * Users can configure in web.xml to set it to fit their needs.
63     */
64    protected int compressionThreshold = 0;
65
66    /**
67     * Debug level
68     */
69    private int debug = 0;
70
71    /**
72     * The buffer through which all of our output bytes are passed.
73     */
74    protected byte[] buffer = null;
75
76    /**
77     * The number of data bytes currently in the buffer.
78     */
79    protected int bufferCount = 0;
80
81    /**
82     * The underlying gzip output stream to which we should write data.
83     */
84    protected OutputStream gzipstream = null;
85
86    /**
87     * Has this stream been closed?
88     */
89    protected boolean closed = false;
90
91    /**
92     * The content length past which we will not write, or -1 if there is
93     * no defined content length.
94     */
95    protected int length = -1;
96
97    /**
98     * The response with which this servlet output stream is associated.
99     */
100    protected HttpServletResponse response = null;
101
102    /**
103     * The underlying servket output stream to which we should write data.
104     */
105    protected ServletOutputStream output = null;
106
107
108    // --------------------------------------------------------- Public Methods
109
110    /**
111     * Set debug level
112     */
113    public void setDebugLevel(int debug) {
114        this.debug = debug;
115    }
116
117
118    /**
119     * Set the compressionThreshold number and create buffer for this size
120     */
121    protected void setBuffer(int threshold) {
122        compressionThreshold = threshold;
123        buffer = new byte[compressionThreshold];
124        if (debug > 1) {
125            System.out.println("buffer is set to "+compressionThreshold);
126        }
127    }
128
129    /**
130     * Close this output stream, causing any buffered data to be flushed and
131     * any further output data to throw an IOException.
132     */
133    public void close() throws IOException {
134
135        if (debug > 1) {
136            System.out.println("close() @ CompressionResponseStream");
137        }
138        if (closed)
139            throw new IOException("This output stream has already been closed");
140
141        if (gzipstream != null) {
142            flushToGZip();
143            gzipstream.close();
144            gzipstream = null;
145        } else {
146            if (bufferCount > 0) {
147                if (debug > 2) {
148                    System.out.print("output.write(");
149                    System.out.write(buffer, 0, bufferCount);
150                    System.out.println(")");
151                }
152                output.write(buffer, 0, bufferCount);
153                bufferCount = 0;
154            }
155        }
156
157        output.close();
158        closed = true;
159
160    }
161
162
163    /**
164     * Flush any buffered data for this output stream, which also causes the
165     * response to be committed.
166     */
167    public void flush() throws IOException {
168
169        if (debug > 1) {
170            System.out.println("flush() @ CompressionResponseStream");
171        }
172        if (closed) {
173            throw new IOException("Cannot flush a closed output stream");
174        }
175
176        if (gzipstream != null) {
177            gzipstream.flush();
178        }
179
180    }
181
182    public void flushToGZip() throws IOException {
183
184        if (debug > 1) {
185            System.out.println("flushToGZip() @ CompressionResponseStream");
186        }
187        if (bufferCount > 0) {
188            if (debug > 1) {
189                System.out.println("flushing out to GZipStream, bufferCount = " + bufferCount);
190            }
191            writeToGZip(buffer, 0, bufferCount);
192            bufferCount = 0;
193        }
194
195    }
196
197    /**
198     * Write the specified byte to our output stream.
199     *
200     * @param b The byte to be written
201     *
202     * @exception IOException if an input/output error occurs
203     */
204    public void write(int b) throws IOException {
205
206        if (debug > 1) {
207            System.out.println("write "+b+" in CompressionResponseStream ");
208        }
209        if (closed)
210            throw new IOException("Cannot write to a closed output stream");
211
212        if (bufferCount >= buffer.length) {
213            flushToGZip();
214        }
215
216        buffer[bufferCount++] = (byte) b;
217
218    }
219
220
221    /**
222     * Write <code>b.length</code> bytes from the specified byte array
223     * to our output stream.
224     *
225     * @param b The byte array to be written
226     *
227     * @exception IOException if an input/output error occurs
228     */
229    public void write(byte b[]) throws IOException {
230
231        write(b, 0, b.length);
232
233    }
234
235
236    /**
237     * Write <code>len</code> bytes from the specified byte array, starting
238     * at the specified offset, to our output stream.
239     *
240     * @param b The byte array containing the bytes to be written
241     * @param off Zero-relative starting offset of the bytes to be written
242     * @param len The number of bytes to be written
243     *
244     * @exception IOException if an input/output error occurs
245     */
246    public void write(byte b[], int off, int len) throws IOException {
247
248        if (debug > 1) {
249            System.out.println("write, bufferCount = " + bufferCount + " len = " + len + " off = " + off);
250        }
251        if (debug > 2) {
252            System.out.print("write(");
253            System.out.write(b, off, len);
254            System.out.println(")");
255        }
256
257        if (closed)
258            throw new IOException("Cannot write to a closed output stream");
259
260        if (len == 0)
261            return;
262
263        // Can we write into buffer ?
264        if (len <= (buffer.length - bufferCount)) {
265            System.arraycopy(b, off, buffer, bufferCount, len);
266            bufferCount += len;
267            return;
268        }
269
270        // There is not enough space in buffer. Flush it ...
271        flushToGZip();
272
273        // ... and try again. Note, that bufferCount = 0 here !
274        if (len <= (buffer.length - bufferCount)) {
275            System.arraycopy(b, off, buffer, bufferCount, len);
276            bufferCount += len;
277            return;
278        }
279
280        // write direct to gzip
281        writeToGZip(b, off, len);
282    }
283
284    public void writeToGZip(byte b[], int off, int len) throws IOException {
285
286        if (debug > 1) {
287            System.out.println("writeToGZip, len = " + len);
288        }
289        if (debug > 2) {
290            System.out.print("writeToGZip(");
291            System.out.write(b, off, len);
292            System.out.println(")");
293        }
294        if (gzipstream == null) {
295            if (debug > 1) {
296                System.out.println("new GZIPOutputStream");
297            }
298            if (response.isCommitted()) {
299                if (debug > 1)
300                    System.out.print("Response already committed. Using original output stream");
301                gzipstream = output;
302            } else {
303                response.addHeader("Content-Encoding", "gzip");
304                gzipstream = new GZIPOutputStream(output);
305            }
306        }
307        gzipstream.write(b, off, len);
308
309    }
310
311
312    // -------------------------------------------------------- Package Methods
313
314
315    /**
316     * Has this response stream been closed?
317     */
318    public boolean closed() {
319
320        return (this.closed);
321
322    }
323
324}
Note: See TracBrowser for help on using the repository browser.