File Source: relatedpostsdecorator.java

     1  package net.sourceforge.pebble.decorator;
     2  
     3  import java.util.HashSet;
     4  import java.util.List;
     5  import java.util.Set;
     6  
     7  import net.sourceforge.pebble.PluginProperties;
     8  import net.sourceforge.pebble.api.decorator.ContentDecoratorContext;
     9  import net.sourceforge.pebble.domain.Blog;
    10  import net.sourceforge.pebble.domain.BlogEntry;
    11  import net.sourceforge.pebble.domain.Tag;
    12  import net.sourceforge.pebble.util.I18n;
    13  import net.sourceforge.pebble.util.StringUtils;
    14  
    15  import org.apache.commons.logging.Log;
    16  import org.apache.commons.logging.LogFactory;
    17  
    18  /**
    19   * Adds related posts to the current post. The posts are selected by matching
    20   * tags of the current post to the tags of other posts in the blog. One related
    21   * post per tag.
    22   * 
    23   * Each blog entry can have up to six related posts or none.
    24   * 
    25   * @author Alexander Zagniotov
    26   */
         /* 
    P/P   *  Method: void net.sourceforge.pebble.decorator.RelatedPostsDecorator()
          */
    27  public class RelatedPostsDecorator extends ContentDecoratorSupport {
    28  
           /* 
    P/P     *  Method: net.sourceforge.pebble.decorator.RelatedPostsDecorator__static_init
            * 
            *  Postconditions:
            *    init'ed(log)
            */
    29    private static final Log log = LogFactory.getLog(RelatedPostsDecorator.class);
    30  
    31    /** the name of the max number of posts property */
    32    public static final String MAX_POSTS = "RelatedPostsDecorator.maxPosts";
    33  
    34    /**
    35     * Decorates the specified blog entry.
    36     * 
    37     * @param context
    38     *          the context in which the decoration is running
    39     * @param blogEntry
    40     *          the blog entry to be decorated
    41     */
    42    public void decorate(ContentDecoratorContext context, BlogEntry blogEntry) {
    43  
             /* 
    P/P       *  Method: void decorate(ContentDecoratorContext, BlogEntry)
              * 
              *  Preconditions:
              *    blogEntry != null
              * 
              *  Presumptions:
              *    java.util.Iterator:next(...)@77 != null
              *    java.util.Iterator:next(...)@85 != null
              *    org.apache.commons.logging.LogFactory:getLog(...)@29 != null
              * 
              *  Test Vectors:
              *    java.lang.String:equals(...)@80: {0}, {1}
              *    java.lang.String:length(...)@60: {0}, {1..232-1}
              *    java.util.Iterator:hasNext(...)@77: {1}, {0}
              *    java.util.Iterator:hasNext(...)@85: {1}, {0}
              *    java.util.Set:add(...)@90: {0}, {1}
              *    java.util.Set:size(...)@103: {-231..-1, 1..232-1}, {0}
              * 
              *  Preconditions:
              *    blogEntry.blog != null
              *    init'ed(blogEntry.body)
              *    (soft) init'ed(blogEntry.categories)
              *    (soft) blogEntry.propertyChangeSupport != null
              *    (soft) blogEntry.tagsAsList != null
              *    (soft) init'ed(blogEntry.title)
              * 
              *  Presumptions:
              *    entry.blog@77 != null
              *    entry.blog@90 != null
              *    entry.tagsAsList@77 != null
              *    entry.title@77 != null
              * 
              *  Postconditions:
              *    init'ed(blogEntry.body)
              * 
              *  Preconditions:
              *    blogEntry.blog.pluginProperties != null
              *    (soft) blogEntry.blog.rootCategory != null
              *    (soft) init'ed(blogEntry.blog.rootCategory...parent)
              *    (soft) init'ed(blogEntry.blog.rootCategory...tagsAsList)
              *    (soft) init'ed(blogEntry.blog.rootCategory.parent)
              *    (soft) init'ed(blogEntry.blog.rootCategory.tagsAsList)
              *    (soft) blogEntry.blog.years != null
              *    (soft) net/sourceforge/pebble/domain/BlogManager.instance != null
              *    (soft) init'ed(net/sourceforge/pebble/domain/BlogManager.instance.multiBlog)
              * 
              *  Presumptions:
              *    entry.blog.rootCategory@77 != null
              * 
              *  Test Vectors:
              *    blogEntry.body: Addr_Set{null}, Inverse{null}
              *    net.sourceforge.pebble.PluginProperties:hasProperty(...)@47: {0}, {1}
              */
    44      PluginProperties props = blogEntry.getBlog().getPluginProperties();
    45      int maxPosts = StringUtils.MAX_NUM_OF_POSTS;
    46  
    47      if (props.hasProperty(RelatedPostsDecorator.MAX_POSTS)) {
    48        try {
    49          maxPosts = Integer.parseInt(props.getProperty(MAX_POSTS));
    50        }
    51        catch (NumberFormatException nfe) {
    52          log.error(nfe.getMessage());
    53          // do nothing, the value has already been defaulted
    54        }
    55      }
    56  
    57      Blog blog = blogEntry.getBlog();
    58      String body = blogEntry.getBody();
    59  
    60      if (body != null && body.trim().length() > 0) {
    61  
    62        StringBuffer buf = new StringBuffer();
    63        buf.append(body);
    64        buf.append("<p><b>" + I18n.getMessage(blog, "common.relatedPosts") + "</b><br />");
    65  
    66        // tags of the current entry
    67        List<Tag> currentEntryTags = blogEntry.getAllTags();
    68  
    69        // all blog entries of the current blog
    70        List<BlogEntry> allBlogEntries = (List<BlogEntry>) blog.getBlogEntries();
    71  
    72        // temporary holder for accumulated unique related posts.
    73        // using hash set assures that we wont have same related post twice for
    74        // different tags.
    75        Set<BlogEntry> relatedEntries = new HashSet<BlogEntry>();
    76  
    77        for (BlogEntry entry : allBlogEntries) {
    78  
    79          // don't add current entry as a related post of it self, skip it
    80          if (entry.getTitle().equals(blogEntry.getTitle()))
    81            continue;
    82  
    83          // loop through each of the current entry tags, and try to find related
    84          // post by matching current tag to the posts tags
    85          for (Tag currentTag : currentEntryTags) {
    86            if (entry.hasTag(currentTag.getName())) {
    87              // if we successfully selected related post - create hyperlink for
    88              // it
    89              // TODO: Missing escaping -- XSS vulnerabilities here :(
    90              if (relatedEntries.add(entry))
    91                buf.append("<a href=\"" + entry.getPermalink() + "\" rel=\"bookmark\" title=\"" + entry.getTitle()
    92                    + "\">" + entry.getTitle() + "</a><br />");
    93            }
    94          }
    95  
    96          // do not allow more than default amount of posts or
    97          // amount set through the RelatedPostsDecorator.maxPosts property
    98          if (relatedEntries.size() == maxPosts) {
    99            break;
   100          }
   101        }
   102  
   103        if (relatedEntries.size() == 0)
   104          buf.append("<i>" + I18n.getMessage(blog, "common.noRelatedPosts") + "</i>");
   105  
   106        buf.append("</p><br />");
   107        blogEntry.setBody(buf.toString());
   108      }
   109    }
   110  }








SofCheck Inspector Build Version : 2.22510
relatedpostsdecorator.java 2010-Jun-25 19:40:32
relatedpostsdecorator.class 2010-Jul-19 20:23:40