Clover coverage report -
Coverage timestamp: Sat Apr 30 2005 21:58:28 PDT
file stats: LOC: 158   Methods: 3
NCLOC: 88   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CacheFilter.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
  * Copyright (c) 2002-2003 by OpenSymphony
 3   
  * All rights reserved.
 4   
  */
 5   
 package com.opensymphony.oscache.web.filter;
 6   
 
 7   
 import com.opensymphony.oscache.base.Cache;
 8   
 import com.opensymphony.oscache.base.NeedsRefreshException;
 9   
 import com.opensymphony.oscache.web.ServletCacheAdministrator;
 10   
 
 11   
 import org.apache.commons.logging.Log;
 12   
 import org.apache.commons.logging.LogFactory;
 13   
 
 14   
 import java.io.IOException;
 15   
 
 16   
 import javax.servlet.*;
 17   
 import javax.servlet.http.HttpServletRequest;
 18   
 import javax.servlet.http.HttpServletResponse;
 19   
 import javax.servlet.jsp.PageContext;
 20   
 
 21   
 /**
 22   
  * CacheFilter is a filter that allows for server-side caching of post-processed servlet content.<p>
 23   
  *
 24   
  * It also gives great programatic control over refreshing, flushing and updating the cache.<p>
 25   
  *
 26   
  * @author <a href="mailto:sergek@lokitech.com">Serge Knystautas</a>
 27   
  * @author <a href="mailto:mike@atlassian.com">Mike Cannon-Brookes</a>
 28   
  * @version $Revision: 1.4.2.2 $
 29   
  */
 30   
 public class CacheFilter implements Filter {
 31   
     // Header
 32   
     public static final String HEADER_LAST_MODIFIED = "Last-Modified";
 33   
     public static final String HEADER_CONTENT_TYPE = "Content-Type";
 34   
     public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
 35   
     public static final String HEADER_EXPIRES = "Expires";
 36   
     public static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since";
 37   
     public static final String HEADER_CACHE_CONTROL = "Cache-control";
 38   
     public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
 39   
     private final Log log = LogFactory.getLog(this.getClass());
 40   
 
 41   
     // filter variables
 42   
     private FilterConfig config;
 43   
     private ServletCacheAdministrator admin = null;
 44   
     private int cacheScope = PageContext.APPLICATION_SCOPE; // filter scope - default is APPLICATION
 45   
     private int time = 60 * 60; // time before cache should be refreshed - default one hour (in seconds)
 46   
 
 47   
     /**
 48   
      * Filter clean-up
 49   
      */
 50  0
     public void destroy() {
 51   
         //Not much to do...
 52   
     }
 53   
 
 54   
     /**
 55   
      * The doFilter call caches the response by wrapping the <code>HttpServletResponse</code>
 56   
      * object so that the output stream can be caught. This works by splitting off the output
 57   
      * stream into two with the {@link SplitServletOutputStream} class. One stream gets written
 58   
      * out to the response as normal, the other is fed into a byte array inside a {@link ResponseContent}
 59   
      * object.
 60   
      *
 61   
      * @param request The servlet request
 62   
      * @param response The servlet response
 63   
      * @param chain The filter chain
 64   
      * @throws ServletException IOException
 65   
      */
 66  0
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
 67  0
         if (log.isInfoEnabled()) {
 68  0
             log.info("<cache>: filter in scope " + cacheScope);
 69   
         }
 70   
 
 71  0
         HttpServletRequest httpRequest = (HttpServletRequest) request;
 72  0
         String key = admin.generateEntryKey(null, httpRequest, cacheScope);
 73  0
         Cache cache = admin.getCache(httpRequest, cacheScope);
 74   
 
 75  0
         try {
 76  0
             ResponseContent respContent = (ResponseContent) cache.getFromCache(key, time);
 77   
 
 78  0
             if (log.isInfoEnabled()) {
 79  0
                 log.info("<cache>: Using cached entry for " + key);
 80   
             }
 81   
 
 82  0
             long clientLastModified = httpRequest.getDateHeader("If-Modified-Since"); // will return -1 if no header...
 83   
 
 84  0
             if ((clientLastModified != -1) && (clientLastModified >= respContent.getLastModified())) {
 85  0
                 ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
 86  0
                 return;
 87   
             }
 88   
 
 89  0
             respContent.writeTo(response);
 90   
         } catch (NeedsRefreshException nre) {
 91  0
             boolean updateSucceeded = false;
 92   
 
 93  0
             try {
 94  0
                 if (log.isInfoEnabled()) {
 95  0
                     log.info("<cache>: New cache entry, cache stale or cache scope flushed for " + key);
 96   
                 }
 97   
 
 98  0
                 CacheHttpServletResponseWrapper cacheResponse = new CacheHttpServletResponseWrapper((HttpServletResponse) response);
 99  0
                 chain.doFilter(request, cacheResponse);
 100  0
                 cacheResponse.flushBuffer();
 101   
 
 102   
                 // Only cache if the response was 200
 103  0
                 if (cacheResponse.getStatus() == HttpServletResponse.SC_OK) {
 104   
                     //Store as the cache content the result of the response
 105  0
                     cache.putInCache(key, cacheResponse.getContent());
 106  0
                     updateSucceeded = true;
 107   
                 }
 108   
             } finally {
 109  0
                 if (!updateSucceeded) {
 110  0
                     cache.cancelUpdate(key);
 111   
                 }
 112   
             }
 113   
         }
 114   
     }
 115   
 
 116   
     /**
 117   
      * Initialize the filter. This retrieves a {@link ServletCacheAdministrator}
 118   
      * instance and configures the filter based on any initialization parameters.<p>
 119   
      * The supported initialization parameters are:
 120   
      * <ul>
 121   
      * <li><b>time</b> - the default time (in seconds) to cache content for. The default
 122   
      * value is 3600 seconds (one hour).</li>
 123   
      * <li><b>scope</b> - the default scope to cache content in. Acceptable values
 124   
      * are <code>application</code> (default), <code>session</code>, <code>request</code> and
 125   
      * <code>page</code>.
 126   
      *
 127   
      * @param filterConfig The filter configuration
 128   
      */
 129  0
     public void init(FilterConfig filterConfig) {
 130   
         //Get whatever settings we want...
 131  0
         config = filterConfig;
 132  0
         admin = ServletCacheAdministrator.getInstance(config.getServletContext());
 133   
 
 134   
         //Will work this out later
 135  0
         try {
 136  0
             time = Integer.parseInt(config.getInitParameter("time"));
 137   
         } catch (Exception e) {
 138  0
             log.info("Could not get init paramter 'time', defaulting to one hour.");
 139   
         }
 140   
 
 141  0
         try {
 142  0
             String scopeString = config.getInitParameter("scope");
 143   
 
 144  0
             if (scopeString.equals("session")) {
 145  0
                 cacheScope = PageContext.SESSION_SCOPE;
 146  0
             } else if (scopeString.equals("application")) {
 147  0
                 cacheScope = PageContext.APPLICATION_SCOPE;
 148  0
             } else if (scopeString.equals("request")) {
 149  0
                 cacheScope = PageContext.REQUEST_SCOPE;
 150  0
             } else if (scopeString.equals("page")) {
 151  0
                 cacheScope = PageContext.PAGE_SCOPE;
 152   
             }
 153   
         } catch (Exception e) {
 154  0
             log.info("Could not get init paramter 'scope', defaulting to 'application'");
 155   
         }
 156   
     }
 157   
 }
 158