View Javadoc

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  */
17  
18  package compressionFilters;
19  
20  import java.io.IOException;
21  import java.util.Enumeration;
22  
23  import javax.servlet.Filter;
24  import javax.servlet.FilterChain;
25  import javax.servlet.FilterConfig;
26  import javax.servlet.ServletException;
27  import javax.servlet.ServletRequest;
28  import javax.servlet.ServletResponse;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  
33  /**
34   * Implementation of <code>javax.servlet.Filter</code> used to compress
35   * the ServletResponse if it is bigger than a threshold.
36   *
37   * @author Amy Roh
38   * @author Dmitri Valdin
39   * @version $Revision: 664175 $, $Date: 2008-06-06 18:43:44 -0400 (Fri, 06 Jun 2008) $
40   */
41  
42  public class CompressionFilter implements Filter {
43  
44      /**
45       * The filter configuration object we are associated with.  If this value
46       * is null, this filter instance is not currently configured.
47       */
48      private FilterConfig config = null;
49  
50      /**
51       * Minimal reasonable threshold
52       */
53      private int minThreshold = 128;
54  
55  
56      /**
57       * The threshold number to compress
58       */
59      protected int compressionThreshold;
60  
61      /**
62       * Debug level for this filter
63       */
64      private int debug = 0;
65  
66      /**
67       * Place this filter into service.
68       *
69       * @param filterConfig The filter configuration object
70       */
71  
72      public void init(FilterConfig filterConfig) {
73  
74          config = filterConfig;
75          if (filterConfig != null) {
76              String value = filterConfig.getInitParameter("debug");
77              if (value != null) {
78                  debug = Integer.parseInt(value);
79              } else {
80                  debug = 0;
81              }
82              String str = filterConfig.getInitParameter("compressionThreshold");
83              if (str != null) {
84                  compressionThreshold = Integer.parseInt(str);
85                  if (compressionThreshold != 0 && compressionThreshold < minThreshold) {
86                      if (debug > 0) {
87                          System.out.println("compressionThreshold should be either 0 - no compression or >= " + minThreshold);
88                          System.out.println("compressionThreshold set to " + minThreshold);
89                      }
90                      compressionThreshold = minThreshold;
91                  }
92              } else {
93                  compressionThreshold = 0;
94              }
95  
96          } else {
97              compressionThreshold = 0;
98          }
99  
100     }
101 
102     /**
103      * Take this filter out of service.
104      */
105     public void destroy() {
106 
107         this.config = null;
108 
109     }
110 
111     /**
112      * The <code>doFilter</code> method of the Filter is called by the container
113      * each time a request/response pair is passed through the chain due
114      * to a client request for a resource at the end of the chain.
115      * The FilterChain passed into this method allows the Filter to pass on the
116      * request and response to the next entity in the chain.<p>
117      * This method first examines the request to check whether the client support
118      * compression. <br>
119      * It simply just pass the request and response if there is no support for
120      * compression.<br>
121      * If the compression support is available, it creates a
122      * CompressionServletResponseWrapper object which compresses the content and
123      * modifies the header if the content length is big enough.
124      * It then invokes the next entity in the chain using the FilterChain object
125      * (<code>chain.doFilter()</code>), <br>
126      */
127 
128     public void doFilter(ServletRequest request, ServletResponse response,
129                          FilterChain chain) throws IOException, ServletException {
130 
131         if (debug > 0) {
132             System.out.println("@doFilter");
133         }
134 
135         if (compressionThreshold == 0) {
136             if (debug > 0) {
137                 System.out.println("doFilter gets called, but compressionTreshold is set to 0 - no compression");
138             }
139             chain.doFilter(request, response);
140             return;
141         }
142 
143         boolean supportCompression = false;
144         if (request instanceof HttpServletRequest) {
145             if (debug > 1) {
146                 System.out.println("requestURI = " + ((HttpServletRequest) request).getRequestURI());
147             }
148 
149             // Are we allowed to compress ?
150             String s = (String) ((HttpServletRequest) request).getParameter("gzip");
151             if ("false".equals(s)) {
152                 if (debug > 0) {
153                     System.out.println("got parameter gzip=false --> don't compress, just chain filter");
154                 }
155                 chain.doFilter(request, response);
156                 return;
157             }
158 
159             Enumeration e =
160                     ((HttpServletRequest) request).getHeaders("Accept-Encoding");
161             while (e.hasMoreElements()) {
162                 String name = (String) e.nextElement();
163                 if (name.indexOf("gzip") != -1) {
164                     if (debug > 0) {
165                         System.out.println("supports compression");
166                     }
167                     supportCompression = true;
168                 } else {
169                     if (debug > 0) {
170                         System.out.println("no support for compresion");
171                     }
172                 }
173             }
174         }
175 
176         if (!supportCompression) {
177             if (debug > 0) {
178                 System.out.println("doFilter gets called wo compression");
179             }
180             chain.doFilter(request, response);
181             return;
182         } else {
183             if (response instanceof HttpServletResponse) {
184                 CompressionServletResponseWrapper wrappedResponse =
185                         new CompressionServletResponseWrapper((HttpServletResponse) response);
186                 wrappedResponse.setDebugLevel(debug);
187                 wrappedResponse.setCompressionThreshold(compressionThreshold);
188                 if (debug > 0) {
189                     System.out.println("doFilter gets called with compression");
190                 }
191                 try {
192                     chain.doFilter(request, wrappedResponse);
193                 } finally {
194                     wrappedResponse.finishResponse();
195                 }
196                 return;
197             }
198         }
199     }
200 
201     /**
202      * Set filter config
203      * This function is equivalent to init. Required by Weblogic 6.1
204      *
205      * @param filterConfig The filter configuration object
206      */
207     public void setFilterConfig(FilterConfig filterConfig) {
208         init(filterConfig);
209     }
210 
211     /**
212      * Return filter config
213      * Required by Weblogic 6.1
214      */
215     public FilterConfig getFilterConfig() {
216         return config;
217     }
218 
219 }
220