You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2006/05/05 19:49:08 UTC

svn commit: r400121 [4/4] - in /incubator/roller/trunk: ./ nbproject/ src/org/apache/roller/presentation/webservices/ src/org/apache/roller/util/ src/org/apache/roller/webservices/ src/org/apache/roller/webservices/adminapi/ src/org/apache/roller/webse...

Added: incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/BloggerAPIHandler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/BloggerAPIHandler.java?rev=400121&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/BloggerAPIHandler.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/BloggerAPIHandler.java Fri May  5 10:49:04 2006
@@ -0,0 +1,504 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+*  contributor license agreements.  The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+
+package org.apache.roller.webservices.xmlrpc;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.roller.RollerException;
+import org.apache.roller.model.Roller;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.model.UserManager;
+import org.apache.roller.model.WeblogManager;
+import org.apache.roller.pojos.WeblogTemplate;
+import org.apache.roller.pojos.UserData;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.presentation.RollerContext;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.util.Utilities;
+
+
+/**
+ * Roller XML-RPC Handler for the Blogger v1 API.
+ *
+ * Blogger API spec can be found at http://plant.blogger.com/api/index.html
+ * See also http://xmlrpc.free-conversant.com/docs/bloggerAPI
+ *
+ * @author David M Johnson
+ */
+public class BloggerAPIHandler extends BaseAPIHandler {
+    
+    static final long serialVersionUID = 2398898776655115019L;
+    
+    private static Log mLogger = LogFactory.getLog(BloggerAPIHandler.class);
+    
+    public BloggerAPIHandler() {
+        super();
+    }
+    
+    
+    /**
+     * Delete a Post
+     *
+     * @param appkey Unique identifier/passcode of the application sending the post
+     * @param postid Unique identifier of the post to be changed
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @param publish Ignored
+     * @throws XmlRpcException
+     * @return
+     */
+    public boolean deletePost(String appkey, String postid, String userid,
+                            String password, boolean publish) throws Exception {
+        
+        mLogger.debug("deletePost() Called =====[ SUPPORTED ]=====");
+        mLogger.debug("     Appkey: " + appkey);
+        mLogger.debug("     PostId: " + postid);
+        mLogger.debug("     UserId: " + userid);
+        
+        Roller roller = RollerFactory.getRoller();
+        WeblogManager weblogMgr = roller.getWeblogManager();
+        WeblogEntryData entry = weblogMgr.getWeblogEntry(postid);
+        
+        validate(entry.getWebsite().getHandle(), userid, password);
+        
+        try {
+            // delete the entry
+            weblogMgr.removeWeblogEntry(entry);
+            roller.flush();
+            
+            // notify cache
+            flushPageCache(entry.getWebsite());
+        } catch (Exception e) {
+            String msg = "ERROR in blogger.deletePost: "+e.getClass().getName();
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+        
+        return true;
+    }
+    
+    
+    /**
+     * Edits the main index template of a given blog. Roller only support
+     * updating the main template, the default template of your weblog.
+     *
+     * @param appkey Unique identifier/passcode of the application sending the post
+     * @param blogid Unique identifier of the blog the post will be added to
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @param template The text for the new template (usually mostly HTML).
+     * @param templateType Determines which of the blog's templates is to be set.
+     * @throws XmlRpcException
+     * @return
+     */
+    public boolean setTemplate(String appkey, String blogid, String userid,
+                                String password, String templateData,
+                                String templateType) throws Exception {
+        
+        mLogger.debug("setTemplate() Called =====[ SUPPORTED ]=====");
+        mLogger.debug("     Appkey: " + appkey);
+        mLogger.debug("     BlogId: " + blogid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("   Template: " + templateData);
+        mLogger.debug("       Type: " + templateType);
+        
+        validate(blogid, userid, password);
+        
+        if (! templateType.equals("main")) {
+            throw new XmlRpcException(
+                    UNKNOWN_EXCEPTION, "Roller only supports main template");
+        }
+        
+        try {
+            Roller roller = RollerFactory.getRoller();
+            UserManager userMgr = roller.getUserManager();
+            
+            WeblogTemplate page = userMgr.getPage(templateType);
+            page.setContents(templateData);
+            userMgr.savePage(page);
+            flushPageCache(page.getWebsite());
+            
+            return true;
+        } catch (RollerException e) {
+            String msg = "ERROR in BlooggerAPIHander.setTemplate";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION,msg);
+        }
+    }
+    
+    
+    /**
+     * Returns the main or archive index template of a given blog
+     *
+     * @param appkey Unique identifier/passcode of the application sending the post
+     * @param blogid Unique identifier of the blog the post will be added to
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @param templateType Determines which of the blog's templates will be returned. Currently, either "main" or "archiveIndex"
+     * @throws XmlRpcException
+     * @return
+     */
+    public String getTemplate(String appkey, String blogid, String userid,
+                                String password, String templateType)
+            throws Exception {
+        
+        mLogger.debug("getTemplate() Called =====[ SUPPORTED ]=====");
+        mLogger.debug("     Appkey: " + appkey);
+        mLogger.debug("     BlogId: " + blogid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("       Type: " + templateType);
+        
+        validate(blogid, userid,password);
+        
+        try {
+            Roller roller = RollerFactory.getRoller();
+            UserManager userMgr = roller.getUserManager();
+            WeblogTemplate page = userMgr.getPage(templateType);
+            
+            if ( null == page ) {
+                throw new XmlRpcException(UNKNOWN_EXCEPTION,"Template not found");
+            } else {
+                return page.getContents();
+            }
+        } catch (Exception e) {
+            String msg = "ERROR in BlooggerAPIHander.getTemplate";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION,msg);
+        }
+    }
+    
+    
+    /**
+     * Authenticates a user and returns basic user info (name, email, userid, etc.)
+     *
+     * @param appkey Unique identifier/passcode of the application sending the post
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @throws XmlRpcException
+     * @return
+     */
+    public Object getUserInfo(String appkey, String userid, String password)
+            throws Exception {
+        
+        mLogger.debug("getUserInfo() Called =====[ SUPPORTED ]=====");
+        mLogger.debug("     Appkey: " + appkey);
+        mLogger.debug("     UserId: " + userid);
+        
+        validateUser(userid, password);
+        
+        try {
+            Roller roller = RollerFactory.getRoller();
+            UserManager userMgr = roller.getUserManager();
+            UserData user = userMgr.getUserByUsername(userid);
+            
+            // parses full name into two strings, firstname and lastname
+            String firstname = "", lastname = "";
+            StringTokenizer toker = new StringTokenizer(user.getFullName());
+            
+            if (toker.hasMoreTokens()) {
+                firstname = toker.nextToken();
+            }
+            
+            while (toker.hasMoreTokens()) {
+                if ( !lastname.equals("") ) {
+                    lastname += " ";
+                }
+                lastname += toker.nextToken();
+            }
+            
+            RollerRequest rreq = RollerRequest.getRollerRequest();
+            HttpServletRequest req = rreq.getRequest();
+            String contextUrl =
+                    RollerContext.getRollerContext().getAbsoluteContextUrl(req);
+            
+            // populates user information to return as a result
+            Hashtable result = new Hashtable();
+            result.put("nickname", user.getUserName());
+            result.put("userid", user.getUserName());
+            result.put("url", contextUrl+"/page/"+userid);
+            result.put("email", "");
+            result.put("lastname", lastname);
+            result.put("firstname", firstname);
+            
+            return result;
+        } catch (RollerException e) {
+            String msg = "ERROR in BlooggerAPIHander.getInfo";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION,msg);
+        }
+    }
+    
+    
+    /**
+     * Returns information on all the blogs a given user is a member of
+     *
+     * @param appkey Unique identifier/passcode of the application sending the post
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @throws XmlRpcException
+     * @return
+     */
+    public Object getUsersBlogs(String appkey, String userid, String password)
+            throws Exception {
+        
+        mLogger.debug("getUsersBlogs() Called ===[ SUPPORTED ]=======");
+        mLogger.debug("     Appkey: " + appkey);
+        mLogger.debug("     UserId: " + userid);
+        
+        Vector result = new Vector();
+        if (validateUser(userid, password)) {
+            try {
+                RollerRequest rreq = RollerRequest.getRollerRequest();
+                HttpServletRequest req = rreq.getRequest();
+                String contextUrl =
+                        RollerContext.getRollerContext().getAbsoluteContextUrl(req);
+                
+                UserManager umgr = RollerFactory.getRoller().getUserManager();
+                UserData user = umgr.getUserByUsername(userid);
+                // get list of user's enabled websites
+                List websites = umgr.getWebsites(user, Boolean.TRUE, null);
+                Iterator iter = websites.iterator();
+                while (iter.hasNext()) {
+                    WebsiteData website = (WebsiteData)iter.next();
+                    Hashtable blog = new Hashtable(3);
+                    blog.put("url", contextUrl+"/page/"+website.getHandle());
+                    blog.put("blogid", website.getHandle());
+                    blog.put("blogName", website.getName());
+                    result.add(blog);
+                }
+            } catch (Exception e) {
+                String msg = "ERROR in BlooggerAPIHander.getUsersBlogs";
+                mLogger.error(msg,e);
+                throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+            }
+        }
+        return result;
+    }
+    
+    
+    /**
+     * Edits a given post. Optionally, will publish the blog after making the edit
+     *
+     * @param appkey Unique identifier/passcode of the application sending the post
+     * @param postid Unique identifier of the post to be changed
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @param content Contents of the post
+     * @param publish If true, the blog will be published immediately after the post is made
+     * @throws XmlRpcException
+     * @return
+     */
+    public boolean editPost(String appkey, String postid, String userid,
+                            String password, String content, boolean publish)
+            throws Exception {
+        
+        mLogger.debug("editPost() Called ========[ SUPPORTED ]=====");
+        mLogger.debug("     Appkey: " + appkey);
+        mLogger.debug("     PostId: " + postid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("    Publish: " + publish);
+        mLogger.debug("     Content:\n " + content);
+        
+        if (validateUser(userid, password)) {
+            try {
+                Timestamp current = new Timestamp(System.currentTimeMillis());
+                
+                Roller roller = RollerFactory.getRoller();
+                WeblogManager weblogMgr = roller.getWeblogManager();
+                WeblogEntryData entry = weblogMgr.getWeblogEntry(postid);
+                entry.setText(content);
+                entry.setUpdateTime(current);
+                if (Boolean.valueOf(publish).booleanValue()) {
+                    entry.setStatus(WeblogEntryData.PUBLISHED);
+                } else {
+                    entry.setStatus(WeblogEntryData.DRAFT);
+                }
+                
+                // save the entry
+                weblogMgr.saveWeblogEntry(entry);
+                roller.flush();
+                
+                // notify cache
+                flushPageCache(entry.getWebsite());
+                
+                return true;
+            } catch (Exception e) {
+                String msg = "ERROR in BlooggerAPIHander.editPost";
+                mLogger.error(msg,e);
+                throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+            }
+        }
+        return false;
+    }
+    
+    
+    /**
+     * Makes a new post to a designated blog. Optionally, will publish the blog after making the post
+     *
+     * @param appkey Unique identifier/passcode of the application sending the post
+     * @param blogid Unique identifier of the blog the post will be added to
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @param content Contents of the post
+     * @param publish If true, the blog will be published immediately after the post is made
+     * @throws XmlRpcException
+     * @return
+     */
+    public String newPost(String appkey, String blogid, String userid,
+                            String password, String content, boolean publish)
+            throws Exception {
+        
+        mLogger.debug("newPost() Called ===========[ SUPPORTED ]=====");
+        mLogger.debug("     Appkey: " + appkey);
+        mLogger.debug("     BlogId: " + blogid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("    Publish: " + publish);
+        mLogger.debug("    Content:\n " + content);
+        
+        WebsiteData website = validate(blogid, userid, password);
+        
+        // extract the title from the content
+        String title = "";
+        
+        if (content.indexOf("<title>") != -1) {
+            title =
+                    content.substring(content.indexOf("<title>") + 7,
+                    content.indexOf("</title>"));
+            content = StringUtils.replace(content, "<title>"+title+"</title>", "");
+        }
+        if (Utilities.isEmpty(title)) { 
+            title = Utilities.truncateNicely(content, 15, 15, "...");
+        }
+        
+        try {
+            RollerRequest rreq = RollerRequest.getRollerRequest();
+            Roller roller = RollerFactory.getRoller();
+            WeblogManager weblogMgr = roller.getWeblogManager();
+            
+            Timestamp current = new Timestamp(System.currentTimeMillis());
+            
+            WeblogEntryData entry = new WeblogEntryData();
+            entry.setTitle(title);
+            entry.setText(content);
+            entry.setPubTime(current);
+            entry.setUpdateTime(current);
+            UserData user = roller.getUserManager().getUserByUsername(userid);
+            entry.setCreator(user);
+            entry.setWebsite(website);
+            entry.setCategory(website.getBloggerCategory());
+            if (Boolean.valueOf(publish).booleanValue()) {
+                entry.setStatus(WeblogEntryData.PUBLISHED);
+            } else {
+                entry.setStatus(WeblogEntryData.DRAFT);
+            }
+            
+            // save the entry
+            weblogMgr.saveWeblogEntry(entry);
+            roller.flush();
+            
+            // notify cache
+            flushPageCache(entry.getWebsite());
+
+            return entry.getId();
+        } catch (Exception e) {
+            String msg = "ERROR in BlooggerAPIHander.newPost";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+    }
+    
+    
+    /**
+     * This method was added to the Blogger 1.0 API via an Email from Evan
+     * Williams to the Yahoo Group bloggerDev, see the email message for details -
+     * http://groups.yahoo.com/group/bloggerDev/message/225
+     *
+     * @param appkey Unique identifier/passcode of the application sending the post
+     * @param blogid Unique identifier of the blog the post will be added to
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @param numposts Number of Posts to Retrieve
+     * @throws XmlRpcException
+     * @return Vector of Hashtables, each containing dateCreated, userid, postid, content
+     */
+    public Object getRecentPosts(String appkey, String blogid, String userid, 
+                                    String password, int numposts)
+            throws Exception {
+        
+        mLogger.debug("getRecentPosts() Called ===========[ SUPPORTED ]=====");
+        mLogger.debug("     Appkey: " + appkey);
+        mLogger.debug("     BlogId: " + blogid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("     Number: " + numposts);
+        
+        WebsiteData website = validate(blogid, userid,password);
+        
+        try {
+            Vector results = new Vector();
+            
+            Roller roller = RollerFactory.getRoller();
+            WeblogManager weblogMgr = roller.getWeblogManager();
+            if (website != null) {
+                Map entries = weblogMgr.getWeblogEntryObjectMap(
+                        website,                // userName
+                        null,                   // startDate
+                        new Date(),             // endDate
+                        null,                   // catName
+                        null,      // status
+                        new Integer(numposts)); // maxEntries
+                
+                Iterator iter = entries.values().iterator();
+                while (iter.hasNext()) {
+                    ArrayList list = (ArrayList) iter.next();
+                    Iterator i = list.iterator();
+                    while (i.hasNext()) {
+                        WeblogEntryData entry = (WeblogEntryData) i.next();
+                        Hashtable result = new Hashtable();
+                        if (entry.getPubTime() != null) {
+                            result.put("dateCreated", entry.getPubTime());
+                        } 
+                        result.put("userid", userid);
+                        result.put("postid", entry.getId());
+                        result.put("content", entry.getText());
+                        results.add(result);
+                    }
+                }
+            }
+            return results;
+        } catch (Exception e) {
+            String msg = "ERROR in BlooggerAPIHander.getRecentPosts";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+    }
+    
+}

Added: incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/MetaWeblogAPIHandler.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/MetaWeblogAPIHandler.java?rev=400121&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/MetaWeblogAPIHandler.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/MetaWeblogAPIHandler.java Fri May  5 10:49:04 2006
@@ -0,0 +1,491 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+*  contributor license agreements.  The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+
+package org.apache.roller.webservices.xmlrpc;
+
+import java.io.ByteArrayInputStream;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts.util.RequestUtils;
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.roller.RollerException;
+import org.apache.roller.model.FileManager;
+import org.apache.roller.model.Roller;
+import org.apache.roller.model.RollerFactory;
+import org.apache.roller.model.WeblogManager;
+import org.apache.roller.pojos.UserData;
+import org.apache.roller.pojos.WeblogCategoryData;
+import org.apache.roller.pojos.WeblogEntryData;
+import org.apache.roller.pojos.WebsiteData;
+import org.apache.roller.presentation.RollerContext;
+import org.apache.roller.presentation.RollerRequest;
+import org.apache.roller.util.RollerMessages;
+import org.apache.roller.util.Utilities;
+
+
+/**
+ * Roller XML-RPC Handler for the MetaWeblog API.
+ *
+ * MetaWeblog API spec can be found at http://www.xmlrpc.com/metaWeblogApi
+ *
+ * @author David M Johnson
+ */
+public class MetaWeblogAPIHandler extends BloggerAPIHandler {
+    
+    static final long serialVersionUID = -1364456614935668629L;
+    
+    private static Log mLogger = LogFactory.getLog(MetaWeblogAPIHandler.class);
+    
+    public MetaWeblogAPIHandler() {
+        super();
+    }
+    
+    
+    /**
+     * Authenticates a user and returns the categories available in the website
+     *
+     * @param blogid Dummy Value for Roller
+     * @param userid Login for a MetaWeblog user who has permission to post to the blog
+     * @param password Password for said username
+     * @throws Exception
+     * @return
+     */
+    public Object getCategories(String blogid, String userid, String password)
+            throws Exception {
+        
+        mLogger.debug("getCategories() Called =====[ SUPPORTED ]=====");
+        mLogger.debug("     BlogId: " + blogid);
+        mLogger.debug("     UserId: " + userid);
+        
+        WebsiteData website = validate(blogid, userid,password);
+        RollerRequest rreq = RollerRequest.getRollerRequest();
+        Roller roller = RollerFactory.getRoller();
+        try {
+            Hashtable result = new Hashtable();
+            WeblogManager weblogMgr = roller.getWeblogManager();
+            List cats = weblogMgr.getWeblogCategories(website, false);
+            for (Iterator wbcItr = cats.iterator(); wbcItr.hasNext();) {
+                WeblogCategoryData category = (WeblogCategoryData) wbcItr.next();
+                result.put(category.getPath(),
+                        createCategoryStruct(category, userid));
+            }
+            return result;
+        } catch (Exception e) {
+            String msg = "ERROR in MetaWeblogAPIHandler.getCategories";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+    }
+    
+    
+    /**
+     * Edits a given post. Optionally, will publish the blog after making the edit
+     *
+     * @param postid Unique identifier of the post to be changed
+     * @param userid Login for a MetaWeblog user who has permission to post to the blog
+     * @param password Password for said username
+     * @param struct Contents of the post
+     * @param publish If true, the blog will be published immediately after the post is made
+     * @throws org.apache.xmlrpc.XmlRpcException
+     * @return
+     */
+    public boolean editPost(String postid, String userid, String password,
+                            Hashtable struct, int publish) throws Exception {
+        
+        return editPost(postid, userid, password, struct, publish > 0);
+    }
+    
+    
+    public boolean editPost(String postid, String userid, String password,
+            Hashtable struct, boolean publish) throws Exception {
+        
+        mLogger.debug("editPost() Called ========[ SUPPORTED ]=====");
+        mLogger.debug("     PostId: " + postid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("    Publish: " + publish);
+        
+        Roller roller = RollerFactory.getRoller();
+        WeblogManager weblogMgr = roller.getWeblogManager();
+        WeblogEntryData entry = weblogMgr.getWeblogEntry(postid);
+        
+        validate(entry.getWebsite().getHandle(), userid,password);
+        
+        Hashtable postcontent = struct;
+        String description = (String)postcontent.get("description");
+        String title = (String)postcontent.get("title");
+        if (title == null) title = "";
+        
+        Date dateCreated = (Date)postcontent.get("dateCreated");
+        if (dateCreated == null) dateCreated = (Date)postcontent.get("pubDate");
+        
+        String cat = null;
+        if ( postcontent.get("categories") != null ) {
+            Vector cats = (Vector)postcontent.get("categories");
+            cat = (String)cats.elementAt(0);
+        }
+        mLogger.debug("      Title: " + title);
+        mLogger.debug("   Category: " + cat);
+        
+        try {
+            
+            Timestamp current =
+                    new Timestamp(System.currentTimeMillis());
+            
+            if ( !title.equals("") ) entry.setTitle(title);
+            entry.setText(description);
+            entry.setUpdateTime(current);
+            if (Boolean.valueOf(publish).booleanValue()) {
+                entry.setStatus(WeblogEntryData.PUBLISHED);
+            } else {
+                entry.setStatus(WeblogEntryData.DRAFT);
+            }
+            if (dateCreated != null) {
+                entry.setPubTime(new Timestamp(dateCreated.getTime()));
+            }
+            
+            if ( cat != null ) {
+                // Use first category specified by request
+                WeblogCategoryData cd =
+                        weblogMgr.getWeblogCategoryByPath(entry.getWebsite(), cat);
+                entry.setCategory(cd);
+            }
+            
+            // save the entry
+            weblogMgr.saveWeblogEntry(entry);
+            roller.flush();
+            
+            // notify cache
+            flushPageCache(entry.getWebsite());
+            
+            // TODO: Roller timestamps need better than 1 second accuracy
+            // Until then, we can't allow more than one post per second
+            Thread.sleep(1000);
+            
+            return true;
+        } catch (Exception e) {
+            String msg = "ERROR in MetaWeblogAPIHandler.editPost";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+    }
+    
+    
+    /**
+     * Makes a new post to a designated blog. Optionally, will publish the blog after making the post
+     *
+     * @param blogid Unique identifier of the blog the post will be added to
+     * @param userid Login for a MetaWeblog user who has permission to post to the blog
+     * @param password Password for said username
+     * @param struct Contents of the post
+     * @param publish If true, the blog will be published immediately after the post is made
+     * @throws org.apache.xmlrpc.XmlRpcException
+     * @return
+     */
+    public String newPost(String blogid, String userid, String password, 
+                            Hashtable struct, int publish) throws Exception {
+        
+        return newPost(blogid, userid, password, struct, publish > 0);
+    }
+    
+    
+    public String newPost(String blogid, String userid, String password, 
+                            Hashtable struct, boolean publish) throws Exception {
+        
+        mLogger.debug("newPost() Called ===========[ SUPPORTED ]=====");
+        mLogger.debug("     BlogId: " + blogid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("    Publish: " + publish);
+        
+        WebsiteData website = validate(blogid, userid, password);
+        
+        Hashtable postcontent = struct;
+        String description = (String)postcontent.get("description");
+        String title = (String)postcontent.get("title");
+        if (Utilities.isEmpty(title) && Utilities.isEmpty(description)) {
+            throw new XmlRpcException(
+              BLOGGERAPI_INCOMPLETE_POST, "Must specify title or description");
+        }
+        if (Utilities.isEmpty(title)) { 
+            title = Utilities.truncateNicely(description, 15, 15, "...");
+        }
+        
+        Date dateCreated = (Date)postcontent.get("dateCreated");
+        if (dateCreated == null) dateCreated = (Date)postcontent.get("pubDate");
+        if (dateCreated == null) dateCreated = new Date();
+        mLogger.debug("      Title: " + title);
+        
+        try {
+            Roller roller = RollerFactory.getRoller();
+            WeblogManager weblogMgr = roller.getWeblogManager();
+            UserData user = roller.getUserManager().getUserByUsername(userid);
+            Timestamp current =
+                    new Timestamp(System.currentTimeMillis());
+            
+            WeblogEntryData entry = new WeblogEntryData();
+            entry.setTitle(title);
+            entry.setText(description);
+            entry.setPubTime(new Timestamp(dateCreated.getTime()));
+            entry.setUpdateTime(current);
+            entry.setWebsite(website);
+            entry.setCreator(user);
+            if (Boolean.valueOf(publish).booleanValue()) {
+                entry.setStatus(WeblogEntryData.PUBLISHED);
+            } else {
+                entry.setStatus(WeblogEntryData.DRAFT);
+            }
+                        
+            // MetaWeblog supports multiple cats, Roller supports one/entry
+            // so here we take accept the first category that exists
+            WeblogCategoryData rollerCat = null;
+            if ( postcontent.get("categories") != null ) {
+                Vector cats = (Vector)postcontent.get("categories");
+                if (cats != null && cats.size() > 0) {
+                    for (int i=0; i<cats.size(); i++) {
+                        String cat = (String)cats.get(i);
+                        rollerCat = weblogMgr.getWeblogCategoryByPath(website, cat);
+                        if (rollerCat != null) {
+                            entry.setCategory(rollerCat);
+                            break;
+                        }
+                    }
+                }
+            }
+            if (rollerCat == null) { 
+                // or we fall back to the default Blogger API category
+                entry.setCategory(website.getBloggerCategory());
+            }
+            
+            // save the entry
+            weblogMgr.saveWeblogEntry(entry);
+            roller.flush();
+            
+            // notify cache
+            flushPageCache(entry.getWebsite());
+            
+            // TODO: Roller timestamps need better than 1 second accuracy
+            // Until then, we can't allow more than one post per second
+            Thread.sleep(1000);
+            
+            return entry.getId();
+        } catch (Exception e) {
+            String msg = "ERROR in MetaWeblogAPIHandler.newPost";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+    }
+    
+    
+    /**
+     *
+     * @param postid
+     * @param userid
+     * @param password
+     * @return
+     * @throws Exception
+     */
+    public Object getPost(String postid, String userid, String password)
+            throws Exception {
+        
+        mLogger.debug("getPost() Called =========[ SUPPORTED ]=====");
+        mLogger.debug("     PostId: " + postid);
+        mLogger.debug("     UserId: " + userid);
+        
+        Roller roller = RollerFactory.getRoller();
+        WeblogManager weblogMgr = roller.getWeblogManager();
+        WeblogEntryData entry = weblogMgr.getWeblogEntry(postid);
+        
+        validate(entry.getWebsite().getHandle(), userid,password);
+        
+        try {
+            return createPostStruct(entry, userid);
+        } catch (Exception e) {
+            String msg = "ERROR in MetaWeblogAPIHandler.getPost";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+    }
+    
+    
+    /**
+     * Allows user to post a binary object, a file, to Roller. If the file is
+     * allowed by the RollerConfig file-upload settings, then the file will be
+     * placed in the user's upload diretory.
+     */
+    public Object newMediaObject(String blogid, String userid, String password, 
+                                    Hashtable struct) throws Exception {
+        
+        mLogger.debug("newMediaObject() Called =[ SUPPORTED ]=====");
+        mLogger.debug("     BlogId: " + blogid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("   Password: *********");
+        
+        WebsiteData website = validate(blogid, userid, password);
+        try {
+            String name = (String) struct.get("name");
+            name = name.replaceAll("/","_");
+            String type = (String) struct.get("type");
+            mLogger.debug("newMediaObject name: " + name);
+            mLogger.debug("newMediaObject type: " + type);
+            
+            byte[] bits = (byte[]) struct.get("bits");
+            
+            Roller roller = RollerFactory.getRoller();
+            FileManager fmgr = roller.getFileManager();
+            RollerMessages msgs = new RollerMessages();
+            
+            // If save is allowed by Roller system-wide policies
+            if (fmgr.canSave(website.getHandle(), name, bits.length, msgs)) {
+                // Then save the file
+                fmgr.saveFile(
+                        website.getHandle(), name, bits.length, new ByteArrayInputStream(bits));
+                
+                RollerRequest rreq = RollerRequest.getRollerRequest();
+                HttpServletRequest request = rreq.getRequest();
+                
+                // TODO: build URL to uploaded file should be done in FileManager
+                String uploadPath = RollerFactory.getRoller().getFileManager().getUploadUrl();
+                uploadPath += "/" + website.getHandle() + "/" + name;
+                String fileLink = RequestUtils.printableURL(
+                        RequestUtils.absoluteURL(request, uploadPath));
+                
+                Hashtable returnStruct = new Hashtable(1);
+                returnStruct.put("url", fileLink);
+                return returnStruct;
+            }
+            throw new XmlRpcException(UPLOAD_DENIED_EXCEPTION,
+                    "File upload denied because:" + msgs.toString());
+        } catch (RollerException e) {
+            String msg = "ERROR in BlooggerAPIHander.newMediaObject";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+    }
+    
+    
+    /**
+     * Get a list of recent posts for a category
+     *
+     * @param blogid Unique identifier of the blog the post will be added to
+     * @param userid Login for a Blogger user who has permission to post to the blog
+     * @param password Password for said username
+     * @param numposts Number of Posts to Retrieve
+     * @throws XmlRpcException
+     * @return
+     */
+    public Object getRecentPosts(String blogid, String userid, String password, 
+                                    int numposts) throws Exception {
+        
+        mLogger.debug("getRecentPosts() Called ===========[ SUPPORTED ]=====");
+        mLogger.debug("     BlogId: " + blogid);
+        mLogger.debug("     UserId: " + userid);
+        mLogger.debug("     Number: " + numposts);
+        
+        WebsiteData website = validate(blogid, userid,password);
+        
+        try {
+            Vector results = new Vector();
+            
+            Roller roller = RollerFactory.getRoller();
+            WeblogManager weblogMgr = roller.getWeblogManager();
+            if (website != null) {
+                List entries = weblogMgr.getWeblogEntries(
+                    website,           // website
+                    null,              // startDate
+                    null,              // endDate
+                    null,              // catName
+                    null,              // status
+                    "updateTime",      // sortby
+                    new Integer(numposts));  // maxEntries
+                
+                Iterator iter = entries.iterator();
+                while (iter.hasNext()) {
+                     WeblogEntryData entry = (WeblogEntryData)iter.next();
+                     results.addElement(createPostStruct(entry, userid));
+                }
+            }
+            return results;
+            
+        } catch (Exception e) {
+            String msg = "ERROR in BlooggerAPIHander.getRecentPosts";
+            mLogger.error(msg,e);
+            throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
+        }
+    }
+    
+    
+    private Hashtable createPostStruct(WeblogEntryData entry, String userid) {
+        
+        RollerRequest rreq = RollerRequest.getRollerRequest();
+        HttpServletRequest request = rreq.getRequest();
+        RollerContext rollerCtx = RollerContext.getRollerContext();
+        String permalink =
+                rollerCtx.getAbsoluteContextUrl(request) + entry.getPermaLink();
+        
+        Hashtable struct = new Hashtable();
+        struct.put("title", entry.getTitle());
+        if (entry.getLink() != null) {
+            struct.put("link", Utilities.escapeHTML(entry.getLink()));
+        }
+        struct.put("description", entry.getText());
+        if (entry.getPubTime() != null) {
+            struct.put("pubDate", entry.getPubTime());
+            struct.put("dateCreated", entry.getPubTime());
+        }
+        struct.put("guid", Utilities.escapeHTML(permalink));
+        struct.put("permaLink", Utilities.escapeHTML(permalink));
+        struct.put("postid", entry.getId());
+        struct.put("userid", userid);
+        
+        Vector catArray = new Vector();
+        catArray.addElement(entry.getCategory().getPath());
+        struct.put("categories", catArray);
+        
+        return struct;
+    }
+    
+    
+    private Hashtable createCategoryStruct(WeblogCategoryData category, String userid) {
+        
+        RollerRequest rreq = RollerRequest.getRollerRequest();
+        HttpServletRequest req = rreq.getRequest();
+        String contextUrl = RollerContext.getRollerContext().getAbsoluteContextUrl(req);
+        
+        Hashtable struct = new Hashtable();
+        struct.put("description", category.getPath());
+        
+        String catUrl = contextUrl+"/page/"+userid+"?catname="+category.getPath();
+        catUrl = Utilities.stringReplace(catUrl," ","%20");
+        struct.put("htmlUrl", catUrl);
+        
+        String rssUrl = contextUrl+"/rss/"+userid+"?catname="+category.getPath();
+        rssUrl = Utilities.stringReplace(catUrl," ","%20");
+        struct.put("rssUrl",rssUrl);
+        
+        return struct;
+    }
+    
+}

Added: incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/RollerXMLRPCServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/RollerXMLRPCServlet.java?rev=400121&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/RollerXMLRPCServlet.java (added)
+++ incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/RollerXMLRPCServlet.java Fri May  5 10:49:04 2006
@@ -0,0 +1,115 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+*  contributor license agreements.  The ASF licenses this file to You
+* under the Apache License, Version 2.0 (the "License"); you may not
+* use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.  For additional information regarding
+* copyright in this work, please see the NOTICE file in the top level
+* directory of this distribution.
+*/
+/*
+ * RollerXMLRPCServlet.java
+ */
+
+package org.apache.roller.webservices.xmlrpc;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.StringBufferInputStream;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xmlrpc.XmlRpcServer;
+
+/**
+ * Roller's XML RPC Servlet sets up XmlRpcHandler for Blogger/ API.
+ * 
+ * @author David M Johnson
+ * 
+ * @web.servlet name="RollerXMLRPCServlet"
+ * @web.servlet-mapping url-pattern="/xmlrpc"
+ */
+public class RollerXMLRPCServlet extends HttpServlet
+{
+    static final long serialVersionUID = -4424719615968330852L;
+    
+    private static Log mLogger = 
+        LogFactory.getFactory().getInstance(RollerXMLRPCServlet.class);
+        
+    private transient XmlRpcServer mXmlRpcServer = new XmlRpcServer();
+    private BloggerAPIHandler mBloggerHandler = null;
+    private MetaWeblogAPIHandler mMetaWeblogHandler = null;
+
+    //------------------------------------------------------------------------
+    
+    /** 
+     * Initializes the servlet.
+     */
+    public void init(ServletConfig config) throws ServletException
+    {
+        super.init(config);
+        try
+        {
+            mBloggerHandler = new BloggerAPIHandler();
+            mXmlRpcServer.addHandler("blogger", mBloggerHandler);
+            
+            mMetaWeblogHandler = new MetaWeblogAPIHandler();
+            mXmlRpcServer.addHandler("metaWeblog", mMetaWeblogHandler);
+        }
+        catch (Exception e)
+        {
+            mLogger.error("Initialization of XML-RPC servlet failed", e);
+        }
+    }
+
+    //------------------------------------------------------------------------
+    
+    protected void service(HttpServletRequest request,
+                                  HttpServletResponse response)
+        throws ServletException, java.io.IOException
+    {
+        InputStream is = request.getInputStream();
+        
+        if (mLogger.isDebugEnabled()) {
+            BufferedReader br = new BufferedReader(new InputStreamReader(is));
+            String line = null;
+            StringBuffer sb = new StringBuffer();
+            while ((line = br.readLine()) != null) {
+                sb.append(line); 
+                sb.append("\n");
+            }
+            mLogger.debug(sb.toString());
+            is = new StringBufferInputStream(sb.toString());
+        }
+        
+        // execute XML-RPC request
+        byte[] result = mXmlRpcServer.execute(is);
+        
+        if (mLogger.isDebugEnabled()) {
+            String output = new String(result);
+            mLogger.debug(output);
+        }
+
+        response.setContentType("text/xml");
+        response.setContentLength(result.length);
+        OutputStream output = response.getOutputStream();
+        output.write(result);
+        output.flush();
+    }
+}

Added: incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/package.html
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/package.html?rev=400121&view=auto
==============================================================================
--- incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/package.html (added)
+++ incubator/roller/trunk/src/org/apache/roller/webservices/xmlrpc/package.html Fri May  5 10:49:04 2006
@@ -0,0 +1,33 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  The ASF licenses this file to You
+  under the Apache License, Version 2.0 (the "License"); you may not
+  use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.  For additional information regarding
+  copyright in this work, please see the NOTICE file in the top level
+  directory of this distribution.
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <title></title>
+</head>
+<body>
+Roller implementation of Blogger and MetaWeblog APIs.
+
+<p>Blogger API spec can be found at http://plant.blogger.com/api/index.html</p>
+
+<p>See also http://xmlrpc.free-conversant.com/docs/bloggerAPI</p>
+
+<p>MetaWeblog API spec can be found at http://www.xmlrpc.com/metaWeblogApi</p>
+
+</body>
+</html>

Modified: incubator/roller/trunk/tests/org/apache/roller/presentation/xmlrpc/RollerXmlRpcServerTest.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/tests/org/apache/roller/presentation/xmlrpc/RollerXmlRpcServerTest.java?rev=400121&r1=400120&r2=400121&view=diff
==============================================================================
--- incubator/roller/trunk/tests/org/apache/roller/presentation/xmlrpc/RollerXmlRpcServerTest.java (original)
+++ incubator/roller/trunk/tests/org/apache/roller/presentation/xmlrpc/RollerXmlRpcServerTest.java Fri May  5 10:49:04 2006
@@ -12,8 +12,8 @@
 import org.apache.roller.RollerTestBase;
 import org.apache.roller.presentation.MockRollerContext;
 import org.apache.roller.presentation.RollerRequest;
-import org.apache.roller.presentation.webservices.xmlrpc.RollerXMLRPCServlet;
 import org.apache.roller.util.RegexUtil;
+import org.apache.roller.webservices.xmlrpc.RollerXMLRPCServlet;
  
 import java.util.ArrayList;
 import java.util.Date;