KickJava   Java API By Example, From Geeks To Geeks.

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


1 // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
2

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

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

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

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

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

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

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

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

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