Coverage Report - net.sourceforge.pebble.event.blog.PebbleAPIBlogEntryAggregator
 
Classes in this File Line Coverage Branch Coverage Complexity
PebbleAPIBlogEntryAggregator
0%
0/76
0%
0/18
2.833
 
 1  
 /*
 2  
  * Copyright (c) 2003-2011, 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;
 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  0
 public abstract class PebbleAPIBlogEntryAggregator extends TimerTask implements BlogListener {
 53  
 
 54  
   private static final int ONE_HOUR = 1000 * 60 * 60;
 55  0
   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  0
   private Timer timer = new Timer();
 65  
 
 66  
   /**
 67  
    * Called when a blog has been started.
 68  
    *
 69  
    * @param event   a BlogEvent instance
 70  
    */
 71  
   public void blogStarted(BlogEvent event) {
 72  0
     this.blog = event.getBlog();
 73  0
     timer.schedule(this, 0, ONE_HOUR);
 74  0
   }
 75  
 
 76  
   /**
 77  
    * Called when a blog has been stopped.
 78  
    *
 79  
    * @param event   a BlogEvent instance
 80  
    */
 81  
   public void blogStopped(BlogEvent event) {
 82  0
     timer.cancel();
 83  0
   }
 84  
 
 85  
   /**
 86  
    *
 87  
    */
 88  
   public void run() {
 89  
     try {
 90  0
       PluginProperties props = blog.getPluginProperties();
 91  0
       XmlRpcClient xmlrpc = new XmlRpcClient(props.getProperty(getPropertyPrefix() + XMLRPC_URL_KEY));
 92  0
       Vector<Object> params = new Vector<Object>();
 93  0
       params.add(props.getProperty(getPropertyPrefix() + BLOG_KEY));
 94  0
       params.add(props.getProperty(getPropertyPrefix() + USERNAME_KEY));
 95  0
       params.add(props.getProperty(getPropertyPrefix() + PASSWORD_KEY));
 96  
 
 97  0
       int numberOfBlogEntries = 10;
 98  
       try {
 99  0
         numberOfBlogEntries = Integer.parseInt(props.getProperty(getPropertyPrefix() + BLOG_ENTRIES_KEY));
 100  0
       } catch (NumberFormatException nfe) {
 101  
         // do nothing, the value has already been defaulted
 102  0
       }
 103  0
       params.add(numberOfBlogEntries);
 104  
 
 105  
       // get the remote blog entries
 106  0
       Vector<Hashtable> remoteBlogEntries = (Vector<Hashtable>)xmlrpc.execute("pebble.getRecentBlogEntries", params);
 107  
 
 108  
       // loop through them and add them to the local blog
 109  0
       for (Hashtable remoteBlogEntry : remoteBlogEntries) {
 110  0
         String id = (String)remoteBlogEntry.get(PebbleAPIHandler.ID);
 111  0
         String title = (String)remoteBlogEntry.get(PebbleAPIHandler.TITLE);
 112  0
         String subtitle = (String)remoteBlogEntry.get(PebbleAPIHandler.SUBTITLE);
 113  0
         String excerpt = (String)remoteBlogEntry.get(PebbleAPIHandler.EXCERPT);
 114  0
         String body = (String)remoteBlogEntry.get(PebbleAPIHandler.BODY);
 115  0
         Date date = (Date)remoteBlogEntry.get(PebbleAPIHandler.DATE);
 116  0
         String author = (String)remoteBlogEntry.get(PebbleAPIHandler.AUTHOR);
 117  0
         String permalink = (String)remoteBlogEntry.get(PebbleAPIHandler.PERMALINK);
 118  0
         Vector<String> categories = (Vector<String>)remoteBlogEntry.get(PebbleAPIHandler.CATEGORIES);
 119  0
         Vector<String> tags = (Vector<String>)remoteBlogEntry.get(PebbleAPIHandler.TAGS);
 120  0
         Hashtable attachment = (Hashtable)remoteBlogEntry.get(PebbleAPIHandler.ATTACHMENT);
 121  
 
 122  0
         if (!preAggregate(remoteBlogEntry)) {
 123  0
           continue;
 124  
         }
 125  
 
 126  0
         log.info("Aggregating " + title + " [ " + id + " | " + permalink + " ]");
 127  
 
 128  0
         BlogService service = new BlogService();
 129  0
         BlogEntry blogEntry = service.getBlogEntry(blog, id);
 130  0
         if (blogEntry == null) {
 131  
           // create a new blog entry if one doesn't exist
 132  0
           blogEntry = new BlogEntry(blog);
 133  0
           blogEntry.setDate(new Date(Long.parseLong(id)));
 134  0
           service.putBlogEntry(blogEntry);
 135  
         }
 136  
 
 137  
         // now ensure the local blog entry is in sync
 138  0
         blogEntry.setTitle(title);
 139  0
         blogEntry.setSubtitle(subtitle);
 140  0
         blogEntry.setBody(body);
 141  0
         blogEntry.setExcerpt(excerpt);
 142  0
         blogEntry.setAuthor(author);
 143  0
         blogEntry.setOriginalPermalink(permalink);
 144  0
         blogEntry.setCommentsEnabled(false);
 145  0
         blogEntry.setTrackBacksEnabled(false);
 146  
 
 147  0
         if (categories != null) {
 148  0
           for (String categoryId : categories) {
 149  0
             blogEntry.addCategory(blog.getCategory(categoryId));
 150  
           }
 151  
         }
 152  
 
 153  0
         if (tags != null) {
 154  0
           StringBuffer buf = new StringBuffer();
 155  0
           Iterator it = tags.iterator();
 156  0
           while (it.hasNext()) {
 157  0
             String tag = (String)it.next();
 158  0
             buf.append(tag);
 159  0
             if (it.hasNext()) {
 160  0
               buf.append(" ");
 161  
             }
 162  0
           }
 163  0
           blogEntry.setTags(buf.toString());
 164  
         }
 165  
 
 166  0
         if (attachment != null) {
 167  0
           Attachment a = new Attachment();
 168  0
           a.setUrl((String)attachment.get(PebbleAPIHandler.ATTACHMENT_URL));
 169  0
           a.setSize((Long)attachment.get(PebbleAPIHandler.ATTACHMENT_SIZE));
 170  0
           a.setType((String)attachment.get(PebbleAPIHandler.ATTACHMENT_TYPE));
 171  0
           blogEntry.setAttachment(a);
 172  
         }
 173  
 
 174  0
         postAggregate(blogEntry);
 175  
 
 176  0
         service.putBlogEntry(blogEntry);
 177  0
       }
 178  0
     } catch (Exception e) {
 179  0
       log.error("Exception encountered", e);
 180  0
     }
 181  0
   }
 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  
    */
 205  
   protected String getPropertyPrefix() {
 206  0
     return this.getClass().getSimpleName();
 207  
   }
 208  
 
 209  
 }