home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-tomcat-addon-1.4.9-installer.exe / CompressionResponseStream.java < prev    next >
Encoding:
Java Source  |  2004-05-17  |  8.6 KB  |  319 lines

  1. /*
  2. * Copyright 2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. *     http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16.  
  17. package compressionFilters;
  18.  
  19. import java.io.IOException;
  20. import java.io.OutputStream;
  21. import java.util.zip.GZIPOutputStream;
  22. import javax.servlet.ServletOutputStream;
  23. import 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: 1.3 $, $Date: 2004/03/18 16:40:28 $
  33.  */
  34.  
  35. public 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 GZIPOutputStream 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.             response.addHeader("Content-Encoding", "gzip");
  299.             gzipstream = new GZIPOutputStream(output);
  300.         }
  301.         gzipstream.write(b, off, len);
  302.  
  303.     }
  304.  
  305.  
  306.     // -------------------------------------------------------- Package Methods
  307.  
  308.  
  309.     /**
  310.      * Has this response stream been closed?
  311.      */
  312.     public boolean closed() {
  313.  
  314.         return (this.closed);
  315.  
  316.     }
  317.  
  318. }
  319.