001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018:
019: package org.apache.roller.webservices.xmlrpc;
020:
021: import java.sql.Timestamp;
022: import java.util.ArrayList;
023: import java.util.Date;
024: import java.util.Hashtable;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.Map;
028: import java.util.StringTokenizer;
029: import java.util.Vector;
030:
031: import javax.servlet.http.HttpServletRequest;
032:
033: import org.apache.commons.lang.StringUtils;
034: import org.apache.commons.logging.Log;
035: import org.apache.commons.logging.LogFactory;
036: import org.apache.roller.RollerException;
037: import org.apache.roller.config.RollerRuntimeConfig;
038: import org.apache.roller.business.Roller;
039: import org.apache.roller.business.RollerFactory;
040: import org.apache.roller.business.UserManager;
041: import org.apache.roller.business.WeblogManager;
042: import org.apache.roller.pojos.UserData;
043: import org.apache.roller.pojos.WeblogEntryData;
044: import org.apache.roller.pojos.WeblogTemplate;
045: import org.apache.roller.pojos.WebsiteData;
046: import org.apache.roller.util.Utilities;
047: import org.apache.xmlrpc.XmlRpcException;
048:
049: /**
050: * Roller XML-RPC Handler for the Blogger v1 API.
051: *
052: * Blogger API spec can be found at http://plant.blogger.com/api/index.html
053: * See also http://xmlrpc.free-conversant.com/docs/bloggerAPI
054: *
055: * @author David M Johnson
056: */
057: public class BloggerAPIHandler extends BaseAPIHandler {
058:
059: static final long serialVersionUID = 2398898776655115019L;
060:
061: private static Log mLogger = LogFactory
062: .getLog(BloggerAPIHandler.class);
063:
064: public BloggerAPIHandler() {
065: super ();
066: }
067:
068: /**
069: * Delete a Post
070: *
071: * @param appkey Unique identifier/passcode of the application sending the post
072: * @param postid Unique identifier of the post to be changed
073: * @param userid Login for a Blogger user who has permission to post to the blog
074: * @param password Password for said username
075: * @param publish Ignored
076: * @throws XmlRpcException
077: * @return
078: */
079: public boolean deletePost(String appkey, String postid,
080: String userid, String password, boolean publish)
081: throws Exception {
082:
083: mLogger.debug("deletePost() Called =====[ SUPPORTED ]=====");
084: mLogger.debug(" Appkey: " + appkey);
085: mLogger.debug(" PostId: " + postid);
086: mLogger.debug(" UserId: " + userid);
087:
088: Roller roller = RollerFactory.getRoller();
089: WeblogManager weblogMgr = roller.getWeblogManager();
090: WeblogEntryData entry = weblogMgr.getWeblogEntry(postid);
091:
092: validate(entry.getWebsite().getHandle(), userid, password);
093:
094: try {
095: // delete the entry
096: weblogMgr.removeWeblogEntry(entry);
097: roller.flush();
098:
099: // notify cache
100: flushPageCache(entry.getWebsite());
101: } catch (Exception e) {
102: String msg = "ERROR in blogger.deletePost: "
103: + e.getClass().getName();
104: mLogger.error(msg, e);
105: throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
106: }
107:
108: return true;
109: }
110:
111: /**
112: * Edits the main index template of a given blog. Roller only support
113: * updating the main template, the default template of your weblog.
114: *
115: * @param appkey Unique identifier/passcode of the application sending the post
116: * @param blogid Unique identifier of the blog the post will be added to
117: * @param userid Login for a Blogger user who has permission to post to the blog
118: * @param password Password for said username
119: * @param template The text for the new template (usually mostly HTML).
120: * @param templateType Determines which of the blog's templates is to be set.
121: * @throws XmlRpcException
122: * @return
123: */
124: public boolean setTemplate(String appkey, String blogid,
125: String userid, String password, String templateData,
126: String templateType) throws Exception {
127:
128: mLogger.debug("setTemplate() Called =====[ SUPPORTED ]=====");
129: mLogger.debug(" Appkey: " + appkey);
130: mLogger.debug(" BlogId: " + blogid);
131: mLogger.debug(" UserId: " + userid);
132: mLogger.debug(" Template: " + templateData);
133: mLogger.debug(" Type: " + templateType);
134:
135: validate(blogid, userid, password);
136:
137: if (!templateType.equals("main")) {
138: throw new XmlRpcException(UNKNOWN_EXCEPTION,
139: "Roller only supports main template");
140: }
141:
142: try {
143: Roller roller = RollerFactory.getRoller();
144: UserManager userMgr = roller.getUserManager();
145:
146: WeblogTemplate page = userMgr.getPage(templateType);
147: page.setContents(templateData);
148: userMgr.savePage(page);
149: flushPageCache(page.getWebsite());
150:
151: return true;
152: } catch (RollerException e) {
153: String msg = "ERROR in BlooggerAPIHander.setTemplate";
154: mLogger.error(msg, e);
155: throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
156: }
157: }
158:
159: /**
160: * Returns the main or archive index template of a given blog
161: *
162: * @param appkey Unique identifier/passcode of the application sending the post
163: * @param blogid Unique identifier of the blog the post will be added to
164: * @param userid Login for a Blogger user who has permission to post to the blog
165: * @param password Password for said username
166: * @param templateType Determines which of the blog's templates will be returned. Currently, either "main" or "archiveIndex"
167: * @throws XmlRpcException
168: * @return
169: */
170: public String getTemplate(String appkey, String blogid,
171: String userid, String password, String templateType)
172: throws Exception {
173:
174: mLogger.debug("getTemplate() Called =====[ SUPPORTED ]=====");
175: mLogger.debug(" Appkey: " + appkey);
176: mLogger.debug(" BlogId: " + blogid);
177: mLogger.debug(" UserId: " + userid);
178: mLogger.debug(" Type: " + templateType);
179:
180: validate(blogid, userid, password);
181:
182: try {
183: Roller roller = RollerFactory.getRoller();
184: UserManager userMgr = roller.getUserManager();
185: WeblogTemplate page = userMgr.getPage(templateType);
186:
187: if (null == page) {
188: throw new XmlRpcException(UNKNOWN_EXCEPTION,
189: "Template not found");
190: } else {
191: return page.getContents();
192: }
193: } catch (Exception e) {
194: String msg = "ERROR in BlooggerAPIHander.getTemplate";
195: mLogger.error(msg, e);
196: throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
197: }
198: }
199:
200: /**
201: * Authenticates a user and returns basic user info (name, email, userid, etc.)
202: *
203: * @param appkey Unique identifier/passcode of the application sending the post
204: * @param userid Login for a Blogger user who has permission to post to the blog
205: * @param password Password for said username
206: * @throws XmlRpcException
207: * @return
208: */
209: public Object getUserInfo(String appkey, String userid,
210: String password) throws Exception {
211:
212: mLogger.debug("getUserInfo() Called =====[ SUPPORTED ]=====");
213: mLogger.debug(" Appkey: " + appkey);
214: mLogger.debug(" UserId: " + userid);
215:
216: validateUser(userid, password);
217:
218: try {
219: Roller roller = RollerFactory.getRoller();
220: UserManager userMgr = roller.getUserManager();
221: UserData user = userMgr.getUserByUserName(userid);
222:
223: // parses full name into two strings, firstname and lastname
224: String firstname = "", lastname = "";
225: StringTokenizer toker = new StringTokenizer(user
226: .getFullName());
227:
228: if (toker.hasMoreTokens()) {
229: firstname = toker.nextToken();
230: }
231:
232: while (toker.hasMoreTokens()) {
233: if (!lastname.equals("")) {
234: lastname += " ";
235: }
236: lastname += toker.nextToken();
237: }
238:
239: // populates user information to return as a result
240: Hashtable result = new Hashtable();
241: result.put("nickname", user.getUserName());
242: result.put("userid", user.getUserName());
243: result.put("email", "");
244: result.put("lastname", lastname);
245: result.put("firstname", firstname);
246:
247: return result;
248: } catch (RollerException e) {
249: String msg = "ERROR in BlooggerAPIHander.getInfo";
250: mLogger.error(msg, e);
251: throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
252: }
253: }
254:
255: /**
256: * Returns information on all the blogs a given user is a member of
257: *
258: * @param appkey Unique identifier/passcode of the application sending the post
259: * @param userid Login for a Blogger user who has permission to post to the blog
260: * @param password Password for said username
261: * @throws XmlRpcException
262: * @return
263: */
264: public Object getUsersBlogs(String appkey, String userid,
265: String password) throws Exception {
266:
267: mLogger.debug("getUsersBlogs() Called ===[ SUPPORTED ]=======");
268: mLogger.debug(" Appkey: " + appkey);
269: mLogger.debug(" UserId: " + userid);
270:
271: Vector result = new Vector();
272: if (validateUser(userid, password)) {
273: try {
274: String contextUrl = RollerRuntimeConfig
275: .getAbsoluteContextURL();
276:
277: UserManager umgr = RollerFactory.getRoller()
278: .getUserManager();
279: UserData user = umgr.getUserByUserName(userid);
280: // get list of user's enabled websites
281: List websites = umgr.getWebsites(user, Boolean.TRUE,
282: null, null, null, 0, -1);
283: Iterator iter = websites.iterator();
284: while (iter.hasNext()) {
285: WebsiteData website = (WebsiteData) iter.next();
286: Hashtable blog = new Hashtable(3);
287: blog.put("url", website.getURL());
288: blog.put("blogid", website.getHandle());
289: blog.put("blogName", website.getName());
290: result.add(blog);
291: }
292: } catch (Exception e) {
293: String msg = "ERROR in BlooggerAPIHander.getUsersBlogs";
294: mLogger.error(msg, e);
295: throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
296: }
297: }
298: return result;
299: }
300:
301: /**
302: * Edits a given post. Optionally, will publish the blog after making the edit
303: *
304: * @param appkey Unique identifier/passcode of the application sending the post
305: * @param postid Unique identifier of the post to be changed
306: * @param userid Login for a Blogger user who has permission to post to the blog
307: * @param password Password for said username
308: * @param content Contents of the post
309: * @param publish If true, the blog will be published immediately after the post is made
310: * @throws XmlRpcException
311: * @return
312: */
313: public boolean editPost(String appkey, String postid,
314: String userid, String password, String content,
315: boolean publish) throws Exception {
316:
317: mLogger.debug("editPost() Called ========[ SUPPORTED ]=====");
318: mLogger.debug(" Appkey: " + appkey);
319: mLogger.debug(" PostId: " + postid);
320: mLogger.debug(" UserId: " + userid);
321: mLogger.debug(" Publish: " + publish);
322: mLogger.debug(" Content:\n " + content);
323:
324: if (validateUser(userid, password)) {
325: try {
326: Timestamp current = new Timestamp(System
327: .currentTimeMillis());
328:
329: Roller roller = RollerFactory.getRoller();
330: WeblogManager weblogMgr = roller.getWeblogManager();
331: WeblogEntryData entry = weblogMgr
332: .getWeblogEntry(postid);
333: entry.setText(content);
334: entry.setUpdateTime(current);
335: if (Boolean.valueOf(publish).booleanValue()) {
336: entry.setStatus(WeblogEntryData.PUBLISHED);
337: } else {
338: entry.setStatus(WeblogEntryData.DRAFT);
339: }
340:
341: // save the entry
342: weblogMgr.saveWeblogEntry(entry);
343: roller.flush();
344:
345: // notify cache
346: flushPageCache(entry.getWebsite());
347:
348: return true;
349: } catch (Exception e) {
350: String msg = "ERROR in BlooggerAPIHander.editPost";
351: mLogger.error(msg, e);
352: throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
353: }
354: }
355: return false;
356: }
357:
358: /**
359: * Makes a new post to a designated blog. Optionally, will publish the blog after making the post
360: *
361: * @param appkey Unique identifier/passcode of the application sending the post
362: * @param blogid Unique identifier of the blog the post will be added to
363: * @param userid Login for a Blogger user who has permission to post to the blog
364: * @param password Password for said username
365: * @param content Contents of the post
366: * @param publish If true, the blog will be published immediately after the post is made
367: * @throws XmlRpcException
368: * @return
369: */
370: public String newPost(String appkey, String blogid, String userid,
371: String password, String content, boolean publish)
372: throws Exception {
373:
374: mLogger.debug("newPost() Called ===========[ SUPPORTED ]=====");
375: mLogger.debug(" Appkey: " + appkey);
376: mLogger.debug(" BlogId: " + blogid);
377: mLogger.debug(" UserId: " + userid);
378: mLogger.debug(" Publish: " + publish);
379: mLogger.debug(" Content:\n " + content);
380:
381: WebsiteData website = validate(blogid, userid, password);
382:
383: // extract the title from the content
384: String title = "";
385:
386: if (content.indexOf("<title>") != -1) {
387: title = content.substring(content.indexOf("<title>") + 7,
388: content.indexOf("</title>"));
389: content = StringUtils.replace(content, "<title>" + title
390: + "</title>", "");
391: }
392: if (StringUtils.isEmpty(title)) {
393: title = Utilities.truncateNicely(content, 15, 15, "...");
394: }
395:
396: try {
397: Roller roller = RollerFactory.getRoller();
398: WeblogManager weblogMgr = roller.getWeblogManager();
399:
400: Timestamp current = new Timestamp(System
401: .currentTimeMillis());
402:
403: WeblogEntryData entry = new WeblogEntryData();
404: entry.setTitle(title);
405: entry.setText(content);
406: entry.setPubTime(current);
407: entry.setUpdateTime(current);
408: UserData user = roller.getUserManager().getUserByUserName(
409: userid);
410: entry.setCreator(user);
411: entry.setWebsite(website);
412: entry.setCategory(website.getBloggerCategory());
413: if (Boolean.valueOf(publish).booleanValue()) {
414: entry.setStatus(WeblogEntryData.PUBLISHED);
415: } else {
416: entry.setStatus(WeblogEntryData.DRAFT);
417: }
418:
419: // save the entry
420: weblogMgr.saveWeblogEntry(entry);
421: roller.flush();
422:
423: // notify cache
424: flushPageCache(entry.getWebsite());
425:
426: return entry.getId();
427: } catch (Exception e) {
428: String msg = "ERROR in BlooggerAPIHander.newPost";
429: mLogger.error(msg, e);
430: throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
431: }
432: }
433:
434: /**
435: * This method was added to the Blogger 1.0 API via an Email from Evan
436: * Williams to the Yahoo Group bloggerDev, see the email message for details -
437: * http://groups.yahoo.com/group/bloggerDev/message/225
438: *
439: * @param appkey Unique identifier/passcode of the application sending the post
440: * @param blogid Unique identifier of the blog the post will be added to
441: * @param userid Login for a Blogger user who has permission to post to the blog
442: * @param password Password for said username
443: * @param numposts Number of Posts to Retrieve
444: * @throws XmlRpcException
445: * @return Vector of Hashtables, each containing dateCreated, userid, postid, content
446: */
447: public Object getRecentPosts(String appkey, String blogid,
448: String userid, String password, int numposts)
449: throws Exception {
450:
451: mLogger
452: .debug("getRecentPosts() Called ===========[ SUPPORTED ]=====");
453: mLogger.debug(" Appkey: " + appkey);
454: mLogger.debug(" BlogId: " + blogid);
455: mLogger.debug(" UserId: " + userid);
456: mLogger.debug(" Number: " + numposts);
457:
458: WebsiteData website = validate(blogid, userid, password);
459:
460: try {
461: Vector results = new Vector();
462:
463: Roller roller = RollerFactory.getRoller();
464: WeblogManager weblogMgr = roller.getWeblogManager();
465: if (website != null) {
466: Map entries = weblogMgr.getWeblogEntryObjectMap(
467: website, // website
468: null, // startDate
469: new Date(), // endDate
470: null, // catName
471: null, // tags
472: null, null, 0, -1);
473:
474: Iterator iter = entries.values().iterator();
475: while (iter.hasNext()) {
476: ArrayList list = (ArrayList) iter.next();
477: Iterator i = list.iterator();
478: while (i.hasNext()) {
479: WeblogEntryData entry = (WeblogEntryData) i
480: .next();
481: Hashtable result = new Hashtable();
482: if (entry.getPubTime() != null) {
483: result.put("dateCreated", entry
484: .getPubTime());
485: }
486: result.put("userid", userid);
487: result.put("postid", entry.getId());
488: result.put("content", entry.getText());
489: results.add(result);
490: }
491: }
492: }
493: return results;
494: } catch (Exception e) {
495: String msg = "ERROR in BlooggerAPIHander.getRecentPosts";
496: mLogger.error(msg, e);
497: throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
498: }
499: }
500:
501: }
|