KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jodd > servlet > filters > GzipFilter


1 package jodd.servlet.filters;
2
3 import java.io.IOException;
4 import java.util.StringTokenizer;
5
6 import javax.servlet.Filter;
7 import javax.servlet.FilterChain;
8 import javax.servlet.FilterConfig;
9 import javax.servlet.ServletException;
10 import javax.servlet.ServletRequest;
11 import javax.servlet.ServletResponse;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14
15 /**
16  * Compresses output with gzip, for browsers that supports it.<p>
17  *
18  * Configuration of this filter is based on the following initialization
19  * parameters:
20  *
21  * <ul>
22  * <li><strong>threshold</strong> - min number of bytes for compressing
23  * or 0 for no compression at all.</li>
24  *
25  * <li><strong>match</strong> - comma separated string patterns to be found
26  * in uri for using gzip. Only uri's that have these patterns inside will use
27  * gzip.</li>
28  *
29  * <li><strong>excludes</strong> - comma separated string patterns to be excluded
30  * if found in uri for using gzip. It is applied only on matched uris.</li>
31  *
32  * </ul>
33  *
34  * <p>
35  * This filter has been build and extend from Tomcats example.
36  * <p>
37  *
38  * Technical notes: i have found that this is the only way how gzip filter
39  * can be build. The first idea that comes to mind is to wrap response to
40  * some character-based wrapper, and then to gzip it to the output. This
41  * works fine except when forwarding is used: forwarded page is gzipped, but
42  * response header is no more there! I have not an idea how to fix this
43  * except from this approach presented in Tomcat.
44  */

45 public class GzipFilter implements Filter {
46     
47     private FilterConfig config;
48
49     protected FilterConfig getFilterConfig() {
50         return (config);
51     }
52
53     /**
54      * If browser supports gzip, set the Content-Encoding response header and
55      * invoke resource with a wrapped response that collects all the output.
56      * Extract the output and write it into a gzipped byte array. Finally, write
57      * that array to the client's output stream.
58      *
59      * If browser does not support gzip, invoke resource normally.
60      *
61      * @param request
62      * @param response
63      * @param chain
64      *
65      * @exception ServletException
66      * @exception IOException
67      */

68     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
69         HttpServletRequest req = (HttpServletRequest) request;
70         HttpServletResponse res = (HttpServletResponse) response;
71         if ( (threshold == 0) || (isGzipSupported(req) == false) || (isGzipEligible(req) == false) ) {
72             chain.doFilter(request, response);
73             return;
74         }
75         GzipResponseWrapper wrappedResponse = new GzipResponseWrapper(res);
76         wrappedResponse.setCompressionThreshold(threshold);
77         try {
78             chain.doFilter(request, wrappedResponse);
79         } finally {
80             wrappedResponse.finishResponse();
81         }
82         return;
83     }
84
85     /**
86      * Comma separated string patterns to be found in the request URI
87      */

88     protected String uriMatch = null;
89     
90     /**
91      * Comma separated string patterns to be excluded in the request URI if
92      * founded by match.
93      */

94     protected String uriExclude = null;
95
96     /**
97      * Minimal threshold.
98      */

99     private int minThreshold = 128;
100
101     /**
102      * The threshold number to compress, (0 == no compression).
103      */

104     protected int threshold;
105
106     private String[] extensions = null;
107     private String[] excludes = null;
108
109     /**
110      * Filter initialization.
111      *
112      * @param config
113      *
114      * @exception ServletException
115      */

116     public void init(FilterConfig config) throws ServletException {
117         this.config = config;
118         extensions = null;
119
120         // min size
121
try {
122             threshold = Integer.parseInt(config.getInitParameter("threshold"));
123         } catch (NumberFormatException nfe) {
124             threshold = 0;
125         }
126         if (threshold < minThreshold) {
127             threshold = 0;
128         }
129
130         // match string
131
uriMatch = config.getInitParameter("match");
132         if ((uriMatch != null) && (uriMatch.equals("*") == false)) {
133             StringTokenizer st = new StringTokenizer(uriMatch, ",");
134             int i = st.countTokens();
135             if (i >= 1) {
136                 extensions = new String[i];
137                 i = 0;
138                 while (st.hasMoreTokens()) {
139                     extensions[i] = st.nextToken().trim();
140                     i++;
141                 }
142             }
143         }
144         // exclude string
145
uriExclude = config.getInitParameter("exclude");
146         if (uriExclude != null) {
147             StringTokenizer st = new StringTokenizer(uriExclude, ",");
148             int i = st.countTokens();
149             if (i >= 1) {
150                 excludes = new String[i];
151                 i = 0;
152                 while (st.hasMoreTokens()) {
153                     excludes[i] = st.nextToken().trim();
154                     i++;
155                 }
156             }
157         }
158     }
159
160     public void destroy() {
161         config = null;
162         extensions = null;
163         excludes = null;
164     }
165
166     private boolean isGzipSupported(HttpServletRequest req) {
167         String browserEncodings = req.getHeader("Accept-Encoding");
168         if ( (browserEncodings != null) && (browserEncodings.indexOf("gzip") != -1) ) {
169             return true;
170         }
171         return false;
172     }
173
174     /**
175      * Determine if uri is eligible for gzip-ing.
176      *
177      * @param req
178      *
179      * @return true to gzip the uri, otherwise false
180      */

181     private boolean isGzipEligible(HttpServletRequest req) {
182         String uri = req.getRequestURI();
183         if (uri == null) {
184             return false;
185         }
186         boolean result = false;
187         
188         if (extensions == null) { // match=*
189
result = true;
190         } else {
191             for (int i = 0; i < extensions.length; i++) {
192                 if (uri.indexOf(extensions[i]) != -1) {
193                     result = true; // extension founded
194
break;
195                 }
196             }
197         }
198
199         if ((result == true) && (excludes != null)) {
200             for (int i = 0; i < excludes.length; i++) {
201                 if (uri.indexOf(excludes[i]) != -1) {
202                     result = false; // excludes founded
203
break;
204                 }
205             }
206         }
207         return result;
208     }
209 }
210
Popular Tags