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 |