Clover Coverage Report - Pebble 2.5-SNAPSHOT
Coverage timestamp: Sat Jun 12 2010 09:39:29 EST
../../../../../img/srcFileCovDistChart0.png 48% of files have more coverage
66   209   13   16,5
14   109   0,2   4
4     3,25  
1    
This report was generated with an evaluation server license. Purchase Clover or configure your license.
 
  PebbleAPIBlogEntryAggregator       Line # 52 66 0% 13 84 0% 0.0
 
No Tests
 
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;
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    */
 
71  0 toggle public void blogStarted(BlogEvent event) {
72  0 this.blog = event.getBlog();
73  0 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    */
 
81  0 toggle public void blogStopped(BlogEvent event) {
82  0 timer.cancel();
83    }
84   
85    /**
86    *
87    */
 
88  0 toggle public void run() {
89  0 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  0 try {
99  0 numberOfBlogEntries = Integer.parseInt(props.getProperty(getPropertyPrefix() + BLOG_ENTRIES_KEY));
100    } catch (NumberFormatException nfe) {
101    // do nothing, the value has already been defaulted
102    }
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    }
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    }
178    } catch (Exception e) {
179  0 log.error(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    */
 
205  0 toggle protected String getPropertyPrefix() {
206  0 return this.getClass().getSimpleName();
207    }
208   
209    }