File Source: pebbleapiblogentryaggregator.java

         /* 
    P/P   *  Method: net.sourceforge.pebble.event.blog.PebbleAPIBlogEntryAggregator__static_init
          * 
          *  Postconditions:
          *    init'ed(log)
          */
     1  /*
     2   * Copyright (c) 2003-2006, Simon Brown
     3   * All rights reserved.
     4   *
     5   * Redistribution and use in source and binary forms, with or without
     6   * modification, are permitted provided that the following conditions are met:
     7   *
     8   *   - Redistributions of source code must retain the above copyright
     9   *     notice, this list of conditions and the following disclaimer.
    10   *
    11   *   - Redistributions in binary form must reproduce the above copyright
    12   *     notice, this list of conditions and the following disclaimer in
    13   *     the documentation and/or other materials provided with the
    14   *     distribution.
    15   *
    16   *   - Neither the name of Pebble nor the names of its contributors may
    17   *     be used to endorse or promote products derived from this software
    18   *     without specific prior written permission.
    19   *
    20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    30   * POSSIBILITY OF SUCH DAMAGE.
    31   */
    32  package net.sourceforge.pebble.event.blog;
    33  
    34  import net.sourceforge.pebble.domain.*;
    35  import net.sourceforge.pebble.webservice.PebbleAPIHandler;
    36  import net.sourceforge.pebble.PluginProperties;
    37  import net.sourceforge.pebble.api.event.blog.BlogEvent;
    38  import net.sourceforge.pebble.api.event.blog.BlogListener;
    39  import org.apache.commons.logging.Log;
    40  import org.apache.commons.logging.LogFactory;
         /* 
    P/P   *  Method: void net.sourceforge.pebble.event.blog.PebbleAPIBlogEntryAggregator()
          * 
          *  Postconditions:
          *    this.timer == &new Timer(PebbleAPIBlogEntryAggregator#1)
          *    new Timer(PebbleAPIBlogEntryAggregator#1) num objects == 1
          */
    41  import org.apache.xmlrpc.XmlRpcClient;
    42  
    43  import java.util.*;
    44  
    45  /**
    46   * Blog listener that polls a Pebble blog, using the Pebble XML-RPC API,
    47   * to pull across and aggregate blog entries. This assumes that the IDs of
    48   * blog entries in both the local and remote blogs don't clash. 
    49   *
    50   * @author Simon Brown
    51   */
    52  public abstract class PebbleAPIBlogEntryAggregator extends TimerTask implements BlogListener {
    53  
    54    private static final int ONE_HOUR = 1000 * 60 * 60;
    55    private static final Log log = LogFactory.getLog(PebbleAPIBlogEntryAggregator.class);
    56  
    57    public static final String XMLRPC_URL_KEY = ".xmlrpcUrl";
    58    public static final String BLOG_KEY = ".blog";
    59    public static final String USERNAME_KEY = ".username";
    60    public static final String PASSWORD_KEY = ".password";
    61    public static final String BLOG_ENTRIES_KEY = ".blogEntries";
    62  
    63    private Blog blog;
    64    private Timer timer = new Timer();
    65  
    66    /**
    67     * Called when a blog has been started.
    68     *
    69     * @param event   a BlogEvent instance
    70     */
           /* 
    P/P     *  Method: void blogStarted(BlogEvent)
            * 
            *  Preconditions:
            *    event != null
            *    this.timer != null
            * 
            *  Postconditions:
            *    init'ed(this.blog)
            */
    71    public void blogStarted(BlogEvent event) {
    72      this.blog = event.getBlog();
    73      timer.schedule(this, 0, ONE_HOUR);
    74    }
    75  
    76    /**
    77     * Called when a blog has been stopped.
    78     *
    79     * @param event   a BlogEvent instance
    80     */
           /* 
    P/P     *  Method: void blogStopped(BlogEvent)
            * 
            *  Preconditions:
            *    this.timer != null
            */
    81    public void blogStopped(BlogEvent event) {
    82      timer.cancel();
    83    }
    84  
    85    /**
    86     *
    87     */
    88    public void run() {
    89      try {
    90        PluginProperties props = blog.getPluginProperties();
               /* 
    P/P         *  Method: void run()
                * 
                *  Preconditions:
                *    (soft) this.blog != null
                *    (soft) this.blog.pluginProperties != null
                * 
                *  Presumptions:
                *    blogEntry.categories@129 != null
                *    blogEntry.categories@134 != null
                *    blogEntry.propertyChangeSupport@129 != null
                *    blogEntry.propertyChangeSupport@134 != null
                *    java.util.Hashtable:get(...)@169 != null
                *    ...
                * 
                *  Postconditions:
                *    init'ed(new ArrayList(Category#1) num objects)
                *    init'ed(new ArrayList(Category#2) num objects)
                *    init'ed(new ArrayList(Category#3) num objects)
                *    init'ed(new Category(getCategory#2*) num objects)
                *    init'ed(new Category(getCategory#2*).blog)
                *    init'ed(new Category(getCategory#2*).blogEntries)
                *    init'ed(new Category(getCategory#2*).id)
                *    init'ed(new Category(getCategory#2*).name)
                *    init'ed(new Category(getCategory#2*).parent)
                *    init'ed(new Category(getCategory#2*).subCategories)
                *    ...
                * 
                *  Test Vectors:
                *    getBlogEntry(...)@129: Inverse{null}, Addr_Set{null}
                *    java.util.Hashtable:get(...)@118: Addr_Set{null}, Inverse{null}
                *    java.util.Hashtable:get(...)@119: Addr_Set{null}, Inverse{null}
                *    java.util.Hashtable:get(...)@120: Addr_Set{null}, Inverse{null}
                *    java.util.Iterator:hasNext(...)@148: {1}, {0}
                *    java.util.Iterator:hasNext(...)@156: {1}, {0}
                *    java.util.Iterator:hasNext(...)@159: {0}, {1}
                *    preAggregate(...)@122: {1}, {0}
                */
    91        XmlRpcClient xmlrpc = new XmlRpcClient(props.getProperty(getPropertyPrefix() + XMLRPC_URL_KEY));
    92        Vector<Object> params = new Vector<Object>();
    93        params.add(props.getProperty(getPropertyPrefix() + BLOG_KEY));
    94        params.add(props.getProperty(getPropertyPrefix() + USERNAME_KEY));
    95        params.add(props.getProperty(getPropertyPrefix() + PASSWORD_KEY));
    96  
    97        int numberOfBlogEntries = 10;
    98        try {
    99          numberOfBlogEntries = Integer.parseInt(props.getProperty(getPropertyPrefix() + BLOG_ENTRIES_KEY));
   100        } catch (NumberFormatException nfe) {
   101          // do nothing, the value has already been defaulted
   102        }
   103        params.add(numberOfBlogEntries);
   104  
   105        // get the remote blog entries
   106        Vector<Hashtable> remoteBlogEntries = (Vector<Hashtable>)xmlrpc.execute("pebble.getRecentBlogEntries", params);
   107  
   108        // loop through them and add them to the local blog
   109        for (Hashtable remoteBlogEntry : remoteBlogEntries) {
   110          String id = (String)remoteBlogEntry.get(PebbleAPIHandler.ID);
   111          String title = (String)remoteBlogEntry.get(PebbleAPIHandler.TITLE);
   112          String subtitle = (String)remoteBlogEntry.get(PebbleAPIHandler.SUBTITLE);
   113          String excerpt = (String)remoteBlogEntry.get(PebbleAPIHandler.EXCERPT);
   114          String body = (String)remoteBlogEntry.get(PebbleAPIHandler.BODY);
+  115          Date date = (Date)remoteBlogEntry.get(PebbleAPIHandler.DATE);
   116          String author = (String)remoteBlogEntry.get(PebbleAPIHandler.AUTHOR);
   117          String permalink = (String)remoteBlogEntry.get(PebbleAPIHandler.PERMALINK);
   118          Vector<String> categories = (Vector<String>)remoteBlogEntry.get(PebbleAPIHandler.CATEGORIES);
   119          Vector<String> tags = (Vector<String>)remoteBlogEntry.get(PebbleAPIHandler.TAGS);
   120          Hashtable attachment = (Hashtable)remoteBlogEntry.get(PebbleAPIHandler.ATTACHMENT);
   121  
   122          if (!preAggregate(remoteBlogEntry)) {
   123            continue;
   124          }
   125  
   126          log.info("Aggregating " + title + " [ " + id + " | " + permalink + " ]");
   127  
   128          BlogService service = new BlogService();
   129          BlogEntry blogEntry = service.getBlogEntry(blog, id);
   130          if (blogEntry == null) {
   131            // create a new blog entry if one doesn't exist
   132            blogEntry = new BlogEntry(blog);
   133            blogEntry.setDate(new Date(Long.parseLong(id)));
   134            service.putBlogEntry(blogEntry);
   135          }
   136  
   137          // now ensure the local blog entry is in sync
   138          blogEntry.setTitle(title);
   139          blogEntry.setSubtitle(subtitle);
   140          blogEntry.setBody(body);
   141          blogEntry.setExcerpt(excerpt);
   142          blogEntry.setAuthor(author);
   143          blogEntry.setOriginalPermalink(permalink);
   144          blogEntry.setCommentsEnabled(false);
   145          blogEntry.setTrackBacksEnabled(false);
   146  
   147          if (categories != null) {
   148            for (String categoryId : categories) {
   149              blogEntry.addCategory(blog.getCategory(categoryId));
   150            }
   151          }
   152  
   153          if (tags != null) {
   154            StringBuffer buf = new StringBuffer();
   155            Iterator it = tags.iterator();
   156            while (it.hasNext()) {
   157              String tag = (String)it.next();
   158              buf.append(tag);
   159              if (it.hasNext()) {
   160                buf.append(" ");
   161              }
   162            }
   163            blogEntry.setTags(buf.toString());
   164          }
   165  
   166          if (attachment != null) {
   167            Attachment a = new Attachment();
   168            a.setUrl((String)attachment.get(PebbleAPIHandler.ATTACHMENT_URL));
   169            a.setSize((Long)attachment.get(PebbleAPIHandler.ATTACHMENT_SIZE));
   170            a.setType((String)attachment.get(PebbleAPIHandler.ATTACHMENT_TYPE));
   171            blogEntry.setAttachment(a);
   172          }
   173  
   174          postAggregate(blogEntry);
   175  
   176          service.putBlogEntry(blogEntry);
   177        }
   178      } catch (Exception e) {
   179        log.error("Exception encountered", e);
   180      }
   181    }
   182  
   183    /**
   184     * Called before each blog entry is aggregated. Returning false will
   185     * stop the entry from being aggregated.
   186     *
   187     * @param blogEntry   a Hashtable instance representing a blog entry
   188     * @return  true if the blog entry should be aggregated, false otherwise
   189     */
   190    protected abstract boolean preAggregate(Hashtable blogEntry);
   191  
   192    /**
   193     * Called after each blog entry is aggregated. Use this to enrich
   194     * aggregated blog entries.
   195     *
   196     * @param blogEntry   a Hashtable instance representing a blog entry
   197     */
   198    protected abstract void postAggregate(BlogEntry blogEntry);
   199  
   200    /**
   201     * Gets the prefix to use when defining properties for this plugin.
   202     *
   203     * @return  a String (the class name)
   204     */
           /* 
    P/P     *  Method: String getPropertyPrefix()
            * 
            *  Presumptions:
            *    java.lang.Object:getClass(...)@206 != null
            * 
            *  Postconditions:
            *    init'ed(return_value)
            */
   205    protected String getPropertyPrefix() {
   206      return this.getClass().getSimpleName();
   207    }
   208  
   209  }








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