View Javadoc

1   package com.atlassian.gzipfilter;
2   
3   import com.atlassian.gzipfilter.integration.GzipFilterIntegration;
4   import com.atlassian.gzipfilter.selector.DefaultGzipCompatibilitySelectorFactory;
5   import com.atlassian.gzipfilter.selector.GzipCompatibilitySelector;
6   import com.atlassian.gzipfilter.selector.GzipCompatibilitySelectorFactory;
7   
8   import org.apache.log4j.Logger;
9   
10  import javax.servlet.*;
11  import javax.servlet.http.HttpServletRequest;
12  import javax.servlet.http.HttpServletResponse;
13  import java.io.IOException;
14  
15  /**
16   * This filter works in conjunction with a custom instance of the URLRewriteFilter to determine whether
17   * to parse a request or not.
18   * <p/>
19   * By default the filter ships with a <code>urlrewrite-gzip-default.xml</code> file which should work for most
20   * situations.
21   * <p/>
22   * The application can supply its own <code>/WEB-INF/urlrewrite-gzip.xml</code> file, or configure which file to use by
23   * setting the filter init parameter <code>urlrewrite.configfile</code>.
24   */
25  public class GzipFilter extends AbstractFilter
26  {
27      private static final Logger log = Logger.getLogger(GzipFilter.class);
28      private static final String ALREADY_FILTERED = GzipFilter.class.getName() + "_already_filtered";
29  
30      private static final GzipCompatibilitySelector NO_GZIP_SELECTOR = new NoGzipCompatibilitySelector();
31  
32      private final DefaultGzipCompatibilitySelectorFactory factory = new DefaultGzipCompatibilitySelectorFactory();
33      private final GzipFilterIntegration integration;
34      private FilterConfig filterConfig;
35  
36      public GzipFilter(GzipFilterIntegration integration)
37      {
38          this.integration = integration;
39      }
40  
41      public void init(FilterConfig filterConfig) throws ServletException
42      {
43          this.filterConfig = filterConfig;
44          super.init(filterConfig);
45      }
46  
47      public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
48      {
49          if (req.getAttribute(ALREADY_FILTERED) == null)
50          {
51              doFilterInternal(req, res, chain);
52          }
53          else
54          {
55              chain.doFilter(req, res);
56          }
57      }
58  
59      private void doFilterInternal(ServletRequest req, ServletResponse res, FilterChain chain)
60              throws IOException, ServletException
61      {
62          req.setAttribute(ALREADY_FILTERED, Boolean.TRUE);
63  
64          if (req instanceof HttpServletRequest && integration.useGzip() && isTopLevelRequest(req))
65          {
66              HttpServletRequest request = (HttpServletRequest) req;
67              HttpServletResponse response = (HttpServletResponse) res;
68              GzipCompatibilitySelector selector = getCompatibilitySelector(request);
69              if (selector.shouldGzip())
70              {
71                  if (log.isDebugEnabled())
72                      log.debug("GZIP supported, compressing.");
73  
74                  SelectingResponseWrapper wrappedResponse = new SelectingResponseWrapper(response, selector, integration.getResponseEncoding(request));
75                  chain.doFilter(req, wrappedResponse);
76                  wrappedResponse.finishResponse();
77                  return;
78              }
79          }
80  
81          chain.doFilter(req, res);
82      }
83  
84      private GzipCompatibilitySelector getCompatibilitySelector(HttpServletRequest request)
85      {
86          String acceptEncodingHeader = request.getHeader("accept-encoding");
87          if (acceptEncodingHeader == null || acceptEncodingHeader.indexOf("gzip") == -1)
88              return NO_GZIP_SELECTOR;
89  
90          return getFactory().getSelector(filterConfig, request);
91      }
92  
93      protected GzipCompatibilitySelectorFactory getFactory()
94      {
95          return factory;
96      }
97  
98      private boolean isTopLevelRequest(ServletRequest request)
99      {
100         return request.getAttribute("javax.servlet.include.servlet_path") == null;
101     }
102 
103     /**
104      * Selector which always says no to gzip
105      */
106     private static final class NoGzipCompatibilitySelector implements GzipCompatibilitySelector
107     {
108         public boolean shouldGzip(String contentType)
109         {
110             return false;
111         }
112 
113         public boolean shouldGzip()
114         {
115             return false;
116         }
117     }
118 }