roller-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agillil...@apache.org
Subject svn commit: r421320 - in /incubator/roller/branches/roller_3.0: metadata/xdoclet/ src/org/apache/roller/ui/rendering/filters/ src/org/apache/roller/ui/rendering/servlets/ src/org/apache/roller/ui/rendering/util/ src/org/apache/roller/ui/rendering/veloc...
Date Wed, 12 Jul 2006 16:59:29 GMT
Author: agilliland
Date: Wed Jul 12 09:59:28 2006
New Revision: 421320

URL: http://svn.apache.org/viewvc?rev=421320&view=rev
Log:
moving planet feed servlet to new rendering system.  this is the last of the old velocity
servlets.

- updated planet feed servlet to use new rendering system
- removed RollerRequest from planet feed servlet and use parse PlanetRequest now
- created new PlanetCache shared cache class for planet content
- removed if planet modified filter, that logic is handled in planet feed servlet now


Added:
    incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/servlets/PlanetFeedServlet.java
      - copied, changed from r421294, incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/velocity/PlanetFeedServlet.java
    incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/util/PlanetCache.java
Removed:
    incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/filters/IfPlanetModifiedFilter.java
    incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/velocity/PlanetFeedServlet.java
Modified:
    incubator/roller/branches/roller_3.0/metadata/xdoclet/filter-mappings.xml

Modified: incubator/roller/branches/roller_3.0/metadata/xdoclet/filter-mappings.xml
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/metadata/xdoclet/filter-mappings.xml?rev=421320&r1=421319&r2=421320&view=diff
==============================================================================
--- incubator/roller/branches/roller_3.0/metadata/xdoclet/filter-mappings.xml (original)
+++ incubator/roller/branches/roller_3.0/metadata/xdoclet/filter-mappings.xml Wed Jul 12 09:59:28
2006
@@ -80,14 +80,6 @@
 	<dispatcher>REQUEST</dispatcher>
 	<dispatcher>FORWARD</dispatcher>
 </filter-mapping>
-<filter-mapping>
-    <filter-name>IfPlanetModifiedFilter</filter-name>
-    <url-pattern>/planetrss/*</url-pattern>
-</filter-mapping>
-<filter-mapping>
-    <filter-name>PlanetCacheFilter</filter-name>
-    <url-pattern>/planetrss</url-pattern>
-</filter-mapping>
 
 
 <!-- Do we still need the RequestFilter? -->

Copied: incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/servlets/PlanetFeedServlet.java
(from r421294, incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/velocity/PlanetFeedServlet.java)
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/servlets/PlanetFeedServlet.java?p2=incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/servlets/PlanetFeedServlet.java&p1=incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/velocity/PlanetFeedServlet.java&r1=421294&r2=421320&rev=421320&view=diff
==============================================================================
--- incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/velocity/PlanetFeedServlet.java
(original)
+++ incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/servlets/PlanetFeedServlet.java
Wed Jul 12 09:59:28 2006
@@ -16,68 +16,125 @@
  * directory of this distribution.
  */
 
-package org.apache.roller.ui.rendering.velocity;
+package org.apache.roller.ui.rendering.servlets;
 
 import java.io.IOException;
 import java.util.Date;
+import java.util.HashMap;
+import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.velocity.Template;
-import org.apache.velocity.context.Context;
-import org.apache.velocity.servlet.VelocityServlet;
 import org.apache.roller.RollerException;
 import org.apache.roller.config.RollerRuntimeConfig;
 import org.apache.roller.model.PlanetManager;
 import org.apache.roller.model.RollerFactory;
-import org.apache.roller.ui.core.RollerRequest;
+import org.apache.roller.ui.rendering.Renderer;
+import org.apache.roller.ui.rendering.RendererManager;
+import org.apache.roller.ui.rendering.util.PlanetCache;
+import org.apache.roller.ui.rendering.util.PlanetRequest;
 import org.apache.roller.util.Utilities;
+import org.apache.roller.util.cache.CachedContent;
 
 
 /**
  * Planet Roller (i.e. NOT for Planet Tool) RSS feed.
  *
- * @web.servlet name="PlanetFeedServlet"
+ * @web.servlet name="PlanetFeedServlet" load-on-startup="7"
  * @web.servlet-mapping url-pattern="/planetrss/*"
  */
-public class PlanetFeedServlet extends VelocityServlet {
+public class PlanetFeedServlet extends HttpServlet {
     
-    private static Log mLogger = LogFactory.getLog(RollerRequest.class);
+    private static Log log = LogFactory.getLog(PlanetFeedServlet.class);
     
+    private PlanetCache planetCache = null;
     
-    public Template handleRequest(HttpServletRequest request,
-            HttpServletResponse response, Context context) {
+    
+    /**
+     * Init method for this servlet
+     */
+    public void init(ServletConfig servletConfig) throws ServletException {
+        
+        super.init(servletConfig);
         
-        RollerRequest rreq = null;
+        log.info("Initializing PlanetRssServlet");
+        
+        this.planetCache = PlanetCache.getInstance();
+    }
+    
+    
+    /**
+     * Handle GET requests for weblog pages.
+     */
+    public void doGet(HttpServletRequest request, HttpServletResponse response) 
+            throws ServletException, IOException {
+        
+        log.debug("Entering");
+        
+        PlanetManager planet = null;
         try {
-            rreq = RollerRequest.getRollerRequest(request, getServletContext());
-        } catch (RollerException e) {
-            // An error initializing the request is considered to be a 404
-            if (mLogger.isDebugEnabled()) {
-                mLogger.debug("RollerRequest threw Exception", e);
-            }
-            try {
-                response.sendError(HttpServletResponse.SC_NOT_FOUND);
-            } catch (IOException e1) {
-                if (mLogger.isDebugEnabled()) {
-                    mLogger.debug("IOException sending error", e);
-                }
-            }
-            return null;
+            planet = RollerFactory.getRoller().getPlanetManager();
+        } catch (RollerException ex) {
+            // error getting planet manager :(
+            log.error("Unable to get planet manager", ex);
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            return;
         }
+        
+        PlanetRequest planetRequest = null;
+        try {
+            planetRequest = new PlanetRequest(request);
+        } catch (Exception e) {
+            // some kind of error parsing the request
+            log.debug("error creating planet request", e);
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+        
+        // figure planet last modified date
+        Date lastModified = planetCache.lastModified();
+        
+        // 304 if-modified-since checking
+        long sinceDate = request.getDateHeader("If-Modified-Since");
+        log.debug("since date = "+sinceDate);
+        if(lastModified.getTime() <= sinceDate) {
+            log.debug("NOT MODIFIED "+request.getRequestURL());
+            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+            return;
+        }
+        
+        // set content type
+        response.setContentType("application/rss+xml; charset=utf-8");
+        
+        // set last-modified date
+        // small hack here, we add 1 second (1000 ms) to the last mod time to
+        // account for some lost precision when converting request date headers
+        response.setDateHeader("Last-Modified", lastModified.getTime()+1000);
+        
+        // cached content checking
+        String cacheKey = PlanetCache.CACHE_ID+":"+this.generateKey(planetRequest);
+        CachedContent entry = (CachedContent) planetCache.get(cacheKey);
+        if(entry != null) {
+            response.setContentLength(entry.getContent().length);
+            response.getOutputStream().write(entry.getContent());
+            return;
+            
+        }
+        
+        
+        // looks like we need to render content
+        HashMap model = new HashMap();
         try {
-            response.setContentType("application/rss+xml;charset=utf-8");
-            PlanetManager planet =
-                    RollerFactory.getRoller().getPlanetManager();
+            // populate the rendering model
             if (request.getParameter("group") != null) {
-                context.put("group",
-                        planet.getGroup(request.getParameter("group")));
+                model.put("group", planet.getGroup(request.getParameter("group")));
             }
-            context.put("planet", planet);
-            context.put("date", new Date());
-            context.put("utilities", new Utilities());
+            model.put("planet", planet);
+            model.put("date", new Date());
+            model.put("utilities", new Utilities());
             
             int entryCount =
                     RollerRuntimeConfig.getIntProperty("site.newsfeeds.defaultEntries");
@@ -88,27 +145,111 @@
                 try {
                     entryCount = Integer.parseInt(sCount);
                 } catch (NumberFormatException e) {
-                    mLogger.warn("Improperly formatted count parameter");
+                    log.warn("Improperly formatted count parameter");
                 }
                 if ( entryCount > maxEntries ) entryCount = maxEntries;
                 if ( entryCount < 0 ) entryCount = 0;
             }
-            context.put("entryCount", new Integer(entryCount));
+            model.put("entryCount", new Integer(entryCount));
             
-            return getTemplate("templates/planet/planetrss.vm");
-        } catch (Exception e) {
-            mLogger.error("ERROR in PlanetFeedServlet", e);
+        } catch (RollerException ex) {
+            log.error("Error loading model objects for page", ex);
+            
+            if(!response.isCommitted()) response.reset();
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            return;
+        }
+        
+        
+        // lookup Renderer we are going to use
+        Renderer renderer = null;
+        try {
+            log.debug("Looking up renderer");
+            renderer = RendererManager.getRenderer("velocity", "templates/planet/planetrss.vm");
+        } catch(Exception e) {
+            // nobody wants to render my content :(
+            log.error("Couldn't find renderer for planet rss", e);
+            
+            if(!response.isCommitted()) response.reset();
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
         }
-        return null;
+        
+        // render content.  use default size of about 24K for a standard page
+        CachedContent rendererOutput = new CachedContent(24567);
+        try {
+            log.debug("Doing rendering");
+            renderer.render(model, rendererOutput.getCachedWriter());
+            
+            // flush rendered output and close
+            rendererOutput.flush();
+            rendererOutput.close();
+        } catch(Exception e) {
+            // bummer, error during rendering
+            log.error("Error during rendering for planet rss", e);
+            
+            if(!response.isCommitted()) response.reset();
+            response.sendError(HttpServletResponse.SC_NOT_FOUND);
+            return;
+        }
+        
+        
+        // post rendering process
+        
+        // flush rendered content to response
+        log.debug("Flushing response output");
+        response.setContentLength(rendererOutput.getContent().length);
+        response.getOutputStream().write(rendererOutput.getContent());
+        
+        // cache rendered content.
+        this.planetCache.put(cacheKey, rendererOutput);
+        
+        log.debug("Exiting");
     }
-    
+
     
     /**
-     * Handle error in Velocity processing.
+     * Generate a cache key from a parsed planet request.
+     * This generates a key of the form ...
+     *
+     * <context>/<type>/<language>[/user]
+     *   or
+     * <context>/<type>[/flavor]/<language>[/excerpts]
+     *
+     *
+     * examples ...
+     *
+     * planet/page/en
+     * planet/feed/rss/en/excerpts
+     *
      */
-    protected void error( HttpServletRequest req, HttpServletResponse res,
-            Exception e) throws ServletException, IOException {
-        mLogger.warn("ERROR in PlanetFeedServlet",e);
+    private String generateKey(PlanetRequest planetRequest) {
+        
+        StringBuffer key = new StringBuffer();
+        key.append(planetRequest.getContext());
+        key.append("/");
+        key.append(planetRequest.getType());
+        
+        if(planetRequest.getFlavor() != null) {
+            key.append("/").append(planetRequest.getFlavor());
+        }
+        
+        // add language
+        key.append("/").append(planetRequest.getLanguage());
+        
+        if(planetRequest.getFlavor() != null) {
+            // add excerpts
+            if(planetRequest.isExcerpts()) {
+                key.append("/excerpts");
+            }
+        } else {
+            // add login state
+            if(planetRequest.getAuthenticUser() != null) {
+                key.append("/user=").append(planetRequest.getAuthenticUser());
+            }
+        }
+        
+        return key.toString();
     }
     
 }

Added: incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/util/PlanetCache.java
URL: http://svn.apache.org/viewvc/incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/util/PlanetCache.java?rev=421320&view=auto
==============================================================================
--- incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/util/PlanetCache.java
(added)
+++ incubator/roller/branches/roller_3.0/src/org/apache/roller/ui/rendering/util/PlanetCache.java
Wed Jul 12 09:59:28 2006
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.ui.rendering.util;
+
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.RollerException;
+import org.apache.roller.config.RollerConfig;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.pojos.BookmarkData;
+import org.apache.roller.pojos.CommentData;
+import org.apache.roller.pojos.FolderData;
+import org.apache.roller.pojos.RefererData;
+import org.apache.roller.pojos.UserData;
+import org.apache.roller.pojos.WeblogCategoryData;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WeblogTemplate;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.util.cache.Cache;
+import org.apache.roller.util.cache.CacheHandler;
+import org.apache.roller.util.cache.CacheManager;
+import org.apache.roller.util.cache.ExpiringCacheEntry;
+
+
+/**
+ * Special cache class for planet content.  We do this as it's own class instead
+ * of in a servlet like elsewhere because this cache is shared between the
+ * planetrss servlet and the planet.do struts action.
+ */
+public class PlanetCache implements CacheHandler {
+    
+    private static Log log = LogFactory.getLog(PlanetCache.class);
+    
+    // a unique identifier for this cache, this is used as the prefix for
+    // roller config properties that apply to this cache
+    public static final String CACHE_ID = "cache.planet";
+    
+    private Cache contentCache = null;
+    
+    private ExpiringCacheEntry lastUpdateTime = null;
+    private long timeout = 15 * 60 * 1000;
+    
+    // for metrics
+    private double hits = 0;
+    private double misses = 0;
+    private Date startTime = new Date();
+    
+    private static PlanetCache singletonInstance = new PlanetCache();
+    
+    
+    private PlanetCache() {
+        
+        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));
+            }
+        }
+        
+        log.info("Planet cache = "+cacheProps);
+        
+        contentCache = CacheManager.constructCache(this, cacheProps);
+        
+        // lookup our timeout value
+        String timeoutString = RollerConfig.getProperty("cache.planet.timeout");
+        try {
+            long timeoutSecs = Long.parseLong(timeoutString);
+            this.timeout = timeoutSecs * 1000;
+        } catch(Exception e) {
+            // ignored ... illegal value
+        }
+    }
+    
+    
+    public static PlanetCache getInstance() {
+        return singletonInstance;
+    }
+    
+    
+    public Object get(String key) {
+        
+        Object entry = contentCache.get(key);
+        
+        if(entry == null) {
+            this.misses++;
+            log.debug("MISS "+key);
+        } else {
+            this.hits++;
+            log.debug("HIT "+key);
+        }
+        
+        return entry;
+    }
+    
+    
+    public void put(String key, Object value) {
+        contentCache.put(key, value);
+        log.debug("PUT "+key);
+    }
+    
+    
+    public Date lastModified() {
+        
+        Date lastModified = null;
+        
+        // first try our cached version
+        if(this.lastUpdateTime != null) {
+            lastModified = (Date) this.lastUpdateTime.getValue();
+        }
+        
+        // still null, we need to get a fresh value
+        if(lastModified == null) {
+            
+            try {
+                lastModified = RollerFactory.getRoller().getPlanetManager().getLastUpdated();
+            } catch (RollerException ex) {
+                log.error("Error getting planet manager", ex);
+            }
+            
+            if (lastModified == null) {
+                lastModified = new Date();
+                log.warn("Can't get lastUpdate time, using current time instead");
+            }
+            
+            this.lastUpdateTime = new ExpiringCacheEntry(lastModified, this.timeout);
+        }
+        
+        return lastModified;
+    }
+
+    
+    /**
+     * A weblog entry has changed.
+     */
+    public void invalidate(WeblogEntryData entry) {
+        // ignored
+    }
+    
+    
+    /**
+     * A weblog has changed.
+     */
+    public void invalidate(WebsiteData website) {
+        // ignored
+    }
+    
+    
+    /**
+     * A bookmark has changed.
+     */
+    public void invalidate(BookmarkData bookmark) {
+        // ignored
+    }
+    
+    
+    /**
+     * A folder has changed.
+     */
+    public void invalidate(FolderData folder) {
+        // ignored
+    }
+    
+    
+    /**
+     * A comment has changed.
+     */
+    public void invalidate(CommentData comment) {
+        // ignored
+    }
+    
+    
+    /**
+     * A referer has changed.
+     */
+    public void invalidate(RefererData referer) {
+        // ignored
+    }
+    
+    
+    /**
+     * A user profile has changed.
+     */
+    public void invalidate(UserData user) {
+        // ignored
+    }
+    
+    
+    /**
+     * A category has changed.
+     */
+    public void invalidate(WeblogCategoryData category) {
+        // ignored
+    }
+    
+    
+    /**
+     * A weblog template has changed.
+     */
+    public void invalidate(WeblogTemplate template) {
+        // ignored
+    }
+    
+    
+    /**
+     * Clear the entire cache.
+     */
+    public void clear() {
+        log.info("Clearing cache");
+        this.contentCache.clear();
+        this.startTime = new Date();
+        this.hits = 0;
+        this.misses = 0;
+    }
+    
+    
+    public Map getStats() {
+        
+        Map stats = new HashMap();
+        stats.put("cacheType", this.contentCache.getClass().getName());
+        stats.put("startTime", this.startTime);
+        stats.put("hits", new Double(this.hits));
+        stats.put("misses", new Double(this.misses));
+        
+        // calculate efficiency
+        if(misses > 0) {
+            double efficiency = hits / (misses + hits);
+            stats.put("efficiency", new Double(efficiency * 100));
+        }
+        
+        return stats;
+    }
+    
+}



Mime
View raw message