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