KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > roller > presentation > filters > IfModifiedFilter


1 /*
2  * Created on Apr 19, 2003
3  */

4 package org.roller.presentation.filters;
5
6 import org.apache.commons.lang.StringUtils;
7 import org.apache.commons.logging.Log;
8 import org.apache.commons.logging.LogFactory;
9 import org.roller.RollerException;
10 import org.roller.model.Roller;
11 import org.roller.model.WeblogManager;
12 import org.roller.pojos.UserData;
13 import org.roller.presentation.RollerContext;
14 import org.roller.presentation.RollerRequest;
15 import org.roller.util.LRUCache2;
16
17 import java.io.IOException JavaDoc;
18 import java.text.SimpleDateFormat JavaDoc;
19 import java.util.Date JavaDoc;
20
21 import javax.servlet.Filter JavaDoc;
22 import javax.servlet.FilterChain JavaDoc;
23 import javax.servlet.FilterConfig JavaDoc;
24 import javax.servlet.ServletException JavaDoc;
25 import javax.servlet.ServletRequest JavaDoc;
26 import javax.servlet.ServletResponse JavaDoc;
27 import javax.servlet.http.HttpServletRequest JavaDoc;
28 import javax.servlet.http.HttpServletResponse JavaDoc;
29 import org.roller.config.RollerConfig;
30
31 /**
32  * Entry point filter for Newsfeed Servlets, this filter
33  * Handles If-Modified-Since header using per-user and per-category
34  * last weblog pub time. Returns 304 if requested weblog has not been
35  * modified since. Also, sets Last-Modified on outgoing response.
36  *
37  * @web.filter name="IfModifiedFilter"
38  *
39  * @web.filter-init-param name="cacheSize" value="300"
40  * description="Number of entries in the last modified date cache"
41  *
42  * @web.filter-init-param name="cacheTimeout" value="1800"
43  * description="Timeout (in seconds) of last modified date cache"
44  *
45  * @author David M Johnson
46  */

47 public class IfModifiedFilter implements Filter JavaDoc
48 {
49     private static Log mLogger =
50         LogFactory.getFactory().getInstance(IfModifiedFilter.class);
51
52     // TODO: make cache configurable
53
private static int mCacheSize = 300;
54     private static int mCacheTime = 1800;
55     private static LRUCache2 mDateCache = null;
56     SimpleDateFormat JavaDoc dateFormatter =
57         new SimpleDateFormat JavaDoc("EEE MMM d HH:mm:ss z yyyy");
58
59     public IfModifiedFilter()
60     {
61         super();
62     }
63
64     /**
65      * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
66      */

67     public void init(FilterConfig JavaDoc filterConfig) throws ServletException JavaDoc
68     {
69         mLogger.debug("Initializing IfModified Filter");
70         
71         String JavaDoc cacheSizeString = RollerConfig.getProperty("cache.filter.ifmodified.size");
72         String JavaDoc cacheTimeString = RollerConfig.getProperty("cache.filter.ifmodified.timeout");
73         
74         try
75         {
76             if (cacheSizeString != null) mCacheSize = Integer.parseInt(cacheSizeString);
77         }
78         catch (Throwable JavaDoc e)
79         {
80             mLogger.warn("ERROR parsing cache size");
81         }
82         try
83         {
84             if (cacheTimeString != null) mCacheTime = Integer.parseInt(cacheTimeString);
85         }
86         catch (Throwable JavaDoc e)
87         {
88             mLogger.warn("ERROR parsing cache time");
89         }
90         
91         mLogger.info("cache size is: "+mCacheSize);
92         mLogger.info("cache timeout is: "+mCacheTime);
93         
94         mDateCache = new LRUCache2(mCacheSize, mCacheTime*60*1000);
95     }
96     
97     /**
98      * Some containers don't call init() until doFilter() is used,
99      * so always check to see if mDateCache is instantiated yet.
100      */

101     private static LRUCache2 getCache()
102     {
103         if (mDateCache == null)
104         {
105             mDateCache = new LRUCache2(mCacheSize, mCacheTime*60*1000);
106         }
107         return mDateCache;
108     }
109
110     /**
111      * @see javax.servlet.Filter#doFilter(
112      * javax.servlet.ServletRequest,
113      * javax.servlet.ServletResponse,
114      * javax.servlet.FilterChain)
115      */

116     public void doFilter(
117         ServletRequest JavaDoc req,
118         ServletResponse JavaDoc res,
119         FilterChain JavaDoc chain)
120         throws IOException JavaDoc, ServletException JavaDoc
121     {
122         HttpServletRequest JavaDoc request = (HttpServletRequest JavaDoc) req;
123         HttpServletResponse JavaDoc response = (HttpServletResponse JavaDoc) res;
124
125         Date JavaDoc updateTime = null;
126         try
127         {
128             updateTime = getLastPublishedDate(request);
129
130             // RSS context loader needs updateTime, so stash it
131
request.setAttribute("updateTime", updateTime);
132
133             // Check the incoming if-modified-since header
134
Date JavaDoc sinceDate =
135                 new Date JavaDoc(request.getDateHeader("If-Modified-Since"));
136
137             if (updateTime != null)
138             {
139                  // convert date (JDK 1.5 workaround)
140
String JavaDoc date = dateFormatter.format(updateTime);
141                  updateTime = new Date JavaDoc(date);
142                  if (updateTime.compareTo(sinceDate) <= 0)
143                  {
144                      response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
145                      return;
146                  }
147             }
148             mLogger.debug("Not returning 304 for: "+request.getRequestURI());
149         }
150         catch (RollerException e)
151         {
152             // Thrown by getLastPublishedDate if there is a db-type error
153
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
154             return;
155         }
156         catch (IllegalArgumentException JavaDoc e)
157         {
158             // Thrown by getDateHeader if not in valid format. This can be
159
// safely ignored, the only consequence is that the NOT MODIFIED
160
// response is not set.
161
}
162
163         // Set outgoing last modified header
164
if (updateTime != null)
165         {
166             response.setDateHeader("Last-Modified", updateTime.getTime());
167         }
168
169         chain.doFilter(request, response);
170     }
171
172     public static Date JavaDoc getLastPublishedDate(HttpServletRequest JavaDoc request)
173         throws RollerException
174     {
175         // Get user name without using heavy RollerRequest URL parser
176
String JavaDoc userName = null;
177         String JavaDoc pathInfo = request.getPathInfo();
178         pathInfo = pathInfo != null ? pathInfo : "";
179         String JavaDoc[] pathInfoArray = StringUtils.split(pathInfo, "/");
180         if (pathInfoArray.length == 1)
181         {
182             userName = pathInfoArray[0];
183         }
184         else if (pathInfoArray.length > 1)
185         {
186             // request is for a specific date or anchor, can't return 304
187
return null;
188         }
189     
190         // Get last pub time for specific weblog category requested
191
String JavaDoc catname =
192             request.getParameter(RollerRequest.WEBLOGCATEGORYNAME_KEY);
193     
194         // update times are cached to reduce database queries per request
195
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
196             sb.append("zzz_");
197         sb.append(userName);
198             sb.append("_zzz_");
199         sb.append(catname);
200         String JavaDoc key = sb.toString();
201     
202         Date JavaDoc updateTime = (Date JavaDoc)getCache().get(key);
203         if (updateTime == null)
204         {
205             mLogger.debug("Hitting database for update time: "+key);
206             Roller roller = RollerContext.getRoller(request);
207             WeblogManager wmgr = roller.getWeblogManager();
208             updateTime = wmgr.getWeblogLastPublishTime(userName, catname);
209             getCache().put(key, updateTime);
210         }
211         return updateTime;
212     }
213     
214     public static void purgeDateCache(UserData user)
215     {
216         String JavaDoc userName = (user != null) ? user.getUserName() : null;
217         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
218         sb.append("zzz_");
219         sb.append(userName);
220         sb.append("_zzz_");
221         getCache().purge(new String JavaDoc[] {sb.toString()});
222     }
223
224     /**
225      * @see javax.servlet.Filter#destroy()
226      */

227     public void destroy()
228     {
229     }
230 }
231
Popular Tags