001 package org.rakeshv.filters;
002
003 import java.io.IOException;
004 import java.util.Enumeration;
005 import javax.servlet.Filter;
006 import javax.servlet.FilterChain;
007 import javax.servlet.FilterConfig;
008 import javax.servlet.ServletException;
009 import javax.servlet.ServletRequest;
010 import javax.servlet.ServletResponse;
011 import javax.servlet.http.HttpServletRequest;
012 import javax.servlet.http.HttpServletResponse;
013
014 /**
015 * A <code>Filter</code> class that is used to compress the response
016 * to a client request. The filter is activated only if the client
017 * specified the <code>Accept-Encoding</code>, or the
018 * <code>TE</code> HTTP headers.
019 *
020 * <p>The following shows ways in which you can enable the filters
021 * in your web application configuration file (WEB-INF/web.xml):</p>
022 *
023 * <pre>
024 * <filter>
025 * <filter-name>compressionFilter</filter-name>
026 * <filter-class>org.rakeshv.filters.CompressionFilter</filter-class>
027 * <description>A servlet filter that supports Gzip, Deflate and ZIP compressed responses.</description>
028 * </filter>
029 *
030 * <filter-mapping>
031 * <filter-name>compressionFilter</filter-name>
032 * <servlet-name>myServlet</servlet-name>
033 * </filter-mapping>
034 *
035 * <filter-mapping>
036 * <filter-name>compressionFilter</filter-name>
037 * <url-pattern>/docs/*</url-pattern>
038 * </filter-mapping>
039 * </pre>
040 *
041 * <p>© Copyright 2003, Rakesh Vidyadharan</p>
042 * @author Rakesh Vidyadharan 2<sup><small>nd</small></sup> September 2003
043 *
044 * @version $Id: CompressionFilter.java,v 1.7 2005/07/19 17:36:37 rakesh Exp $
045 */
046 public class CompressionFilter extends FilterAdapter
047 {
048 /**
049 * A constant that is used to denote that <code>deflate</code>
050 * compression is to be used.
051 */
052 public static final int DEFLATE_COMPRESSION = 1;
053
054 /**
055 * A constant that is used to denote that <code>zip</code>
056 * compression is to be used.
057 */
058 public static final int ZIP_COMPRESSION = 2;
059
060 /**
061 * A constant that is used to denote that <code>gzip</code>
062 * compression is to be used.
063 */
064 public static final int GZIP_COMPRESSION = 3;
065
066 /**
067 * A reference to the Servlet container's Filter configuration.
068 */
069 private FilterConfig filterConfig = null;
070
071 /**
072 * Check the <code>Accept-Encoding</code> and
073 * <code>accept-encoding</code> HTTP headers, and if either of them
074 * specified the accepted compression methods (those supported by
075 * the java.util.zip classes), then the response is compressed using
076 * the desired compression algorithm. If multiple algorithms were
077 * specified, then one of the specified algorithms will be used.
078 * The exact algorithm that will be used is in the order specified:
079 * </p>
080 * <ol>
081 * <li>GZIP
082 * <li>ZIP
083 * <li>Deflate
084 * </ol>
085 *
086 * <p>If the special <code>*</code> value is used to specify the
087 * compression to use, <code>Deflate</code> compression will be used.
088 * </p>
089 *
090 * <p><b>Note:</b> This method does an implicit call to {@link
091 * CompressionResponseWrapper#finish()} if the response if being
092 * compressed. Other servlets down the chain do not need to
093 * worry about finishing the compression stream.</p>
094 *
095 * @throws IOException - If exceptions are encountered while
096 * applying the filter.
097 * @throws ServletException - If exceptions are encountered while
098 * interacting with the request or response objects.
099 */
100 public void doFilter( ServletRequest request,
101 ServletResponse response, FilterChain chain )
102 throws IOException, ServletException
103 {
104 int compressionType = -1;
105
106 Enumeration e = ( (HttpServletRequest) request ).getHeaderNames();
107 while ( e.hasMoreElements() )
108 {
109 String header = (String) e.nextElement();
110 if ( header.equalsIgnoreCase( "Accept-Encoding" ) ||
111 header.equalsIgnoreCase( "TE" ) )
112 {
113 String encoding =
114 ( (HttpServletRequest ) request ).getHeader( header );
115 if ( encoding.indexOf( "gzip" ) != -1 )
116 {
117 compressionType = CompressionFilter.GZIP_COMPRESSION;
118 }
119 else if ( encoding.indexOf( "zip" ) != -1 )
120 {
121 compressionType = CompressionFilter.ZIP_COMPRESSION;
122 }
123 else if ( encoding.indexOf( "deflate" ) != -1 || encoding.equals( "*" ) )
124 {
125 compressionType = CompressionFilter.DEFLATE_COMPRESSION;
126 }
127 }
128 }
129
130 if ( compressionType == -1 )
131 {
132 chain.doFilter( request, response );
133 }
134 else
135 {
136 CompressionResponseWrapper wrappedResponse =
137 new CompressionResponseWrapper( (HttpServletResponse) response );
138 wrappedResponse.setCompressionType( compressionType );
139 chain.doFilter( request, wrappedResponse );
140
141 try
142 {
143 wrappedResponse.finish();
144 }
145 catch ( IOException ioex )
146 {
147 // Do nothing
148 }
149 }
150 }
151 }