Clover coverage report -
Coverage timestamp: Mon Jan 17 2005 23:51:40 PST
file stats: LOC: 150   Methods: 3
NCLOC: 81   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.1 $
 29   
  */
 30   
 public class CacheFilter implements Filter {
 31   
     private final Log log = LogFactory.getLog(this.getClass());
 32   
 
 33   
     // filter variables
 34   
     private FilterConfig config;
 35   
     private ServletCacheAdministrator admin = null;
 36   
     private int cacheScope = PageContext.APPLICATION_SCOPE; // filter scope - default is APPLICATION
 37   
     private int time = 60 * 60; // time before cache should be refreshed - default one hour (in seconds)
 38   
 
 39   
     /**
 40   
      * Filter clean-up
 41   
      */
 42  0
     public void destroy() {
 43   
         //Not much to do...
 44   
     }
 45   
 
 46   
     /**
 47   
      * The doFilter call caches the response by wrapping the <code>HttpServletResponse</code>
 48   
      * object so that the output stream can be caught. This works by splitting off the output
 49   
      * stream into two with the {@link SplitServletOutputStream} class. One stream gets written
 50   
      * out to the response as normal, the other is fed into a byte array inside a {@link ResponseContent}
 51   
      * object.
 52   
      *
 53   
      * @param request The servlet request
 54   
      * @param response The servlet response
 55   
      * @param chain The filter chain
 56   
      * @throws ServletException IOException
 57   
      */
 58  0
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
 59  0
         if (log.isInfoEnabled()) {
 60  0
             log.info("<cache>: filter in scope " + cacheScope);
 61   
         }
 62   
 
 63  0
         HttpServletRequest httpRequest = (HttpServletRequest) request;
 64  0
         String key = admin.generateEntryKey(null, httpRequest, cacheScope);
 65  0
         Cache cache = admin.getCache(httpRequest, cacheScope);
 66   
 
 67  0
         try {
 68  0
             ResponseContent respContent = (ResponseContent) cache.getFromCache(key, time);
 69   
 
 70  0
             if (log.isInfoEnabled()) {
 71  0
                 log.info("<cache>: Using cached entry for " + key);
 72   
             }
 73   
 
 74  0
             long clientLastModified = httpRequest.getDateHeader("If-Modified-Since"); // will return -1 if no header...
 75   
 
 76  0
             if (clientLastModified >= respContent.getLastModified()) {
 77  0
                 ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_NOT_MODIFIED);
 78  0
                 return;
 79   
             }
 80   
 
 81  0
             respContent.writeTo(response);
 82   
         } catch (NeedsRefreshException nre) {
 83  0
             boolean updateSucceeded = false;
 84   
 
 85  0
             try {
 86  0
                 if (log.isInfoEnabled()) {
 87  0
                     log.info("<cache>: New cache entry, cache stale or cache scope flushed for " + key);
 88   
                 }
 89   
 
 90  0
                 CacheHttpServletResponseWrapper cacheResponse = new CacheHttpServletResponseWrapper((HttpServletResponse) response);
 91  0
                 chain.doFilter(request, cacheResponse);
 92  0
                 cacheResponse.flushBuffer();
 93   
 
 94   
                 // Only cache if the response was 200
 95  0
                 if (cacheResponse.getStatus() == HttpServletResponse.SC_OK) {
 96   
                     //Store as the cache content the result of the response
 97  0
                     cache.putInCache(key, cacheResponse.getContent());
 98  0
                     updateSucceeded = true;
 99   
                 }
 100   
             } finally {
 101  0
                 if (!updateSucceeded) {
 102  0
                     cache.cancelUpdate(key);
 103   
                 }
 104   
             }
 105   
         }
 106   
     }
 107   
 
 108   
     /**
 109   
      * Initialize the filter. This retrieves a {@link ServletCacheAdministrator}
 110   
      * instance and configures the filter based on any initialization parameters.<p>
 111   
      * The supported initialization parameters are:
 112   
      * <ul>
 113   
      * <li><b>time</b> - the default time (in seconds) to cache content for. The default
 114   
      * value is 3600 seconds (one hour).</li>
 115   
      * <li><b>scope</b> - the default scope to cache content in. Acceptable values
 116   
      * are <code>application</code> (default), <code>session</code>, <code>request</code> and
 117   
      * <code>page</code>.
 118   
      *
 119   
      * @param filterConfig The filter configuration
 120   
      */
 121  0
     public void init(FilterConfig filterConfig) {
 122   
         //Get whatever settings we want...
 123  0
         config = filterConfig;
 124  0
         admin = ServletCacheAdministrator.getInstance(config.getServletContext());
 125   
 
 126   
         //Will work this out later
 127  0
         try {
 128  0
             time = Integer.parseInt(config.getInitParameter("time"));
 129   
         } catch (Exception e) {
 130  0
             log.info("Could not get init paramter 'time', defaulting to one hour.");
 131   
         }
 132   
 
 133  0
         try {
 134  0
             String scopeString = config.getInitParameter("scope");
 135   
 
 136  0
             if (scopeString.equals("session")) {
 137  0
                 cacheScope = PageContext.SESSION_SCOPE;
 138  0
             } else if (scopeString.equals("application")) {
 139  0
                 cacheScope = PageContext.APPLICATION_SCOPE;
 140  0
             } else if (scopeString.equals("request")) {
 141  0
                 cacheScope = PageContext.REQUEST_SCOPE;
 142  0
             } else if (scopeString.equals("page")) {
 143  0
                 cacheScope = PageContext.PAGE_SCOPE;
 144   
             }
 145   
         } catch (Exception e) {
 146  0
             log.info("Could not get init paramter 'scope', defaulting to 'application'");
 147   
         }
 148   
     }
 149   
 }
 150