KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > blojsom > extension > comment > CommentAPIServlet


1 /**
2  * Copyright (c) 2003-2006, David A. Czarnecki
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 notice, this list of conditions and the
9  * following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
11  * following disclaimer in the documentation and/or other materials provided with the distribution.
12  * Neither the name of "David A. Czarnecki" and "blojsom" nor the names of its contributors may be used to
13  * endorse or promote products derived from this software without specific prior written permission.
14  * Products derived from this software may not be called "blojsom", nor may "blojsom" appear in their name,
15  * without prior written permission of David A. Czarnecki.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21  * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */

31 package org.blojsom.extension.comment;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.blojsom.blog.Blog;
36 import org.blojsom.blog.Comment;
37 import org.blojsom.blog.Entry;
38 import org.blojsom.event.EventBroadcaster;
39 import org.blojsom.fetcher.Fetcher;
40 import org.blojsom.fetcher.FetcherException;
41 import org.blojsom.plugin.comment.event.CommentAddedEvent;
42 import org.blojsom.plugin.common.ResponseConstants;
43 import org.blojsom.servlet.ServletConfigFactoryBean;
44 import org.blojsom.util.BlojsomConstants;
45 import org.blojsom.util.BlojsomUtils;
46 import org.springframework.context.support.ClassPathXmlApplicationContext;
47 import org.w3c.dom.Document JavaDoc;
48 import org.w3c.dom.Element JavaDoc;
49 import org.w3c.dom.Node JavaDoc;
50 import org.w3c.dom.NodeList JavaDoc;
51 import org.xml.sax.SAXException JavaDoc;
52
53 import javax.mail.internet.AddressException JavaDoc;
54 import javax.mail.internet.InternetAddress JavaDoc;
55 import javax.servlet.ServletConfig JavaDoc;
56 import javax.servlet.ServletException JavaDoc;
57 import javax.servlet.http.HttpServlet JavaDoc;
58 import javax.servlet.http.HttpServletRequest JavaDoc;
59 import javax.servlet.http.HttpServletResponse JavaDoc;
60 import javax.xml.parsers.DocumentBuilder JavaDoc;
61 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
62 import javax.xml.parsers.FactoryConfigurationError JavaDoc;
63 import javax.xml.parsers.ParserConfigurationException JavaDoc;
64 import java.io.IOException JavaDoc;
65 import java.io.PrintWriter JavaDoc;
66 import java.io.UnsupportedEncodingException JavaDoc;
67 import java.net.HttpURLConnection JavaDoc;
68 import java.util.Date JavaDoc;
69 import java.util.HashMap JavaDoc;
70
71 /**
72  * blojsom Comment API Implementation
73  * <p/>
74  * <a HREF="http://wellformedweb.org/story/9">Comment API specification</a>.
75  * <p/>
76  * For more information on the &lt;item/&gt; fragment and its content, check the <a HREF="http://blogs.law.harvard.edu/tech/rss">RSS 2.0 specification</a>.
77  *
78  * @author David Czarnecki
79  * @author Mark Lussier
80  * @since blojsom 3.0
81  * @version $Id: CommentAPIServlet.java,v 1.3 2006/09/26 02:55:19 czarneckid Exp $
82  */

83 public class CommentAPIServlet extends HttpServlet JavaDoc {
84
85     private Log _logger = LogFactory.getLog(CommentAPIServlet.class);
86
87     /**
88      * RSS &lt;item/&gt; fragment tag containing the title
89      */

90     private static final String JavaDoc COMMENTAPI_TITLE = "title";
91
92     /**
93      * RSS &lt;item/&gt; fragment tag containing the link
94      */

95     private static final String JavaDoc COMMENTAPI_LINK = "link";
96
97     /**
98      * RSS &lt;item/&gt; fragment tag containing the description
99      */

100     private static final String JavaDoc COMMENTAPI_DESCRIPTION = "description";
101
102     /**
103      * RSS &lt;item/&gt; fragment tag containing the author
104      */

105     private static final String JavaDoc COMMENTAPI_AUTHOR = "author";
106
107     /**
108      * RSS &lt;dc:creator/&gt; fragment tag containing the author's name
109      */

110     private static final String JavaDoc COMMENTAPI_DC_CREATOR = "dc:creator";
111
112     private static final String JavaDoc COMMENTAPI_TITLE_METADATA = "comment-api-metadata-title";
113
114     private static final String JavaDoc COMMENTAPI_ACCEPTS_ONLY_POSTS_MESSAGE = "Comment API server only accepts POST requests.";
115
116     private String JavaDoc[] BLOJSOM_CONFIGURATION_FILES = {"blojsom-commentapi.xml"};
117
118     private ClassPathXmlApplicationContext _classPathXmlApplicationContext;
119
120     /**
121      * Default constructor
122      */

123     public CommentAPIServlet() {
124     }
125
126     /**
127      * Initialize the blojsom Comment API servlet
128      *
129      * @param servletConfig Servlet configuration information
130      * @throws ServletException If there is an error initializing the servlet
131      */

132     public void init(ServletConfig JavaDoc servletConfig) throws ServletException JavaDoc {
133         super.init(servletConfig);
134
135         ServletConfigFactoryBean.setServletConfig(servletConfig);
136
137         _classPathXmlApplicationContext = new ClassPathXmlApplicationContext(BLOJSOM_CONFIGURATION_FILES);
138         servletConfig.getServletContext().setAttribute(BlojsomConstants.BLOJSOM_COMMENTAPI_APPLICATION_CONTEXT, _classPathXmlApplicationContext);
139
140         if (_logger.isDebugEnabled()) {
141             _logger.debug("blojsom Comment API: All Your Blog Are Belong To Us");
142         }
143     }
144
145     /**
146      * Service a Comment API request
147      *
148      * @param httpServletRequest Request
149      * @param httpServletResponse Response
150      * @throws ServletException If there is an error processing the request
151      * @throws IOException If there is an error during I/O
152      */

153     protected void service(HttpServletRequest JavaDoc httpServletRequest, HttpServletResponse JavaDoc httpServletResponse) throws ServletException JavaDoc, IOException JavaDoc {
154         try {
155             httpServletRequest.setCharacterEncoding(BlojsomConstants.UTF8);
156         } catch (UnsupportedEncodingException JavaDoc e) {
157             _logger.error(e);
158         }
159
160         if (!"post".equalsIgnoreCase(httpServletRequest.getMethod())) {
161             httpServletResponse.setContentType("text/html; charset=UTF-8");
162             httpServletResponse.setContentLength(COMMENTAPI_ACCEPTS_ONLY_POSTS_MESSAGE.length());
163             httpServletResponse.setStatus(HttpURLConnection.HTTP_BAD_METHOD);
164             PrintWriter JavaDoc printWriter = httpServletResponse.getWriter();
165             printWriter.print(COMMENTAPI_ACCEPTS_ONLY_POSTS_MESSAGE);
166             printWriter.flush();
167
168             return;
169         }
170
171         String JavaDoc commentAuthor = null;
172         String JavaDoc commentEmail = null;
173         String JavaDoc commentLink = null;
174         String JavaDoc commentText = null;
175         String JavaDoc commentTitle = null;
176         String JavaDoc commentDCCreator = null;
177
178         // Determine the appropriate user from the URL
179
String JavaDoc blogId = BlojsomUtils.getBlogFromPath(httpServletRequest.getPathInfo());
180         if (BlojsomUtils.checkNullOrBlank(blogId) || "/".equals(blogId)) {
181             httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND, "Requested blog not found: " + blogId);
182
183             return;
184         }
185
186         Fetcher fetcher = (Fetcher) _classPathXmlApplicationContext.getBean("fetcher");
187
188         Blog blog;
189         try {
190             blog = fetcher.loadBlog(blogId);
191         } catch (FetcherException e) {
192             if (_logger.isErrorEnabled()) {
193                 _logger.error(e);
194             }
195
196             return;
197         }
198
199         if (blog.getProperty(BlojsomConstants.USE_DYNAMIC_BLOG_URLS) != null) {
200             BlojsomUtils.resolveDynamicBaseAndBlogURL(httpServletRequest, blog, blogId);
201         }
202
203         if (blog.getBlogCommentsEnabled().booleanValue() && httpServletRequest.getContentLength() > 0) {
204             String JavaDoc permalink = httpServletRequest.getParameter(BlojsomConstants.PERMALINK_PARAM);
205
206             try {
207                 DocumentBuilder JavaDoc builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
208                 Document JavaDoc document = builder.parse(httpServletRequest.getInputStream());
209
210                 // Walk through the RSS2 Item Fragment
211
Element JavaDoc docElement = document.getDocumentElement();
212                 if (docElement.hasChildNodes()) {
213                     NodeList JavaDoc comment = docElement.getChildNodes();
214                     if (comment.getLength() > 0) {
215                         for (int x = 0; x < comment.getLength(); x++) {
216                             Node JavaDoc node = comment.item(x);
217                             if (node.getNodeType() == Node.ELEMENT_NODE) {
218                                 if (node.getNodeName().equals(COMMENTAPI_LINK) && (node.getFirstChild() != null)) {
219                                     commentLink = node.getFirstChild().getNodeValue();
220                                 }
221
222                                 if (node.getNodeName().equals(COMMENTAPI_TITLE) && (node.getFirstChild() != null)) {
223                                     commentTitle = node.getFirstChild().getNodeValue();
224                                 }
225
226                                 if (node.getNodeName().equals(COMMENTAPI_AUTHOR) && (node.getFirstChild() != null)) {
227                                     commentAuthor = node.getFirstChild().getNodeValue();
228                                 }
229
230                                 if (node.getNodeName().equals(COMMENTAPI_DESCRIPTION) && (node.getFirstChild() != null)) {
231                                     commentText = node.getFirstChild().getNodeValue();
232                                 }
233
234                                 if (node.getNodeName().equals(COMMENTAPI_DC_CREATOR) && (node.getFirstChild() != null)) {
235                                     commentDCCreator = node.getFirstChild().getNodeValue();
236                                 }
237                             }
238                         }
239                     }
240                 }
241             } catch (ParserConfigurationException JavaDoc e) {
242                 if (_logger.isErrorEnabled()) {
243                     _logger.error(e);
244                 }
245                 httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
246
247                 return;
248             } catch (FactoryConfigurationError JavaDoc e) {
249                 if (_logger.isErrorEnabled()) {
250                     _logger.error(e);
251                 }
252                 httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
253
254                 return;
255             } catch (SAXException JavaDoc e) {
256                 if (_logger.isErrorEnabled()) {
257                     _logger.error(e);
258                 }
259                 httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
260
261                 return;
262             } catch (IOException JavaDoc e) {
263                 if (_logger.isErrorEnabled()) {
264                     _logger.error(e);
265                 }
266                 httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
267
268                 return;
269             }
270
271             // Try to extract an email address from "User Name <useremail@.com>" formatted string,
272
// otherwise, just use the Name
273
if (commentAuthor != null) {
274                 try {
275                     InternetAddress JavaDoc emailaddress = new InternetAddress JavaDoc(commentAuthor);
276                     commentEmail = emailaddress.getAddress();
277                     commentAuthor = emailaddress.getPersonal();
278                     if (commentAuthor == null) {
279                         commentAuthor = commentEmail;
280                     }
281                 } catch (AddressException JavaDoc e) {
282                     if (_logger.isErrorEnabled()) {
283                         _logger.error(e);
284                     }
285                 }
286             } else {
287                 commentAuthor = "";
288                 commentEmail = "";
289             }
290
291             // If the link is null, set it to an empty string
292
if (commentLink == null) {
293                 commentLink = "";
294             }
295
296             // If the dc:creator element is available, assign that to the author name
297
if (commentDCCreator != null) {
298                 commentAuthor = commentDCCreator;
299             }
300
301             if (commentText != null) {
302                 if (_logger.isDebugEnabled()) {
303                     _logger.debug("Comment API ==============================================");
304                     _logger.debug(" Blog: " + blog.getBlogId());
305                     _logger.debug(" Permalink: " + permalink);
306                     _logger.debug(" Commenter: " + commentAuthor);
307                     _logger.debug("Cmtr Email: " + commentEmail);
308                     _logger.debug(" Link: " + commentLink);
309                     _logger.debug(" Comment: \n" + commentText);
310                 }
311
312                 // Create a new blog comment
313
Comment comment = fetcher.newComment();
314                 try {
315                     Entry entry = fetcher.loadEntry(blog, permalink);
316
317                     HashMap JavaDoc commentMetaData = new HashMap JavaDoc();
318                     commentMetaData.put(COMMENTAPI_TITLE_METADATA, commentTitle);
319
320                     comment.setAuthor(commentAuthor);
321                     comment.setAuthorEmail(commentEmail);
322                     comment.setAuthorURL(commentLink);
323                     comment.setBlogId(blog.getId());
324                     comment.setComment(commentText);
325                     comment.setCommentDate(new Date JavaDoc());
326                     comment.setEntry(entry);
327                     comment.setIp(httpServletRequest.getRemoteAddr());
328                     comment.setMetaData(commentMetaData);
329                     comment.setStatus(ResponseConstants.NEW_STATUS);
330
331                     fetcher.saveComment(blog, comment);
332
333                     EventBroadcaster eventBroadcaster = (EventBroadcaster) _classPathXmlApplicationContext.getBean("eventBroadcaster");
334
335                     eventBroadcaster.broadcastEvent(new CommentAddedEvent(this, new Date JavaDoc(), comment, blog));
336
337                     httpServletResponse.setStatus(HttpServletResponse.SC_OK);
338                 } catch (FetcherException e) {
339                     _logger.error(e);
340
341                     httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND, "Could not find blog entry: " + permalink);
342                 }
343             } else {
344                 httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "No comment text available");
345             }
346         } else {
347             httpServletResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Blog comments not enabled or No content in request");
348         }
349     }
350
351     /**
352      * Called when removing the servlet from the servlet container
353      */

354     public void destroy() {
355         super.destroy();
356
357         _classPathXmlApplicationContext.destroy();
358
359         if (_logger.isDebugEnabled()) {
360             _logger.debug("blojsom Comment API destroyed");
361         }
362     }
363 }
364
365
Popular Tags