001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2004 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.ecyrd.jspwiki.rpc.atom;
021:
022: import java.io.*;
023: import javax.servlet.ServletConfig;
024: import javax.servlet.ServletException;
025: import javax.servlet.http.HttpServlet;
026: import javax.servlet.http.HttpServletRequest;
027: import javax.servlet.http.HttpServletResponse;
028:
029: import java.util.Date;
030: import java.util.Collection;
031: import java.util.Iterator;
032: import org.apache.log4j.Logger;
033: import org.intabulas.sandler.*;
034: import org.intabulas.sandler.exceptions.*;
035: import org.intabulas.sandler.elements.*;
036:
037: import com.ecyrd.jspwiki.*;
038: import com.ecyrd.jspwiki.util.*;
039:
040: import com.ecyrd.jspwiki.plugin.WeblogEntryPlugin;
041: import com.ecyrd.jspwiki.plugin.WeblogPlugin;
042: import com.ecyrd.jspwiki.providers.ProviderException;
043:
044: /**
045: * Handles incoming requests for the Atom API. This class uses the
046: * "sandler" Atom API implementation.
047: *
048: * @author Janne Jalkanen
049: * @since 2.1.97
050: */
051: public class AtomAPIServlet extends HttpServlet {
052: static final Logger log = Logger.getLogger(AtomAPIServlet.class);
053:
054: private static final long serialVersionUID = 0L;
055:
056: private WikiEngine m_engine;
057:
058: /**
059: * Initializes the servlet.
060: */
061: public void init(ServletConfig config) throws ServletException {
062: m_engine = WikiEngine.getInstance(config);
063: }
064:
065: /**
066: * Takes the name of the page from the request URI.
067: * The initial slash is also removed. If there is no page,
068: * returns null.
069: */
070: private String getPageName(HttpServletRequest request) {
071: String name = request.getPathInfo();
072:
073: if (name == null || name.length() <= 1) {
074: return null;
075: } else if (name.charAt(0) == '/') {
076: name = name.substring(1);
077: }
078:
079: name = TextUtil.urlDecodeUTF8(name);
080:
081: return name;
082: }
083:
084: /**
085: * Implements the PostURI of the Atom spec.
086: * <p>
087: * Implementation notes:
088: * <ul>
089: * <li>Only fetches the first content. All other contents are ignored.
090: * <li>Assumes that incoming code is plain text or WikiMarkup, not html.
091: * </ul>
092: */
093: public void doPost(HttpServletRequest request,
094: HttpServletResponse response) throws ServletException {
095: log.debug("Received POST to AtomAPIServlet");
096:
097: try {
098: String blogid = getPageName(request);
099:
100: WikiPage page = m_engine.getPage(blogid);
101:
102: if (page == null) {
103: throw new ServletException("Page " + blogid
104: + " does not exist, cannot add blog post.");
105: }
106:
107: //FIXME: Do authentication here
108: Entry entry = Sandler.unmarshallEntry(request
109: .getInputStream());
110:
111: //
112: // Fetch the obligatory parts of the content.
113: //
114: Content title = entry.getTitle();
115: Content content = entry.getContent(0);
116:
117: Person author = entry.getAuthor();
118:
119: //FIXME: Sandler 0.5 does not support generator
120:
121: //
122: // Generate new blog entry.
123: //
124: WeblogEntryPlugin plugin = new WeblogEntryPlugin();
125:
126: String pageName = plugin.getNewEntryPage(m_engine, blogid);
127: String username = author.getName();
128:
129: WikiPage entryPage = new WikiPage(m_engine, pageName);
130: entryPage.setAuthor(username);
131:
132: WikiContext context = new WikiContext(m_engine, request,
133: entryPage);
134:
135: StringBuffer text = new StringBuffer();
136: text.append("!" + title.getBody());
137: text.append("\n\n");
138: text.append(content.getBody());
139:
140: log.debug("Writing entry: " + text);
141:
142: m_engine.saveText(context, text.toString());
143:
144: } catch (FeedMarshallException e) {
145: log.error("Received faulty Atom entry", e);
146: throw new ServletException("Faulty Atom entry", e);
147: } catch (IOException e) {
148: log.error("I/O exception", e);
149: throw new ServletException("Could not get body of request",
150: e);
151: } catch (WikiException e) {
152: log.error("Provider exception while posting", e);
153: throw new ServletException("JSPWiki cannot save the entry",
154: e);
155: }
156: }
157:
158: /**
159: * Handles HTTP GET. However, we do not respond to GET requests,
160: * other than to show an explanatory text.
161: */
162: public void doGet(HttpServletRequest request,
163: HttpServletResponse response) throws ServletException {
164: log.debug("Received HTTP GET to AtomAPIServlet");
165:
166: String blogid = getPageName(request);
167:
168: log.debug("Requested page " + blogid);
169:
170: try {
171: if (blogid == null) {
172: Feed feed = listBlogs();
173:
174: response
175: .setContentType("application/x.atom+xml; charset=UTF-8");
176: response.getWriter()
177: .println(Sandler.marshallFeed(feed));
178:
179: response.getWriter().flush();
180: } else {
181: Entry entry = getBlogEntry(blogid);
182:
183: response
184: .setContentType("application/x.atom+xml; charset=UTF-8");
185: response.getWriter().println(
186: Sandler.marshallEntry(entry));
187:
188: response.getWriter().flush();
189: }
190: } catch (Exception e) {
191: log.error("Unable to generate response", e);
192: throw new ServletException(
193: "Internal problem - whack Janne on the head to get a better error report",
194: e);
195: }
196:
197: }
198:
199: private Entry getBlogEntry(String entryid) throws ProviderException {
200: WikiPage page = m_engine.getPage(entryid);
201: WikiPage firstVersion = m_engine.getPage(entryid, 1);
202:
203: Entry entry = SyndicationFactory.newSyndicationEntry();
204:
205: String pageText = m_engine.getText(page.getName());
206: String title = "";
207: int firstLine = pageText.indexOf('\n');
208:
209: if (firstLine > 0) {
210: title = pageText.substring(0, firstLine);
211: }
212:
213: if (title.trim().length() == 0)
214: title = page.getName();
215:
216: // Remove wiki formatting
217: while (title.startsWith("!"))
218: title = title.substring(1);
219:
220: entry.setTitle(title);
221: entry.setCreated(firstVersion.getLastModified());
222: entry.setModified(page.getLastModified());
223: entry.setAuthor(SyndicationFactory.createPerson(page
224: .getAuthor(), null, null));
225:
226: entry.addContent(SyndicationFactory
227: .createEscapedContent(pageText));
228:
229: return entry;
230: }
231:
232: /**
233: * Creates and outputs a full list of all available blogs
234: */
235: private Feed listBlogs() throws ProviderException, IOException {
236: Collection pages = m_engine.getPageManager().getAllPages();
237:
238: Feed feed = SyndicationFactory.newSyndicationFeed();
239: feed.setTitle("List of blogs at this site");
240: feed.setModified(new Date());
241:
242: for (Iterator i = pages.iterator(); i.hasNext();) {
243: WikiPage p = (WikiPage) i.next();
244:
245: //
246: // List only weblogs
247: // FIXME: Unfortunately, a weblog is not known until it has
248: // been executed once, because plugins are off during
249: // the initial startup phase.
250: //
251:
252: log.debug(p.getName() + " = "
253: + p.getAttribute(WeblogPlugin.ATTR_ISWEBLOG));
254:
255: if (!("true".equals(p
256: .getAttribute(WeblogPlugin.ATTR_ISWEBLOG))))
257: continue;
258:
259: String encodedName = TextUtil.urlEncodeUTF8(p.getName());
260:
261: WikiContext context = new WikiContext(m_engine, p);
262:
263: String title = TextUtil.replaceEntities(BlogUtil
264: .getSiteName(context));
265:
266: Link postlink = createLink("service.post", m_engine
267: .getBaseURL()
268: + "atom/" + encodedName, title);
269:
270: Link editlink = createLink("service.edit", m_engine
271: .getBaseURL()
272: + "atom/" + encodedName, title);
273:
274: Link feedlink = createLink("service.feed", m_engine
275: .getBaseURL()
276: + "atom.jsp?page=" + encodedName, title);
277:
278: feed.addLink(postlink);
279: feed.addLink(feedlink);
280: feed.addLink(editlink);
281: }
282:
283: return feed;
284: }
285:
286: private Link createLink(String rel, String href, String title) {
287: org.intabulas.sandler.elements.impl.LinkImpl link = new org.intabulas.sandler.elements.impl.LinkImpl();
288:
289: link.setRelationship(rel);
290: link.setTitle(title);
291: link.setType("application/x.atom+xml");
292: link.setHref(href);
293:
294: return link;
295: }
296:
297: /**
298: *
299: */
300: public void doDelete(HttpServletRequest request,
301: HttpServletResponse response) throws ServletException {
302: log.debug("Received HTTP DELETE");
303: }
304:
305: /**
306: *
307: */
308: public void doPut(HttpServletRequest request,
309: HttpServletResponse response) throws ServletException {
310: log.debug("Received HTTP PUT");
311: }
312: }
|