roller-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agillil...@apache.org
Subject svn commit: r370070 - /incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedWeblogPageCacheFilter.java
Date Wed, 18 Jan 2006 06:50:35 GMT
Author: agilliland
Date: Tue Jan 17 22:50:27 2006
New Revision: 370070

URL: http://svn.apache.org/viewcvs?rev=370070&view=rev
Log:
last-modified-since checking for weblog pages.


Added:
    incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedWeblogPageCacheFilter.java

Added: incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedWeblogPageCacheFilter.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedWeblogPageCacheFilter.java?rev=370070&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedWeblogPageCacheFilter.java
(added)
+++ incubator/roller/trunk/src/org/roller/presentation/filters/IfModifiedWeblogPageCacheFilter.java
Tue Jan 17 22:50:27 2006
@@ -0,0 +1,372 @@
+/*
+ * IfModifiedWeblogPageCacheFilter.java
+ *
+ * Created on November 9, 2005, 9:02 PM
+ */
+
+package org.roller.presentation.filters;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.roller.config.RollerConfig;
+import org.roller.pojos.BookmarkData;
+import org.roller.pojos.CommentData;
+import org.roller.pojos.FolderData;
+import org.roller.pojos.RefererData;
+import org.roller.pojos.UserData;
+import org.roller.pojos.WeblogCategoryData;
+import org.roller.pojos.WeblogEntryData;
+import org.roller.pojos.WeblogTemplate;
+import org.roller.pojos.WebsiteData;
+import org.roller.presentation.WeblogPageRequest;
+import org.roller.presentation.cache.Cache;
+import org.roller.presentation.cache.CacheHandler;
+import org.roller.presentation.cache.CacheManager;
+import org.roller.presentation.cache.LazyExpiringCacheEntry;
+
+
+/**
+ * A filter used for caching last modified dates.
+ * 
+ * @web.filter name="IfModifiedWeblogPageCacheFilter"
+ *
+ * @author Allen Gilliland
+ */
+public class IfModifiedWeblogPageCacheFilter implements Filter, CacheHandler {
+    
+    private static Log mLogger = 
+            LogFactory.getLog(IfModifiedWeblogPageCacheFilter.class);
+    
+    // a unique identifier for this cache, this is used as the prefix for
+    // roller config properties that apply to this cache
+    private static final String CACHE_ID = "cache.ifmodified.page";
+    
+    private Cache mCache = null;
+    
+    SimpleDateFormat dateFormatter =
+            new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy");
+    
+    
+    /**
+     * Process filter.
+     */
+    public void doFilter(ServletRequest req, 
+                        ServletResponse res, 
+                        FilterChain chain)
+            throws IOException, ServletException {
+        
+        mLogger.debug("entering");
+        
+        HttpServletRequest request = (HttpServletRequest) req;
+        HttpServletResponse response = (HttpServletResponse) res;
+        
+        WeblogPageRequest pageRequest = null;
+        try {
+            pageRequest = new WeblogPageRequest(request);
+        } catch(Exception e) {
+            mLogger.error("error creating page request", e);
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+        
+        String key = this.CACHE_ID+":"+this.generateKey(pageRequest);
+        
+        Date updateTime = null;
+        try {
+            // we need the last expiration time for the given weblog
+            long lastExpiration = 0;
+            Date lastExpirationDate =
+                    (Date) CacheManager.getLastExpiredDate(pageRequest.getWeblogHandle());
+            if(lastExpirationDate != null)
+                lastExpiration = lastExpirationDate.getTime();
+            
+            LazyExpiringCacheEntry entry =
+                    (LazyExpiringCacheEntry) this.mCache.get(key);
+            if(entry != null) {
+                updateTime = (Date) entry.getValue(lastExpiration);
+                
+                if(updateTime == null)
+                    mLogger.debug("HIT-INVALID "+key);
+            }
+            
+            if (updateTime == null) {
+                mLogger.debug("MISS "+key);
+                
+                if(pageRequest.getWeblogHandle() != null) {
+                    // just set updateTime to now
+                    updateTime = new Date();
+                    this.mCache.put(key, new LazyExpiringCacheEntry(updateTime));
+                }
+                
+            } else {
+                mLogger.debug("HIT "+key);
+            }
+            
+            // Check the incoming if-modified-since header
+            Date sinceDate =
+                    new Date(request.getDateHeader("If-Modified-Since"));
+            
+            if (updateTime != null) {
+                // convert date (JDK 1.5 workaround)
+                String date = dateFormatter.format(updateTime);
+                updateTime = new Date(date);
+                if (updateTime.compareTo(sinceDate) <= 0) {
+                    mLogger.debug("NOT_MODIFIED "+key);
+                    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+                    return;
+                }
+            }
+            
+        } catch (IllegalArgumentException e) {
+            // Thrown by getDateHeader if not in valid format. This can be
+            // safely ignored, the only consequence is that the NOT MODIFIED
+            // response is not set.
+        }
+        
+        // Set outgoing last modified header
+        if (updateTime != null) {
+            response.setDateHeader("Last-Modified", updateTime.getTime());
+        }
+        
+        chain.doFilter(request, response);
+        
+        mLogger.debug("exiting");
+    }
+    
+    
+    /**
+     * Generate a cache key from a parsed weblog page request.
+     * This generates a key of the form ...
+     *
+     * weblog/<handle>/page/<weblogPage>/[anchor]/<language>/[user]
+     *   or
+     * weblog/<handle>/page/<weblogPage>/[date]/[category]/<language>/[user]
+     *
+     *
+     * examples ...
+     *
+     * weblog/foo/page/Weblog/en
+     * weblog/foo/page/Weblog/entry_anchor/en
+     * weblog/foo/page/Weblog/20051110/en
+     * weblog/foo/page/Weblog/MyCategory/en
+     *
+     */
+    private String generateKey(WeblogPageRequest pageRequest) {
+        
+        StringBuffer key = new StringBuffer();
+        key.append("weblog/");
+        key.append(pageRequest.getWeblogHandle());
+        key.append("/page/");
+        key.append(pageRequest.getWeblogPage());
+        
+        if(pageRequest.getWeblogAnchor() != null) {
+            // TODO: do we need to convert to base64 here?
+            // this.weblogAnchor = Utilities.toBase64(this.weblogAnchor.getBytes());
+            key.append("/").append(pageRequest.getWeblogAnchor());
+        } else {
+            if(pageRequest.getWeblogDate() != null) {
+                key.append("/").append(pageRequest.getWeblogDate());
+            }
+            
+            if(pageRequest.getWeblogCategory() != null) {
+                String cat = pageRequest.getWeblogCategory();
+                if(cat.startsWith("/")) {
+                    cat = cat.substring(1);
+                }
+
+                key.append("/").append(cat);
+            }
+        }
+        
+        // add language
+        key.append("/").append(pageRequest.getLanguage());
+        
+        // add login state
+        if(pageRequest.getAuthenticUser() != null) {
+            key.append("/user=").append(pageRequest.getAuthenticUser());
+        }
+        
+        return key.toString();
+    }
+    
+    
+    /**
+     * A weblog entry has changed.
+     */
+    public void invalidate(WeblogEntryData entry) {
+        
+        mLogger.debug("invalidating entry = "+entry.getAnchor());
+        
+        // we need to remove the following cached items if they exist
+        //   - the weblog main page
+        //   - the weblog entry permalink page
+        //   - the weblog entry category page
+        //   - the weblog entry date archive pages
+        
+        /*
+        Set removeSet = new HashSet();
+        
+        // TODO: it would be nice to be able to do this without iterating
+        //       over the entire cache key set
+        String key = null;
+        Iterator allKeys = this.mCache.keySet().iterator();
+        while(allKeys.hasNext()) {
+            key = (String) allKeys.next();
+            if(key.startsWith("ifmod:weblog/"+entry.getWebsite().getHandle())) {
+                removeSet.add(key);
+            }
+        }
+        
+        this.mCache.remove(removeSet);
+        */
+    }
+    
+    
+    /**
+     * A weblog has changed.
+     */
+    public void invalidate(WebsiteData website) {
+        
+        mLogger.debug("invalidating website = "+website.getHandle());
+        
+        // we need to remove the following cached items if they exist
+        //   - all pages for this weblog
+        
+        /*
+        Set removeSet = new HashSet();
+        
+        // TODO: it would be nice to be able to do this without iterating
+        //       over the entire cache key set
+        String key = null;
+        Iterator allKeys = this.mCache.keySet().iterator();
+        while(allKeys.hasNext()) {
+            key = (String) allKeys.next();
+            
+            if(key.startsWith("ifmod:weblog/"+website.getHandle())) {
+                removeSet.add(key);
+            }
+        }
+        
+        this.mCache.remove(removeSet);
+        */
+    }
+    
+    
+    /**
+     * A bookmark has changed.
+     */
+    public void invalidate(BookmarkData bookmark) {
+        this.invalidate(bookmark.getWebsite());
+    }
+    
+    
+    /**
+     * A folder has changed.
+     */
+    public void invalidate(FolderData folder) {
+        this.invalidate(folder.getWebsite());
+    }
+    
+    
+    /**
+     * A comment has changed.
+     */
+    public void invalidate(CommentData comment) {
+        this.invalidate(comment.getWeblogEntry());
+    }
+    
+    
+    /**
+     * A referer has changed.
+     */
+    public void invalidate(RefererData referer) {
+        // ignored
+        // TODO: we probably should invalidate the entire website?
+    }
+    
+    
+    /**
+     * A user profile has changed.
+     */
+    public void invalidate(UserData user) {
+        // ignored
+        // TODO: i don't think weblog pages currently have user info, but this may change
+    }
+    
+    
+    /**
+     * A category has changed.
+     */
+    public void invalidate(WeblogCategoryData category) {
+        this.invalidate(category.getWebsite());
+    }
+    
+    
+    /**
+     * A weblog template has changed.
+     */
+    public void invalidate(WeblogTemplate template) {
+        this.invalidate(template.getWebsite());
+    }
+    
+    
+    public void clear() {
+        this.mCache.clear();
+    }
+    
+    
+    public Map getStats() {
+        
+        Map stats = new HashMap();
+        
+        return stats;
+    }
+    
+    
+    /**
+     * Destroy method for this filter
+     */
+    public void destroy() {
+    }
+    
+    
+    /**
+     * Init method for this filter
+     */
+    public void init(FilterConfig filterConfig) {
+        
+        mLogger.info("Initializing if-modified cache");
+        
+        Map cacheProps = new HashMap();
+        Enumeration allProps = RollerConfig.keys();
+        String prop = null;
+        while(allProps.hasMoreElements()) {
+            prop = (String) allProps.nextElement();
+            
+            // we are only interested in props for this cache
+            if(prop.startsWith(CACHE_ID+".")) {
+                cacheProps.put(prop.substring(CACHE_ID.length()+1), 
+                        RollerConfig.getProperty(prop));
+            }
+        }
+        
+        mLogger.info(cacheProps);
+        
+        mCache = CacheManager.constructCache(this, cacheProps);
+    }
+    
+}



Mime
View raw message