KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > roller > presentation > atomapi > AtomServlet


1 /*
2  * Copyright 2005 David M Johnson (For RSS and Atom In Action)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not 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.
15  */

16 package org.roller.presentation.atomapi;
17
18 import java.io.FileInputStream JavaDoc;
19 import java.io.IOException JavaDoc;
20 import java.io.InputStreamReader JavaDoc;
21 import java.io.Reader JavaDoc;
22 import java.io.Writer JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26
27 import javax.servlet.ServletException JavaDoc;
28 import javax.servlet.http.HttpServlet JavaDoc;
29 import javax.servlet.http.HttpServletRequest JavaDoc;
30 import javax.servlet.http.HttpServletResponse JavaDoc;
31
32 import org.apache.commons.lang.StringUtils;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.jdom.Document;
36 import org.jdom.Element;
37 import org.jdom.JDOMException;
38 import org.jdom.input.SAXBuilder;
39 import org.jdom.output.Format;
40 import org.jdom.output.XMLOutputter;
41 import org.roller.util.Utilities;
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
50 /**
51  * Atom Servlet implements Atom by calling a Roller independent handler.
52  * @web.servlet name="AtomServlet"
53  * @web.servlet-mapping url-pattern="/atom/*"
54  * @author David M Johnson
55  */

56 public class AtomServlet extends HttpServlet JavaDoc
57 {
58     /** We use Rome to parse/generate Atom feeds and it does Atom format 0.3 */
59     public static final String JavaDoc FEED_TYPE = "atom_0.3";
60     
61     private static Log mLogger =
62         LogFactory.getFactory().getInstance(AtomServlet.class);
63
64     //-----------------------------------------------------------------------------
65
/**
66      * Create an Atom request handler.
67      * TODO: make AtomRequestHandler implementation configurable.
68      */

69     private AtomHandler createAtomRequestHandler(HttpServletRequest JavaDoc request)
70     {
71         return new RollerAtomHandler(request);
72     }
73     
74     //-----------------------------------------------------------------------------
75
/**
76      * Handles an Atom GET by calling handler and writing results to response.
77      */

78     protected void doGet(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
79         throws ServletException JavaDoc, IOException JavaDoc
80     {
81         AtomHandler handler = createAtomRequestHandler(req);
82         String JavaDoc userName = handler.getAuthenticatedUsername();
83         if (userName != null)
84         {
85             String JavaDoc[] pathInfo = getPathInfo(req);
86             try
87             {
88                 if (handler.isIntrospectionURI(pathInfo))
89                 {
90                     // return an Atom Service document
91
AtomService service = handler.getIntrospection(pathInfo);
92                     Document doc = AtomService.serviceToDocument(service);
93                     Writer JavaDoc writer = res.getWriter();
94                     XMLOutputter outputter = new XMLOutputter();
95                     outputter.setFormat(Format.getPrettyFormat());
96                     outputter.output(doc, writer);
97                     writer.close();
98                     res.setStatus(HttpServletResponse.SC_OK);
99                 }
100                 else if (handler.isCollectionURI(pathInfo))
101                 {
102                     // return a collection
103
String JavaDoc ranges = req.getHeader("Range");
104                     if (ranges == null) req.getParameter("Range");
105                     AtomCollection col = null;
106                     if (ranges != null)
107                     {
108                         AtomCollection.Range range =
109                             AtomCollection.parseRange(req.getHeader("Range"));
110                         int offset = 0;
111                         String JavaDoc offsetString = req.getParameter("offset");
112                         if (offsetString != null)
113                         {
114                             offset = Integer.parseInt(offsetString);
115                         }
116                         col= handler.getCollection(
117                             pathInfo, range.start, range.end, offset);
118                     }
119                     else
120                     {
121                         col= handler.getCollection(pathInfo);
122                     }
123                     Document doc = AtomCollection.collectionToDocument(col);
124                     Writer JavaDoc writer = res.getWriter();
125                     XMLOutputter outputter = new XMLOutputter();
126                     outputter.setFormat(Format.getPrettyFormat());
127                     outputter.output(doc, writer);
128                     writer.close();
129                     res.setStatus(HttpServletResponse.SC_OK);
130                 }
131                 else if (handler.isEntryURI(pathInfo))
132                 {
133                     // return an entry
134
Entry entry = handler.getEntry(pathInfo);
135                     Writer JavaDoc writer = res.getWriter();
136                     serializeEntry(entry, writer);
137                     writer.close();
138                 }
139                 else if (handler.isResourceURI(pathInfo))
140                 {
141                     // return a resource
142
String JavaDoc absPath = handler.getResourceFilePath(pathInfo);
143                     String JavaDoc type = getServletContext().getMimeType(absPath);
144                     res.setContentType(type);
145                     Utilities.copyInputToOutput(
146                         new FileInputStream JavaDoc(absPath), res.getOutputStream());
147                 }
148                 else
149                 {
150                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
151                 }
152             }
153             catch (Exception JavaDoc e)
154             {
155                 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
156                 e.printStackTrace(res.getWriter());
157                 mLogger.error(e);
158             }
159         }
160         else
161         {
162             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
163         }
164     }
165     
166     //-----------------------------------------------------------------------------
167
/**
168      * Handles an Atom POST by calling handler to identify URI, reading/parsing
169      * data, calling handler and writing results to response.
170      */

171     protected void doPost(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
172         throws ServletException JavaDoc, IOException JavaDoc
173     {
174         AtomHandler handler = createAtomRequestHandler(req);
175         String JavaDoc userName = handler.getAuthenticatedUsername();
176         if (userName != null)
177         {
178             String JavaDoc[] pathInfo = getPathInfo(req);
179             try
180             {
181                 if (handler.isEntryCollectionURI(pathInfo))
182                 {
183                     // parse incoming entry
184
Entry unsavedEntry = parseEntry(
185                         new InputStreamReader JavaDoc(req.getInputStream()));
186                     
187                     // call handler to post it
188
Entry savedEntry = handler.postEntry(pathInfo, unsavedEntry);
189                     Iterator JavaDoc links = savedEntry.getAlternateLinks().iterator();
190                     while (links.hasNext()) {
191                         Link link = (Link) links.next();
192                         if (link.getRel().equals("alternate")) {
193                             res.addHeader("Location", link.getHref());
194                             break;
195                         }
196                     }
197                     // write entry back out to response
198
res.setStatus(HttpServletResponse.SC_CREATED);
199                     Writer JavaDoc writer = res.getWriter();
200                     serializeEntry(savedEntry, writer);
201                     writer.close();
202                 }
203                 else if (handler.isResourceCollectionURI(pathInfo))
204                 {
205                     // get incoming file name from HTTP header
206
String JavaDoc name = req.getHeader("Name");
207                     
208                     // hand input stream of to hander to post file
209
String JavaDoc location = handler.postResource(
210                        pathInfo, name, req.getContentType(), req.getInputStream());
211                     res.setStatus(HttpServletResponse.SC_CREATED);
212                     res.setHeader("Location", location);
213                 }
214                 else
215                 {
216                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
217                 }
218             }
219             catch (Exception JavaDoc e)
220             {
221                 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
222                 e.printStackTrace(res.getWriter());
223                 mLogger.error(e);
224             }
225         }
226         else
227         {
228             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
229         }
230     }
231
232     //-----------------------------------------------------------------------------
233
/**
234      * Handles an Atom PUT by calling handler to identify URI, reading/parsing
235      * data, calling handler and writing results to response.
236      */

237     protected void doPut(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
238         throws ServletException JavaDoc, IOException JavaDoc
239     {
240         AtomHandler handler = createAtomRequestHandler(req);
241         String JavaDoc userName = handler.getAuthenticatedUsername();
242         if (userName != null)
243         {
244             String JavaDoc[] pathInfo = getPathInfo(req);
245             try
246             {
247                 if (handler.isEntryURI(pathInfo))
248                 {
249                     // parse incoming entry
250
Entry unsavedEntry = parseEntry(
251                         new InputStreamReader JavaDoc(req.getInputStream()));
252                     
253                     // call handler to put entry
254
Entry updatedEntry = handler.putEntry(pathInfo, unsavedEntry);
255                     
256                     // write entry back out to response
257
Writer JavaDoc writer = res.getWriter();
258                     serializeEntry(updatedEntry, writer);
259                     res.setStatus(HttpServletResponse.SC_OK);
260                     writer.close();
261                 }
262                 else if (handler.isResourceCollectionURI(pathInfo))
263                 {
264                     // handle input stream to handler
265
handler.putResource(
266                         pathInfo, req.getContentType(), req.getInputStream());
267                     res.setStatus(HttpServletResponse.SC_OK);
268                 }
269                 else
270                 {
271                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
272                 }
273             }
274             catch (Exception JavaDoc e)
275             {
276                 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
277                 e.printStackTrace(res.getWriter());
278                 mLogger.error(e);
279             }
280         }
281         else
282         {
283             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
284         }
285     }
286
287     //-----------------------------------------------------------------------------
288
/**
289      * Handle Atom DELETE by calling appropriate handler.
290      */

291     protected void doDelete(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
292         throws ServletException JavaDoc, IOException JavaDoc
293     {
294         AtomHandler handler = createAtomRequestHandler(req);
295         String JavaDoc userName = handler.getAuthenticatedUsername();
296         if (userName != null)
297         {
298             String JavaDoc[] pathInfo = getPathInfo(req);
299             try
300             {
301                 if (handler.isEntryURI(pathInfo))
302                 {
303                     handler.deleteEntry(pathInfo);
304                     res.setStatus(HttpServletResponse.SC_OK);
305                 }
306                 else if (handler.isResourceURI(pathInfo))
307                 {
308                     handler.deleteResource(pathInfo);
309                     res.setStatus(HttpServletResponse.SC_OK);
310                 }
311                 else
312                 {
313                     res.setStatus(HttpServletResponse.SC_NOT_FOUND);
314                 }
315             }
316             catch (Exception JavaDoc e)
317             {
318                 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
319                 e.printStackTrace(res.getWriter());
320                 mLogger.error(e);
321             }
322         }
323         else
324         {
325             res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
326         }
327     }
328     
329     //-----------------------------------------------------------------------------
330
/**
331      * Convenience method to return the PathInfo from the request.
332      */

333     protected String JavaDoc[] getPathInfo(HttpServletRequest JavaDoc request)
334     {
335         String JavaDoc mPathInfo = request.getPathInfo();
336         mPathInfo = (mPathInfo!=null) ? mPathInfo : "";
337         return StringUtils.split(mPathInfo,"/");
338     }
339
340     /**
341      * Utility method to make up for a Rome shortcoming:
342      * Rome can only serialize entire feeds, not individual elements
343      */

344     public static void serializeEntry(Entry entry, Writer JavaDoc writer)
345         throws IllegalArgumentException JavaDoc, FeedException, IOException JavaDoc
346     {
347         // Build a feed containing only the entry
348
List JavaDoc entries = new ArrayList JavaDoc();
349         entries.add(entry);
350         Feed feed1 = new Feed();
351         feed1.setFeedType(AtomServlet.FEED_TYPE);
352         feed1.setEntries(entries);
353         
354         // Get Rome to output feed as a JDOM document
355
WireFeedOutput wireFeedOutput = new WireFeedOutput();
356         Document feedDoc = wireFeedOutput.outputJDom(feed1);
357         
358         // Grab entry element from feed and get JDOM to serialize it
359
Element entryElement= (Element)feedDoc.getRootElement().getChildren().get(0);
360         XMLOutputter outputter = new XMLOutputter();
361         outputter.setFormat(Format.getPrettyFormat());
362         outputter.output(entryElement, writer);
363     }
364     
365     /**
366      * Utility method to make up for a Rome shortcoming:
367      * Rome can only parse Atom data with XML document root 'feed'
368      */

369     public static Entry parseEntry(Reader JavaDoc rd)
370         throws JDOMException, IOException JavaDoc, IllegalArgumentException JavaDoc, FeedException
371     {
372         // Parse entry into JDOM tree
373
SAXBuilder builder = new SAXBuilder();
374         Document entryDoc = builder.build(rd);
375         Element fetchedEntryElement = entryDoc.getRootElement();
376         fetchedEntryElement.detach();
377         
378         // Put entry into a JDOM document with 'feed' root so that Rome can handle it
379
Feed feed = new Feed();
380         feed.setFeedType(FEED_TYPE);
381         WireFeedOutput wireFeedOutput = new WireFeedOutput();
382         Document feedDoc = wireFeedOutput.outputJDom(feed);
383         feedDoc.getRootElement().addContent(fetchedEntryElement);
384         
385         WireFeedInput input = new WireFeedInput();
386         Feed parsedFeed = (Feed)input.build(feedDoc);
387         return (Entry)parsedFeed.getEntries().get(0);
388     }
389 }
390
Popular Tags