File Source: CompressionFilter.java

         /* 
    P/P   *  Method: org.apache.roller.weblogger.ui.core.filters.CompressionFilter$ByteArrayResponseWrapper__static_init
          */
     1  /*
     2  * Licensed to the Apache Software Foundation (ASF) under one or more
     3  *  contributor license agreements.  The ASF licenses this file to You
     4  * under the Apache License, Version 2.0 (the "License"); you may not
     5  * 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.  For additional information regarding
    15  * copyright in this work, please see the NOTICE file in the top level
    16  * directory of this distribution.
    17  */
    18  
    19  package org.apache.roller.weblogger.ui.core.filters;
    20  
    21  import java.io.ByteArrayOutputStream;
    22  import java.io.IOException;
    23  import java.io.OutputStream;
    24  import java.io.OutputStreamWriter;
    25  import java.io.PrintWriter;
    26  import java.util.zip.GZIPOutputStream;
    27  import javax.servlet.Filter;
    28  import javax.servlet.FilterChain;
    29  import javax.servlet.FilterConfig;
    30  import javax.servlet.ServletException;
    31  import javax.servlet.ServletOutputStream;
    32  import javax.servlet.ServletRequest;
    33  import javax.servlet.ServletResponse;
    34  import javax.servlet.http.HttpServletRequest;
    35  import javax.servlet.http.HttpServletResponse;
    36  import javax.servlet.http.HttpServletResponseWrapper;
    37  import org.apache.commons.logging.Log;
    38  import org.apache.commons.logging.LogFactory;
    39  import org.apache.roller.weblogger.config.WebloggerConfig;
    40  
    41  
    42  /** 
    43   * Filter that compresses output with gzip (assuming that browser supports gzip).
    44   * <P>
    45   * Taken from More Servlets and JavaServer Pages from Prentice Hall and 
    46   * Sun Microsystems Press, http://www.moreservlets.com/.
    47   * &copy; 2002 Marty Hall; may be freely used or adapted.
    48   */
         /* 
    P/P   *  Method: void org.apache.roller.weblogger.ui.core.filters.CompressionFilter()
          * 
          *  Postconditions:
          *    this.enabled == 1
          */
    49  public class CompressionFilter implements Filter {
    50      
             /* 
    P/P       *  Method: org.apache.roller.weblogger.ui.core.filters.CompressionFilter__static_init
              * 
              *  Postconditions:
              *    init'ed(log)
              */
    51      private static Log log = LogFactory.getLog(CompressionFilter.class);
    52      
    53      private boolean enabled = true;
    54      
    55      
    56      /** 
    57       * If browser does not support gzip, invoke resource normally. If browser 
    58       * does support gzip, set the Content-Encoding response header and invoke 
    59       * resource with a wrapped response that collects all the output. Extract 
    60       * the output and write it into a gzipped byte array. Finally, write that 
    61       * array to the client's output stream.
    62       */
    63      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    64              throws ServletException, IOException {
    65          
                 /* 
    P/P           *  Method: void doFilter(ServletRequest, ServletResponse, FilterChain)
                  * 
                  *  Preconditions:
                  *    chain != null
                  *    init'ed(this.enabled)
                  *    (soft) log != null
                  *    (soft) request != null
                  *    (soft) response != null
                  * 
                  *  Presumptions:
                  *    javax.servlet.ServletResponse:getOutputStream(...)@150 != null
                  * 
                  *  Test Vectors:
                  *    this.enabled: {0}, {1}
                  */
    66          HttpServletRequest req = (HttpServletRequest) request;
    67          HttpServletResponse res = (HttpServletResponse) response;
    68          
    69          if (!this.enabled || !isGzipSupported(req)) {
    70              // Invoke resource normally.
    71              chain.doFilter(req, res);
    72          } else {
    73              // Tell browser we are sending it gzipped data.
    74              res.setHeader("Content-Encoding", "gzip");
    75              
    76              // Invoke resource, accumulating output in the wrapper.
    77              ByteArrayResponseWrapper responseWrapper =
    78                      new ByteArrayResponseWrapper(response);
    79              
    80              chain.doFilter(req, responseWrapper);
    81              
    82              ByteArrayOutputStream outputStream = responseWrapper.getByteArrayOutputStream();
    83              
    84              // Get character array representing output.
    85              log.debug("Pre-zip size:" + outputStream.size());
    86              
    87              // Make a writer that compresses data and puts
    88              // it into a byte array.
    89              ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    90              GZIPOutputStream zipOut = new GZIPOutputStream(byteStream);
    91              
    92              // Compress original output and put it into byte array.
    93              zipOut.write(responseWrapper.getByteArrayOutputStream().toByteArray());
    94              
    95              // Gzip streams must be explicitly closed.
    96              zipOut.close();
    97              
    98              log.debug("Gzip size:" + byteStream.size());
    99              
   100              // Update the Content-Length header.
   101              res.setContentLength(byteStream.size());
   102              
   103              ByteArrayOutputStreamWrapper newOut =
   104                      (ByteArrayOutputStreamWrapper) responseWrapper.getOutputStream();
   105              newOut.clear();
   106              newOut.setFinallized();
   107              
   108              /* now force close of OutputStream */
   109              newOut.write(byteStream.toByteArray());
   110              newOut.close();
   111          }
   112          
   113      }
   114      
   115  
   116      public void init(FilterConfig config) throws ServletException {
   117          
   118          // is compression enabled?
                 /* 
    P/P           *  Method: void init(FilterConfig)
                  * 
                  *  Preconditions:
                  *    log != null
                  * 
                  *  Postconditions:
                  *    init'ed(this.enabled)
                  * 
                  *  Test Vectors:
                  *    org.apache.roller.weblogger.config.WebloggerConfig:getBooleanProperty(...)@119: {0}, {1}
                  */
   119          if(WebloggerConfig.getBooleanProperty("compression.gzipResponse.enabled")) {
   120              this.enabled = true;
   121              log.info("Compressed Output ENABLED");
   122          } else {
   123              this.enabled = false;
   124              log.info("Compressed Output DISABLED");
   125          }
   126      }
   127      
   128      
             /* 
    P/P       *  Method: void destroy()
              */
   129      public void destroy() {}
   130      
   131      
   132      private boolean isGzipSupported(HttpServletRequest req) {
                 /* 
    P/P           *  Method: bool isGzipSupported(HttpServletRequest)
                  * 
                  *  Preconditions:
                  *    req != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
   133          String browserEncodings = req.getHeader("Accept-Encoding");
   134          return ((browserEncodings != null)
   135                      && (browserEncodings.indexOf("gzip") != -1));
   136      }
   137      
   138      
   139      /**
   140       * Implementation of HttpServletResponseWrapper that supports caching.
   141       */
   142      private class ByteArrayResponseWrapper extends HttpServletResponseWrapper {
   143          
   144          private PrintWriter tpWriter;
   145          private ByteArrayOutputStreamWrapper tpStream;
   146          
   147          
                 /* 
    P/P           *  Method: void org.apache.roller.weblogger.ui.core.filters.CompressionFilter$ByteArrayResponseWrapper(CompressionFilter, ServletResponse)
                  * 
                  *  Preconditions:
                  *    inResp != null
                  * 
                  *  Postconditions:
                  *    this.tpStream == &new CompressionFilter$ByteArrayOutputStreamWrapper(CompressionFilter$ByteArrayResponseWrapper#1)
                  *    this.tpWriter == &new PrintWriter(CompressionFilter$ByteArrayResponseWrapper#2)
                  *    new ByteArrayOutputStream(CompressionFilter$ByteArrayOutputStreamWrapper#1) num objects == 1
                  *    new CompressionFilter$ByteArrayOutputStreamWrapper(CompressionFilter$ByteArrayResponseWrapper#1) num objects == 1
                  *    this.tpStream.flushOnFinalizeOnly == 1
                  *    new PrintWriter(CompressionFilter$ByteArrayResponseWrapper#2) num objects == 1
                  *    this.tpStream.baStream == &new ByteArrayOutputStream(CompressionFilter$ByteArrayOutputStreamWrapper#1)
                  *    init'ed(this.tpStream.finallized)
                  *    init'ed(this.tpStream.intStream)
                  */
   148          public ByteArrayResponseWrapper(ServletResponse inResp) throws IOException {
   149              super((HttpServletResponse) inResp);
   150              tpStream = new ByteArrayOutputStreamWrapper(inResp.getOutputStream());
   151              tpWriter = new PrintWriter(new OutputStreamWriter(tpStream,"UTF-8"));
   152          }
   153          
   154          
   155          public ServletOutputStream getOutputStream() throws IOException {
                     /* 
    P/P               *  Method: ServletOutputStream getOutputStream()
                      * 
                      *  Preconditions:
                      *    init'ed(this.tpStream)
                      * 
                      *  Postconditions:
                      *    return_value == this.tpStream
                      *    init'ed(return_value)
                      */
   156              return tpStream;
   157          }
   158          
   159          public PrintWriter getWriter() throws IOException {
                     /* 
    P/P               *  Method: PrintWriter getWriter()
                      * 
                      *  Preconditions:
                      *    init'ed(this.tpWriter)
                      * 
                      *  Postconditions:
                      *    return_value == this.tpWriter
                      *    init'ed(return_value)
                      */
   160              return tpWriter;
   161          }
   162          
   163          /**
   164           * Get a String representation of the entire buffer.
   165           */
   166          public String toString() {
                     /* 
    P/P               *  Method: String toString()
                      * 
                      *  Preconditions:
                      *    this.tpStream != null
                      *    this.tpStream.baStream != null
                      * 
                      *  Postconditions:
                      *    java.io.ByteArrayOutputStream:toString(...)._tainted == this.tpStream.baStream._tainted
                      *    init'ed(java.io.ByteArrayOutputStream:toString(...)._tainted)
                      *    return_value == &java.io.ByteArrayOutputStream:toString(...)
                      */
   167              return tpStream.getByteArrayStream().toString();
   168          }
   169          
   170          public ByteArrayOutputStream getByteArrayOutputStream() throws IOException {
                     /* 
    P/P               *  Method: ByteArrayOutputStream getByteArrayOutputStream()
                      * 
                      *  Preconditions:
                      *    this.tpStream != null
                      *    init'ed(this.tpStream.baStream)
                      * 
                      *  Postconditions:
                      *    return_value == this.tpStream.baStream
                      *    init'ed(return_value)
                      */
   171              return tpStream.getByteArrayStream();
   172          }
   173          
   174      }
   175      
   176      
   177      /**
   178       * Implementation of ServletOutputStream that allows the filter to hold the
   179       * Response content for insertion into the cache.
   180       */
   181      private class ByteArrayOutputStreamWrapper extends ServletOutputStream {
   182          
   183          protected OutputStream intStream;
   184          protected ByteArrayOutputStream baStream;
   185          protected boolean finallized = false;
   186          protected boolean flushOnFinalizeOnly = true;
   187          
   188          
                 /* 
    P/P           *  Method: void org.apache.roller.weblogger.ui.core.filters.CompressionFilter$ByteArrayOutputStreamWrapper(CompressionFilter, OutputStream)
                  * 
                  *  Postconditions:
                  *    this.baStream == &new ByteArrayOutputStream(CompressionFilter$ByteArrayOutputStreamWrapper#1)
                  *    this.finallized == 0
                  *    this.flushOnFinalizeOnly == 1
                  *    new ByteArrayOutputStream(CompressionFilter$ByteArrayOutputStreamWrapper#1) num objects == 1
                  *    this.intStream == outStream
                  *    init'ed(this.intStream)
                  */
   189          public ByteArrayOutputStreamWrapper(OutputStream outStream) {
   190              intStream = outStream;
   191              baStream = new ByteArrayOutputStream();
   192          }
   193          
                 /* 
    P/P           *  Method: void org.apache.roller.weblogger.ui.core.filters.CompressionFilter$ByteArrayOutputStreamWrapper(CompressionFilter)
                  * 
                  *  Presumptions:
                  *    init'ed(java.lang.System.out)
                  * 
                  *  Postconditions:
                  *    this.baStream == &new ByteArrayOutputStream(CompressionFilter$ByteArrayOutputStreamWrapper#1)
                  *    this.finallized == 0
                  *    this.flushOnFinalizeOnly == 1
                  *    new ByteArrayOutputStream(CompressionFilter$ByteArrayOutputStreamWrapper#1) num objects == 1
                  *    this.intStream == java.lang.System.out
                  *    (soft) init'ed(this.intStream)
                  */
   194          public ByteArrayOutputStreamWrapper() {
   195              intStream = System.out;
   196              baStream = new ByteArrayOutputStream();
   197          }
   198          
   199          
   200          public ByteArrayOutputStream getByteArrayStream() {
                     /* 
    P/P               *  Method: ByteArrayOutputStream getByteArrayStream()
                      * 
                      *  Preconditions:
                      *    init'ed(this.baStream)
                      * 
                      *  Postconditions:
                      *    return_value == this.baStream
                      *    init'ed(return_value)
                      */
   201              return baStream;
   202          }
   203          
   204          public void setFinallized() {
                     /* 
    P/P               *  Method: void setFinallized()
                      * 
                      *  Postconditions:
                      *    this.finallized == 1
                      */
   205              finallized = true;
   206          }
   207          
   208          public boolean isFinallized() {
                     /* 
    P/P               *  Method: bool isFinallized()
                      * 
                      *  Preconditions:
                      *    init'ed(this.finallized)
                      * 
                      *  Postconditions:
                      *    return_value == this.finallized
                      *    init'ed(return_value)
                      */
   209              return finallized;
   210          }
   211          
   212          
   213          public void write(int i) throws java.io.IOException {
                     /* 
    P/P               *  Method: void write(int)
                      * 
                      *  Preconditions:
                      *    this.baStream != null
                      */
   214              baStream.write(i);
   215          }
   216          
   217          public void close() throws java.io.IOException {
                     /* 
    P/P               *  Method: void close()
                      * 
                      *  Preconditions:
                      *    init'ed(this.finallized)
                      *    (soft) this.baStream != null
                      *    (soft) this.intStream != null
                      * 
                      *  Test Vectors:
                      *    this.finallized: {0}, {1}
                      */
   218              if (finallized) {
   219                  processStream();
   220                  intStream.close();
   221              }
   222          }
   223          
   224          public void flush() throws java.io.IOException {
                     /* 
    P/P               *  Method: void flush()
                      * 
                      *  Preconditions:
                      *    this.baStream != null
                      *    (soft) init'ed(this.finallized)
                      *    (soft) init'ed(this.flushOnFinalizeOnly)
                      *    (soft) this.intStream != null
                      * 
                      *  Postconditions:
                      *    this.baStream == One-of{old this.baStream, &new ByteArrayOutputStream(flush#1)}
                      *    this.baStream != null
                      *    new ByteArrayOutputStream(flush#1) num objects <= 1
                      * 
                      *  Test Vectors:
                      *    this.finallized: {0}, {1}
                      *    java.io.ByteArrayOutputStream:size(...)@225: {0}, {-231..-1, 1..232-1}
                      */
   225              if (baStream.size() != 0) {
   226                  if (!flushOnFinalizeOnly || finallized) {
   227                      processStream();
   228                      baStream = new ByteArrayOutputStream();
   229                  }
   230              }
   231          }
   232          
   233          protected void processStream() throws java.io.IOException {
                     /* 
    P/P               *  Method: void processStream()
                      * 
                      *  Preconditions:
                      *    this.baStream != null
                      *    this.intStream != null
                      */
   234              intStream.write(baStream.toByteArray());
   235              intStream.flush();
   236          }
   237          
   238          public void clear() {
                     /* 
    P/P               *  Method: void clear()
                      * 
                      *  Postconditions:
                      *    this.baStream == &new ByteArrayOutputStream(clear#1)
                      *    new ByteArrayOutputStream(clear#1) num objects == 1
                      */
   239              baStream = new ByteArrayOutputStream();
   240          }
   241          
   242      }
   243  
   244  }








SofCheck Inspector Build Version : 2.18479
CompressionFilter.java 2009-Jan-02 14:24:56
CompressionFilter.class 2009-Sep-04 03:12:44
CompressionFilter$ByteArrayOutputStreamWrapper.class 2009-Sep-04 03:12:44
CompressionFilter$ByteArrayResponseWrapper.class 2009-Sep-04 03:12:44