001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018
019 package compressionFilters;
020
021 import java.io.IOException;
022 import java.util.Enumeration;
023 import javax.servlet.Filter;
024 import javax.servlet.FilterChain;
025 import javax.servlet.FilterConfig;
026 import javax.servlet.ServletException;
027 import javax.servlet.ServletRequest;
028 import javax.servlet.ServletResponse;
029 import javax.servlet.http.HttpServletRequest;
030 import javax.servlet.http.HttpServletResponse;
031
032
033 /**
034 * Implementation of <code>javax.servlet.Filter</code> used to compress
035 * the ServletResponse if it is bigger than a threshold.
036 *
037 * @author Amy Roh
038 * @author Dmitri Valdin
039 * @version $Revision: 514091 $, $Date: 2007-03-03 01:26:39 -0500 (Sat, 03 Mar 2007) $
040 */
041
042 public class CompressionFilter implements Filter{
043
044 /**
045 * The filter configuration object we are associated with. If this value
046 * is null, this filter instance is not currently configured.
047 */
048 private FilterConfig config = null;
049
050 /**
051 * Minimal reasonable threshold
052 */
053 private int minThreshold = 128;
054
055
056 /**
057 * The threshold number to compress
058 */
059 protected int compressionThreshold;
060
061 /**
062 * Debug level for this filter
063 */
064 private int debug = 0;
065
066 /**
067 * Place this filter into service.
068 *
069 * @param filterConfig The filter configuration object
070 */
071
072 public void init(FilterConfig filterConfig) {
073
074 config = filterConfig;
075 if (filterConfig != null) {
076 String value = filterConfig.getInitParameter("debug");
077 if (value!=null) {
078 debug = Integer.parseInt(value);
079 } else {
080 debug = 0;
081 }
082 String str = filterConfig.getInitParameter("compressionThreshold");
083 if (str!=null) {
084 compressionThreshold = Integer.parseInt(str);
085 if (compressionThreshold != 0 && compressionThreshold < minThreshold) {
086 if (debug > 0) {
087 System.out.println("compressionThreshold should be either 0 - no compression or >= " + minThreshold);
088 System.out.println("compressionThreshold set to " + minThreshold);
089 }
090 compressionThreshold = minThreshold;
091 }
092 } else {
093 compressionThreshold = 0;
094 }
095
096 } else {
097 compressionThreshold = 0;
098 }
099
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