Mega Code Archive

 
Categories / Java / Servlets
 

Compression Response Stream servlets

/* * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.IOException; import java.io.OutputStream; import java.util.zip.GZIPOutputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; /**  * Implementation of <b>ServletOutputStream</b> that works with  * the CompressionServletResponseWrapper implementation.  *  * @author Amy Roh  * @author Dmitri Valdin  * @version $Revision: 1.3 $, $Date: 2004/03/18 16:40:33 $  */ public class CompressionResponseStream     extends ServletOutputStream {     /**      * Construct a servlet output stream associated with the specified Response.      *      * @param response The associated response      */     public CompressionResponseStream(HttpServletResponse response) throws IOException{         super();         closed = false;         this.response = response;         this.output = response.getOutputStream();     }     /**      * The threshold number which decides to compress or not.      * Users can configure in web.xml to set it to fit their needs.      */     protected int compressionThreshold = 0;     /**      * Debug level      */     private int debug = 0;     /**      * The buffer through which all of our output bytes are passed.      */     protected byte[] buffer = null;     /**      * The number of data bytes currently in the buffer.      */     protected int bufferCount = 0;     /**      * The underlying gzip output stream to which we should write data.      */     protected GZIPOutputStream gzipstream = null;     /**      * Has this stream been closed?      */     protected boolean closed = false;     /**      * The content length past which we will not write, or -1 if there is      * no defined content length.      */     protected int length = -1;     /**      * The response with which this servlet output stream is associated.      */     protected HttpServletResponse response = null;     /**      * The underlying servket output stream to which we should write data.      */     protected ServletOutputStream output = null;     /**      * Set debug level      */     public void setDebugLevel(int debug) {         this.debug = debug;     }     /**      * Set the compressionThreshold number and create buffer for this size      */     protected void setBuffer(int threshold) {         compressionThreshold = threshold;         buffer = new byte[compressionThreshold];         if (debug > 1) {             System.out.println("buffer is set to "+compressionThreshold);         }     }     /**      * Close this output stream, causing any buffered data to be flushed and      * any further output data to throw an IOException.      */     public void close() throws IOException {         if (debug > 1) {             System.out.println("close() @ CompressionResponseStream");         }         if (closed)             throw new IOException("This output stream has already been closed");         if (gzipstream != null) {             flushToGZip();             gzipstream.close();             gzipstream = null;         } else {             if (bufferCount > 0) {                 if (debug > 2) {                     System.out.print("output.write(");                     System.out.write(buffer, 0, bufferCount);                     System.out.println(")");                 }                 output.write(buffer, 0, bufferCount);                 bufferCount = 0;             }         }         output.close();         closed = true;     }     /**      * Flush any buffered data for this output stream, which also causes the      * response to be committed.      */     public void flush() throws IOException {         if (debug > 1) {             System.out.println("flush() @ CompressionResponseStream");         }         if (closed) {             throw new IOException("Cannot flush a closed output stream");         }         if (gzipstream != null) {             gzipstream.flush();         }     }     public void flushToGZip() throws IOException {         if (debug > 1) {             System.out.println("flushToGZip() @ CompressionResponseStream");         }         if (bufferCount > 0) {             if (debug > 1) {                 System.out.println("flushing out to GZipStream, bufferCount = " + bufferCount);             }             writeToGZip(buffer, 0, bufferCount);             bufferCount = 0;         }     }     /**      * Write the specified byte to our output stream.      *      * @param b The byte to be written      *      * @exception IOException if an input/output error occurs      */     public void write(int b) throws IOException {         if (debug > 1) {             System.out.println("write "+b+" in CompressionResponseStream ");         }         if (closed)             throw new IOException("Cannot write to a closed output stream");         if (bufferCount >= buffer.length) {             flushToGZip();         }         buffer[bufferCount++] = (byte) b;     }     /**      * Write <code>b.length</code> bytes from the specified byte array      * to our output stream.      *      * @param b The byte array to be written      *      * @exception IOException if an input/output error occurs      */     public void write(byte b[]) throws IOException {         write(b, 0, b.length);     }     /**      * Write <code>len</code> bytes from the specified byte array, starting      * at the specified offset, to our output stream.      *      * @param b The byte array containing the bytes to be written      * @param off Zero-relative starting offset of the bytes to be written      * @param len The number of bytes to be written      *      * @exception IOException if an input/output error occurs      */     public void write(byte b[], int off, int len) throws IOException {         if (debug > 1) {             System.out.println("write, bufferCount = " + bufferCount + " len = " + len + " off = " + off);         }         if (debug > 2) {             System.out.print("write(");             System.out.write(b, off, len);             System.out.println(")");         }         if (closed)             throw new IOException("Cannot write to a closed output stream");         if (len == 0)             return;         // Can we write into buffer ?         if (len <= (buffer.length - bufferCount)) {             System.arraycopy(b, off, buffer, bufferCount, len);             bufferCount += len;             return;         }         // There is not enough space in buffer. Flush it ...         flushToGZip();         // ... and try again. Note, that bufferCount = 0 here !         if (len <= (buffer.length - bufferCount)) {             System.arraycopy(b, off, buffer, bufferCount, len);             bufferCount += len;             return;         }         // write direct to gzip         writeToGZip(b, off, len);     }     public void writeToGZip(byte b[], int off, int len) throws IOException {         if (debug > 1) {             System.out.println("writeToGZip, len = " + len);         }         if (debug > 2) {             System.out.print("writeToGZip(");             System.out.write(b, off, len);             System.out.println(")");         }         if (gzipstream == null) {             if (debug > 1) {                 System.out.println("new GZIPOutputStream");             }             response.addHeader("Content-Encoding", "gzip");             gzipstream = new GZIPOutputStream(output);         }         gzipstream.write(b, off, len);     }     // -------------------------------------------------------- Package Methods     /**      * Has this response stream been closed?      */     public boolean closed() {         return (this.closed);     } }