KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > roller > webservices > atomprotocol > AtomServlet


1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. The ASF licenses this file to You
4 * under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License. For additional information regarding
15 * copyright in this work, please see the NOTICE file in the top level
16 * directory of this distribution.
17 */

18 package org.apache.roller.webservices.atomprotocol;
19
20 import java.io.IOException JavaDoc;
21 import java.io.InputStreamReader JavaDoc;
22 import java.io.Reader JavaDoc;
23 import java.io.Writer JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27
28 import javax.servlet.ServletException JavaDoc;
29 import javax.servlet.http.HttpServlet JavaDoc;
30 import javax.servlet.http.HttpServletRequest JavaDoc;
31 import javax.servlet.http.HttpServletResponse JavaDoc;
32
33 import org.apache.commons.lang.StringUtils;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.jdom.Document;
37 import org.jdom.Element;
38 import org.jdom.JDOMException;
39 import org.jdom.input.SAXBuilder;
40 import org.jdom.output.Format;
41 import org.jdom.output.XMLOutputter;
42
43 import com.sun.syndication.feed.atom.Entry;
44 import com.sun.syndication.feed.atom.Feed;
45 import com.sun.syndication.feed.atom.Link;
46 import com.sun.syndication.io.FeedException;
47 import com.sun.syndication.io.WireFeedInput;
48 import com.sun.syndication.io.WireFeedOutput;
49 import java.io.BufferedReader JavaDoc;
50 import java.io.StringWriter JavaDoc;
51 import org.jdom.Namespace;
52 import org.apache.roller.config.RollerConfig;
53
54 /**
55  * Atom Servlet implements Atom by calling a Roller independent handler.
56  * @web.servlet name="AtomServlet"
57  * @web.servlet-mapping url-pattern="/roller-services/app/*"
58  * @author David M Johnson
59  */

60 public class AtomServlet extends HttpServlet JavaDoc {
61     public static final String JavaDoc FEED_TYPE = "atom_1.0";
62     
63     private static Log mLogger =
64             LogFactory.getFactory().getInstance(AtomServlet.class);
65     
66     //-----------------------------------------------------------------------------
67
/**
68      * Create an Atom request handler.
69      * TODO: make AtomRequestHandler implementation configurable.
70      */

71     private AtomHandler createAtomRequestHandler(HttpServletRequest JavaDoc request)
72     throws ServletException JavaDoc {
73         boolean enabled = RollerConfig.getBooleanProperty(
74             "webservices.atomprotocol.enabled");
75         if (!enabled) {
76             throw new ServletException JavaDoc("ERROR: Atom protocol not enabled");
77         }
78         return new RollerAtomHandler(request);
79     }
80     
81     //-----------------------------------------------------------------------------
82
/**
83      * Handles an Atom GET by calling handler and writing results to response.
84      */

85     protected void doGet(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
86     throws ServletException JavaDoc, IOException JavaDoc {
87         AtomHandler handler = createAtomRequestHandler(req);
88         String JavaDoc userName = handler.getAuthenticatedUsername();
89         if (userName != null) {
90             String JavaDoc[] pathInfo = getPathInfo(req);
91             try {
92                 if (handler.isIntrospectionURI(pathInfo)) {
93                     // return an Atom Service document
94
AtomService service = handler.getIntrospection();
95                     Document doc = AtomService.serviceToDocument(service);
96                     res.setContentType("application/atomserv+xml; charset=utf-8");
97                     Writer JavaDoc writer = res.getWriter();
98                     XMLOutputter outputter = new XMLOutputter();
99                     outputter.setFormat(Format.getPrettyFormat());
100                     outputter.output(doc, writer);
101                     writer.close();
102                     res.setStatus(HttpServletResponse.SC_OK);
103                 }
104                 else if (handler.isCollectionURI(pathInfo)) {
105                     // return a collection
106
Feed col = handler.getCollection(pathInfo);
107                     col.setFeedType(FEED_TYPE);
108                     WireFeedOutput wireFeedOutput = new WireFeedOutput();
109                     Document feedDoc = wireFeedOutput.outputJDom(col);
110                     res.setContentType("application/atom+xml; charset=utf-8");
111                     Writer JavaDoc writer = res.getWriter();
112                     XMLOutputter outputter = new XMLOutputter();
113                     outputter.setFormat(Format.getPrettyFormat());
114                     outputter.output(feedDoc, writer);
115                     writer.close();
116                     res.setStatus(HttpServletResponse.SC_OK);
117                 }
118                 else if (handler.isEntryURI(pathInfo)) {
119                     // return an entry
120
Entry entry = handler.getEntry(pathInfo);
121                     if (entry != null) {
122                         res.setContentType("application/atom+xml; charset=utf-8");
123                         Writer JavaDoc writer = res.getWriter();
124                         serializeEntry(entry, writer);
125                         writer.close();
126                     } else {
127                         res.setStatus(HttpServletResponse.SC_NOT_FOUND);
128                     }
129                 } else {
130                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
131                 }
132             } catch (AtomException ae) {
133                 res.setStatus(ae.getStatus());
134                 mLogger.debug(ae);
135             } catch (Exception JavaDoc ae) {
136                 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
137                 mLogger.debug(ae);
138             }
139         } else {
140             res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
141             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
142         }
143     }
144     
145     //-----------------------------------------------------------------------------
146
/**
147      * Handles an Atom POST by calling handler to identify URI, reading/parsing
148      * data, calling handler and writing results to response.
149      */

150     protected void doPost(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
151     throws ServletException JavaDoc, IOException JavaDoc {
152         AtomHandler handler = createAtomRequestHandler(req);
153         String JavaDoc userName = handler.getAuthenticatedUsername();
154         if (userName != null) {
155             String JavaDoc[] pathInfo = getPathInfo(req);
156             try {
157                 if (handler.isCollectionURI(pathInfo)) {
158                     
159                     if (req.getContentType().startsWith("application/atom+xml")) {
160
161                         // parse incoming entry
162
Entry unsavedEntry = parseEntry(new BufferedReader JavaDoc(
163                             new InputStreamReader JavaDoc(
164                                 req.getInputStream(), "UTF-8")));
165
166                         // call handler to post it
167
Entry savedEntry = handler.postEntry(pathInfo, unsavedEntry);
168                         
169                         // return alternate link as Location header
170
Iterator JavaDoc links = savedEntry.getOtherLinks().iterator();
171                         while (links.hasNext()) {
172                             Link link = (Link) links.next();
173                             if (link.getRel().equals("edit") || link.getRel() == null) {
174                                 res.addHeader("Location", link.getHref());
175                                 break;
176                             }
177                         }
178                         // write entry back out to response
179
res.setStatus(HttpServletResponse.SC_CREATED);
180                         res.setContentType("application/atom+xml; charset=utf-8");
181                         Writer JavaDoc writer = res.getWriter();
182                         serializeEntry(savedEntry, writer);
183                         writer.close();
184                     
185                     } else if (req.getContentType() != null) {
186                         // get incoming title and slug from HTTP header
187
String JavaDoc title = req.getHeader("Title");
188                         String JavaDoc slug = req.getHeader("Slug");
189
190                         // hand input stream of to hander to post file
191
Entry resource = handler.postMedia(
192                             pathInfo, title, slug, req.getContentType(), req.getInputStream());
193                         
194                         res.setStatus(HttpServletResponse.SC_CREATED);
195                         com.sun.syndication.feed.atom.Content content =
196                             (com.sun.syndication.feed.atom.Content)resource.getContents().get(0);
197
198                         // return alternate link as Location header
199
Iterator JavaDoc links = resource.getOtherLinks().iterator();
200                         while (links.hasNext()) {
201                             Link link = (Link) links.next();
202                             if (link.getRel().equals("edit") || link.getRel() == null) {
203                                 res.addHeader("Location", link.getHref());
204                                 break;
205                             }
206                         }
207                         Writer JavaDoc writer = res.getWriter();
208                         serializeEntry(resource, writer);
209                         writer.close();
210                     } else {
211                         res.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
212                     }
213                     
214                 } else {
215                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
216                 }
217             } catch (AtomException ae) {
218                 res.setStatus(ae.getStatus());
219                 mLogger.debug(ae);
220             } catch (Exception JavaDoc ae) {
221                 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
222                 mLogger.debug(ae);
223             }
224         } else {
225             res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
226             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
227         }
228     }
229     
230     //-----------------------------------------------------------------------------
231
/**
232      * Handles an Atom PUT by calling handler to identify URI, reading/parsing
233      * data, calling handler and writing results to response.
234      */

235     protected void doPut(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
236     throws ServletException JavaDoc, IOException JavaDoc {
237         AtomHandler handler = createAtomRequestHandler(req);
238         String JavaDoc userName = handler.getAuthenticatedUsername();
239         if (userName != null) {
240             String JavaDoc[] pathInfo = getPathInfo(req);
241             try {
242                 if (handler.isEntryURI(pathInfo)) {
243                     
244                     // parse incoming entry
245
Entry unsavedEntry = parseEntry(new BufferedReader JavaDoc(
246                         new InputStreamReader JavaDoc(
247                             req.getInputStream(), "UTF-8")));
248                     
249                     // call handler to put entry
250
Entry updatedEntry = handler.putEntry(pathInfo, unsavedEntry);
251                     
252                     // write entry back out to response
253
res.setContentType("application/atom+xml; charset=utf-8");
254                     Writer JavaDoc writer = res.getWriter();
255                     serializeEntry(updatedEntry, writer);
256                     res.setStatus(HttpServletResponse.SC_OK);
257                     writer.close();
258                     
259                 } else if (handler.isMediaEditURI(pathInfo)) {
260                     
261                     // hand input stream to handler
262
Entry updatedEntry = handler.putMedia(
263                         pathInfo, req.getContentType(), req.getInputStream());
264                                         
265                     // write entry back out to response
266
res.setContentType("application/atom+xml; charset=utf-8");
267                     Writer JavaDoc writer = res.getWriter();
268                     serializeEntry(updatedEntry, writer);
269                     writer.close();
270                     res.setStatus(HttpServletResponse.SC_OK);
271                     
272                 } else {
273                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
274                 }
275             } catch (AtomException ae) {
276                 res.setStatus(ae.getStatus());
277                 mLogger.debug(ae);
278             } catch (Exception JavaDoc ae) {
279                 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
280                 mLogger.debug(ae);
281             }
282         } else {
283             res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
284             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
285         }
286     }
287     
288     //-----------------------------------------------------------------------------
289
/**
290      * Handle Atom DELETE by calling appropriate handler.
291      */

292     protected void doDelete(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
293     throws ServletException JavaDoc, IOException JavaDoc {
294         AtomHandler handler = createAtomRequestHandler(req);
295         String JavaDoc userName = handler.getAuthenticatedUsername();
296         if (userName != null) {
297             String JavaDoc[] pathInfo = getPathInfo(req);
298             try {
299                 if (handler.isEntryURI(pathInfo)) {
300                     handler.deleteEntry(pathInfo);
301                     res.setStatus(HttpServletResponse.SC_OK);
302                 }
303                 else {
304                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
305                 }
306             } catch (AtomException ae) {
307                 res.setStatus(ae.getStatus());
308                 mLogger.debug(ae);
309             } catch (Exception JavaDoc ae) {
310                 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
311                 mLogger.debug(ae);
312             }
313         } else {
314             res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
315             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
316         }
317     }
318     
319     //-----------------------------------------------------------------------------
320
/**
321      * Convenience method to return the PathInfo from the request.
322      */

323     protected String JavaDoc[] getPathInfo(HttpServletRequest JavaDoc request) {
324         String JavaDoc mPathInfo = request.getPathInfo();
325         mPathInfo = (mPathInfo!=null) ? mPathInfo : "";
326         return StringUtils.split(mPathInfo,"/");
327     }
328     
329     /**
330      * Serialize entry to writer.
331      */

332     public static void serializeEntry(Entry entry, Writer JavaDoc writer)
333     throws IllegalArgumentException JavaDoc, FeedException, IOException JavaDoc {
334         // Build a feed containing only the entry
335
List JavaDoc entries = new ArrayList JavaDoc();
336         entries.add(entry);
337         Feed feed1 = new Feed();
338         feed1.setFeedType(AtomServlet.FEED_TYPE);
339         feed1.setEntries(entries);
340         
341         // Get Rome to output feed as a JDOM document
342
WireFeedOutput wireFeedOutput = new WireFeedOutput();
343         Document feedDoc = wireFeedOutput.outputJDom(feed1);
344         
345         // Grab entry element from feed and get JDOM to serialize it
346
Element entryElement= (Element)feedDoc.getRootElement().getChildren().get(0);
347         
348         // Add our own namespaced element, so we can determine if we can
349
// count on client to preserve foreign markup as it should.
350
Element rollerElement = new Element("atom-draft",
351             "http://rollerweblogger.org/namespaces/app");
352         rollerElement.setText("9");
353         entryElement.addContent(rollerElement);
354         
355         XMLOutputter outputter = new XMLOutputter();
356         outputter.setFormat(Format.getPrettyFormat());
357         
358         if (mLogger.isDebugEnabled()) {
359             StringWriter JavaDoc sw = new StringWriter JavaDoc();
360             outputter.output(entryElement, sw);
361             mLogger.debug(sw.toString());
362             writer.write(sw.toString());
363         } else {
364             outputter.output(entryElement, writer);
365         }
366     }
367     
368     /**
369      * Parse entry from reader.
370      */

371     public static Entry parseEntry(Reader JavaDoc rd)
372         throws JDOMException, IOException JavaDoc, IllegalArgumentException JavaDoc, FeedException {
373         // Parse entry into JDOM tree
374
SAXBuilder builder = new SAXBuilder();
375         Document entryDoc = builder.build(rd);
376         Element fetchedEntryElement = entryDoc.getRootElement();
377         fetchedEntryElement.detach();
378         
379         // Put entry into a JDOM document with 'feed' root so that Rome can handle it
380
Feed feed = new Feed();
381         feed.setFeedType(FEED_TYPE);
382         WireFeedOutput wireFeedOutput = new WireFeedOutput();
383         Document feedDoc = wireFeedOutput.outputJDom(feed);
384         feedDoc.getRootElement().addContent(fetchedEntryElement);
385         
386         // Check for our special namespaced element. If it's there, then we
387
// know that client is not preserving foreign markup.
388
Namespace ns = Namespace.getNamespace(
389             "http://rollerweblogger.org/namespaces/app");
390         Element rollerElement = fetchedEntryElement.getChild("atom-draft", ns);
391         if (rollerElement == null) {
392             mLogger.debug("Client is NOT preserving foreign markup");
393         }
394         
395         WireFeedInput input = new WireFeedInput();
396         Feed parsedFeed = (Feed)input.build(feedDoc);
397         return (Entry)parsedFeed.getEntries().get(0);
398     }
399 }
400
Popular Tags