File Source: FeedServlet.java

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   *  contributor license agreements.  The ASF licenses this file to You
     4   * under the Apache License, Version 2.0 (the "License"); you may not
     5   * use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.  For additional information regarding
    15   * copyright in this work, please see the NOTICE file in the top level
    16   * directory of this distribution.
    17   */
    18  
    19  package org.apache.roller.weblogger.ui.rendering.servlets;
    20  
    21  import java.io.IOException;
    22  import java.util.HashMap;
    23  import java.util.Map;
    24  import javax.servlet.ServletConfig;
    25  import javax.servlet.ServletException;
    26  import javax.servlet.http.HttpServlet;
    27  import javax.servlet.http.HttpServletRequest;
    28  import javax.servlet.http.HttpServletResponse;
    29  import org.apache.commons.logging.Log;
    30  import org.apache.commons.logging.LogFactory;
    31  import org.apache.roller.weblogger.WebloggerException;
    32  import org.apache.roller.weblogger.business.WebloggerFactory;
    33  import org.apache.roller.weblogger.business.WeblogManager;
    34  import org.apache.roller.weblogger.config.WebloggerConfig;
    35  import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
    36  import org.apache.roller.weblogger.pojos.StaticTemplate;
    37  import org.apache.roller.weblogger.pojos.Template;
    38  import org.apache.roller.weblogger.pojos.Weblog;
    39  import org.apache.roller.weblogger.ui.rendering.util.WeblogFeedRequest;
    40  import org.apache.roller.weblogger.util.cache.CachedContent;
    41  import org.apache.roller.weblogger.ui.rendering.Renderer;
    42  import org.apache.roller.weblogger.ui.rendering.RendererManager;
    43  import org.apache.roller.weblogger.ui.rendering.model.ModelLoader;
    44  import org.apache.roller.weblogger.ui.rendering.model.SearchResultsFeedModel;
    45  import org.apache.roller.weblogger.ui.rendering.util.cache.SiteWideCache;
    46  import org.apache.roller.weblogger.ui.rendering.util.cache.WeblogFeedCache;
    47  import org.apache.roller.weblogger.ui.rendering.util.ModDateHeaderUtil;
    48  
    49  
    50  /**
    51   * Responsible for rendering weblog feeds.
    52   *
    53   * @web.servlet name="FeedServlet" load-on-startup="5"
    54   * @web.servlet-mapping url-pattern="/roller-ui/rendering/feed/*"
    55   */
         /* 
    P/P   *  Method: void org.apache.roller.weblogger.ui.rendering.servlets.FeedServlet()
          * 
          *  Postconditions:
          *    this.siteWideCache == null
          *    this.weblogFeedCache == null
          */
    56  public class FeedServlet extends HttpServlet {
    57  
             /* 
    P/P       *  Method: org.apache.roller.weblogger.ui.rendering.servlets.FeedServlet__static_init
              * 
              *  Postconditions:
              *    init'ed(log)
              */
    58      private static Log log = LogFactory.getLog(FeedServlet.class);
    59  
    60      private WeblogFeedCache weblogFeedCache = null;
    61      private SiteWideCache siteWideCache = null;
    62  
    63  
    64      /**
    65       * Init method for this servlet
    66       */
    67      public void init(ServletConfig servletConfig) throws ServletException {
    68  
                 /* 
    P/P           *  Method: void init(ServletConfig)
                  * 
                  *  Preconditions:
                  *    log != null
                  * 
                  *  Postconditions:
                  *    init'ed(this.siteWideCache)
                  *    init'ed(this.weblogFeedCache)
                  */
    69          super.init(servletConfig);
    70  
    71          log.info("Initializing FeedServlet");
    72  
    73          // get a reference to the weblog feed cache
    74          this.weblogFeedCache = WeblogFeedCache.getInstance();
    75  
    76          // get a reference to the site wide cache
    77          this.siteWideCache = SiteWideCache.getInstance();
    78      }
    79  
    80  
    81      /**
    82       * Handle GET requests for weblog feeds.
    83       */
    84      public void doGet(HttpServletRequest request, HttpServletResponse response)
    85              throws ServletException, IOException {
    86  
                 /* 
    P/P           *  Method: void doGet(HttpServletRequest, HttpServletResponse)
                  * 
                  *  Preconditions:
                  *    log != null
                  *    (soft) org/apache/roller/weblogger/ui/rendering/RendererManager.rendererFactories != null
                  *    (soft) org/apache/roller/weblogger/ui/rendering/model/ModelLoader.log != null
                  *    (soft) org/apache/roller/weblogger/util/cache/CachedContent.log != null
                  *    (soft) request != null
                  *    (soft) response != null
                  *    (soft) this.siteWideCache != null
                  *    (soft) this.weblogFeedCache != null
                  * 
                  *  Presumptions:
                  *    cachedContent.content@157 != null
                  *    cachedContent.content@159 != null
                  *    getContent(...).length@157 <= 232-1
                  *    getContent(...).length@159 <= 232-1
                  *    getContent(...).length@291 <= 232-1
                  *    ...
                  * 
                  *  Test Vectors:
                  *    java.lang.String:equals(...)@140: {0}, {1}
                  *    java.lang.String:equals(...)@142: {0}, {1}
                  *    java.lang.String:equals(...)@246: {0}, {1}
                  *    java.lang.String:indexOf(...)@133: {-1}, {-231..-2, 0..232-1}
                  *    java.lang.String:startsWith(...)@133: {0}, {1}
                  *    java.util.List:size(...)@191: {-231..0}, {1..232-1}
                  *    javax.servlet.http.HttpServletRequest:getHeader(...)@131: Addr_Set{null}, Inverse{null}
                  *    javax.servlet.http.HttpServletRequest:getHeader(...)@132: Addr_Set{null}, Inverse{null}
                  *    javax.servlet.http.HttpServletResponse:isCommitted(...)@203: {1}, {0}
                  *    org.apache.roller.weblogger.config.WebloggerRuntimeConfig:getBooleanProperty(...)@133: {0}, {1}
                  *    ...
                  */
    87          log.debug("Entering");
    88  
    89          Weblog weblog = null;
    90          boolean isSiteWide = false;
    91  
    92          WeblogFeedRequest feedRequest = null;
    93          try {
    94              // parse the incoming request and extract the relevant data
    95              feedRequest = new WeblogFeedRequest(request);
    96  
    97              weblog = feedRequest.getWeblog();
    98              if(weblog == null) {
    99                  throw new WebloggerException("unable to lookup weblog: "+
   100                          feedRequest.getWeblogHandle());
   101              }
   102  
   103              // is this the site-wide weblog?
   104              isSiteWide = WebloggerRuntimeConfig.isSiteWideWeblog(feedRequest.getWeblogHandle());
   105  
   106          } catch(Exception e) {
   107              // invalid feed request format or weblog doesn't exist
   108              log.debug("error creating weblog feed request", e);
   109              response.sendError(HttpServletResponse.SC_NOT_FOUND);
   110              return;
   111          }
   112  
   113  
   114          // determine the lastModified date for this content
   115          long lastModified = System.currentTimeMillis();
   116          if(isSiteWide) {
   117              lastModified = siteWideCache.getLastModified().getTime();
   118          } else if (weblog.getLastModified() != null) {
   119              lastModified = weblog.getLastModified().getTime();
   120          }
   121  
   122          // Respond with 304 Not Modified if it is not modified.
   123          if (ModDateHeaderUtil.respondIfNotModified(request,response,lastModified)) {
   124              return;
   125          }
   126  
   127          // set last-modified date
   128          ModDateHeaderUtil.setLastModifiedHeader(response, lastModified);
   129  
   130          // set content type
   131          String accepts = request.getHeader("Accept");
   132          String userAgent = request.getHeader("User-Agent");
   133          if (WebloggerRuntimeConfig.getBooleanProperty("site.newsfeeds.styledFeeds") &&
   134              accepts != null && accepts.indexOf("*/*") != -1 &&
   135              userAgent != null && userAgent.startsWith("Mozilla")) {
   136              // client is a browser and feed style is enabled so we want 
   137              // browsers to load the page rather than popping up the download 
   138              // dialog, so we provide a content-type that browsers will display
   139              response.setContentType("text/xml");
   140          } else if("rss".equals(feedRequest.getFormat())) {
   141              response.setContentType("application/rss+xml; charset=utf-8");
   142          } else if("atom".equals(feedRequest.getFormat())) {
   143              response.setContentType("application/atom+xml; charset=utf-8");
   144          }
   145  
   146          // generate cache key
   147          String cacheKey = null;
   148          if(isSiteWide) {
   149              cacheKey = siteWideCache.generateKey(feedRequest);
   150          } else {
   151              cacheKey = weblogFeedCache.generateKey(feedRequest);
   152          }
   153  
   154          // cached content checking
   155          CachedContent cachedContent = null;
   156          if(isSiteWide) {
   157              cachedContent = (CachedContent) siteWideCache.get(cacheKey);
   158          } else {
   159              cachedContent = (CachedContent) weblogFeedCache.get(cacheKey, lastModified);
   160          }
   161  
   162          if(cachedContent != null) {
   163              log.debug("HIT "+cacheKey);
   164  
   165              response.setContentLength(cachedContent.getContent().length);
   166              response.getOutputStream().write(cachedContent.getContent());
   167              return;
   168  
   169          } else {
   170              log.debug("MISS "+cacheKey);
   171          }
   172          
   173          
   174          // validation.  make sure that request input makes sense.
   175          boolean invalid = false;
   176          if(feedRequest.getLocale() != null) {
   177              
   178              // locale view only allowed if weblog has enabled it
   179              if(!feedRequest.getWeblog().isEnableMultiLang()) {
   180                  invalid = true;
   181              }
   182              
   183          }
   184          if(feedRequest.getWeblogCategoryName() != null) {
   185              
   186              // category specified.  category must exist.
   187              if(feedRequest.getWeblogCategory() == null) {
   188                  invalid = true;
   189              }
   190              
   191          } else if(feedRequest.getTags() != null && feedRequest.getTags().size() > 0) {
   192              
   193              try {
   194                  // tags specified.  make sure they exist.
   195                  WeblogManager wmgr = WebloggerFactory.getWeblogger().getWeblogManager();
   196                  invalid = !wmgr.getTagComboExists(feedRequest.getTags(), (isSiteWide) ? null : weblog);
   197              } catch (WebloggerException ex) {
   198                  invalid = true;
   199              }
   200          }
   201          
   202          if(invalid) {
   203              if(!response.isCommitted()) response.reset();
   204              response.sendError(HttpServletResponse.SC_NOT_FOUND);
   205              return;
   206          }
   207          
   208          
   209          // do we need to force a specific locale for the request?
   210          if(feedRequest.getLocale() == null && !weblog.isShowAllLangs()) {
   211              feedRequest.setLocale(weblog.getLocale());
   212          }
   213          
   214          // looks like we need to render content
   215          HashMap model = new HashMap();
   216          String pageId = null;
   217          try {
   218              // determine what template to render with
   219              if (WebloggerRuntimeConfig.isSiteWideWeblog(weblog.getHandle())) {
   220                  pageId = "templates/feeds/site-"+feedRequest.getType()+"-"+feedRequest.getFormat()+".vm";
   221              } else {
   222                  pageId = "templates/feeds/weblog-"+feedRequest.getType()+"-"+feedRequest.getFormat()+".vm";
   223              }
   224  
   225              // populate the rendering model
   226              Map initData = new HashMap();
   227              initData.put("parsedRequest", feedRequest);
   228  
   229              // define url strategy
   230              initData.put("urlStrategy", WebloggerFactory.getWeblogger().getUrlStrategy());
   231              
   232              // Load models for feeds
   233              String feedModels = WebloggerConfig.getProperty("rendering.feedModels");
   234              ModelLoader.loadModels(feedModels, model, initData, true);
   235  
   236              // Load special models for site-wide blog
   237  
   238              if(WebloggerRuntimeConfig.isSiteWideWeblog(weblog.getHandle())) {
   239                  String siteModels = WebloggerConfig.getProperty("rendering.siteModels");
   240                  ModelLoader.loadModels(siteModels, model, initData, true);
   241              }
   242  
   243              // Load weblog custom models
   244              ModelLoader.loadCustomModels(weblog, model, initData);
   245              
   246              if("entries".equals(feedRequest.getType()) && feedRequest.getTerm() != null) {
   247                  pageId = "templates/feeds/weblog-search-atom.vm";                
   248                  ModelLoader.loadModels(SearchResultsFeedModel.class.getName(), model, initData, true);
   249              }                        
   250  
   251          } catch (WebloggerException ex) {
   252              log.error("ERROR loading model for page", ex);
   253  
   254              if(!response.isCommitted()) response.reset();
   255              response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
   256              return;
   257          }
   258  
   259  
   260          // lookup Renderer we are going to use
   261          Renderer renderer = null;
   262          try {
   263              log.debug("Looking up renderer");
   264              Template template = new StaticTemplate(pageId, "velocity");
   265              renderer = RendererManager.getRenderer(template);
   266          } catch(Exception e) {
   267              // nobody wants to render my content :(
   268  
   269              // TODO: this log message has been disabled because it fills up
   270              // the logs with useless errors due to the fact that the way these
   271              // template ids are formed comes directly from the request and it
   272              // often gets bunk data causing invalid template ids.
   273              // at some point we should have better validation on the input so
   274              // that we can quickly dispatch invalid feed requests and only
   275              // get this far if we expect the template to be found
   276              //log.error("Couldn't find renderer for page "+pageId, e);
   277  
   278              if(!response.isCommitted()) response.reset();
   279              response.sendError(HttpServletResponse.SC_NOT_FOUND);
   280              return;
   281          }
   282  
   283          // render content.  use default size of about 24K for a standard page
   284          CachedContent rendererOutput = new CachedContent(24567);
   285          try {
   286              log.debug("Doing rendering");
   287              renderer.render(model, rendererOutput.getCachedWriter());
   288  
   289              // flush rendered output and close
   290              rendererOutput.flush();
   291              rendererOutput.close();
   292          } catch(Exception e) {
   293              // bummer, error during rendering
   294              log.error("Error during rendering for page "+pageId, e);
   295  
   296              if(!response.isCommitted()) response.reset();
   297              response.sendError(HttpServletResponse.SC_NOT_FOUND);
   298              return;
   299          }
   300  
   301  
   302          // post rendering process
   303  
   304          // flush rendered content to response
   305          log.debug("Flushing response output");
+  306          response.setContentLength(rendererOutput.getContent().length);
   307          response.getOutputStream().write(rendererOutput.getContent());
   308  
   309          // cache rendered content.  only cache if user is not logged in?
   310          log.debug("PUT "+cacheKey);
   311          if(isSiteWide) {
   312              siteWideCache.put(cacheKey, rendererOutput);
   313          } else {
   314              weblogFeedCache.put(cacheKey, rendererOutput);
   315          }
   316  
   317          log.debug("Exiting");
   318      }
   319  
   320  }








SofCheck Inspector Build Version : 2.18479
FeedServlet.java 2009-Jan-02 14:24:44
FeedServlet.class 2009-Sep-04 03:12:45