Package org.apache.roller.webservices.atomprotocol

Source Code of org.apache.roller.webservices.atomprotocol.AtomServlet

/*
* 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.atomprotocol;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import com.sun.syndication.feed.atom.Entry;
import com.sun.syndication.feed.atom.Feed;
import com.sun.syndication.feed.atom.Link;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.WireFeedInput;
import com.sun.syndication.io.WireFeedOutput;
import java.io.BufferedReader;
import java.io.StringWriter;
import org.jdom.Namespace;
import org.apache.roller.config.RollerConfig;

/**
* Atom Servlet implements Atom by calling a Roller independent handler.
* @web.servlet name="AtomServlet"
* @web.servlet-mapping url-pattern="/roller-services/app/*"
* @author David M Johnson
*/
public class AtomServlet extends HttpServlet {
    public static final String FEED_TYPE = "atom_1.0";
   
    private static Log mLogger =
            LogFactory.getFactory().getInstance(AtomServlet.class);
   
    //-----------------------------------------------------------------------------
    /**
     * Create an Atom request handler.
     * TODO: make AtomRequestHandler implementation configurable.
     */
    private AtomHandler createAtomRequestHandler(HttpServletRequest request)
    throws ServletException {
        boolean enabled = RollerConfig.getBooleanProperty(
            "webservices.atomprotocol.enabled");
        if (!enabled) {
            throw new ServletException("ERROR: Atom protocol not enabled");
        }
        return new RollerAtomHandler(request);
    }
   
    //-----------------------------------------------------------------------------
    /**
     * Handles an Atom GET by calling handler and writing results to response.
     */
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
        AtomHandler handler = createAtomRequestHandler(req);
        String userName = handler.getAuthenticatedUsername();
        if (userName != null) {
            String[] pathInfo = getPathInfo(req);
            try {
                if (handler.isIntrospectionURI(pathInfo)) {
                    // return an Atom Service document
                    AtomService service = handler.getIntrospection();
                    Document doc = AtomService.serviceToDocument(service);
                    res.setContentType("application/atomserv+xml; charset=utf-8");
                    Writer writer = res.getWriter();
                    XMLOutputter outputter = new XMLOutputter();
                    outputter.setFormat(Format.getPrettyFormat());
                    outputter.output(doc, writer);
                    writer.close();
                    res.setStatus(HttpServletResponse.SC_OK);
                }
                else if (handler.isCollectionURI(pathInfo)) {
                    // return a collection
                    Feed col = handler.getCollection(pathInfo);
                    col.setFeedType(FEED_TYPE);
                    WireFeedOutput wireFeedOutput = new WireFeedOutput();
                    Document feedDoc = wireFeedOutput.outputJDom(col);
                    res.setContentType("application/atom+xml; charset=utf-8");
                    Writer writer = res.getWriter();
                    XMLOutputter outputter = new XMLOutputter();
                    outputter.setFormat(Format.getPrettyFormat());
                    outputter.output(feedDoc, writer);
                    writer.close();
                    res.setStatus(HttpServletResponse.SC_OK);
                }
                else if (handler.isEntryURI(pathInfo)) {
                    // return an entry
                    Entry entry = handler.getEntry(pathInfo);
                    if (entry != null) {
                        res.setContentType("application/atom+xml; charset=utf-8");
                        Writer writer = res.getWriter();
                        serializeEntry(entry, writer);
                        writer.close();
                    } else {
                        res.setStatus(HttpServletResponse.SC_NOT_FOUND);
                    }
                } else {
                    res.setStatus(HttpServletResponse.SC_NOT_FOUND);
                }
            } catch (AtomException ae) {
                res.setStatus(ae.getStatus());
                mLogger.debug(ae);
            } catch (Exception ae) {
                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                mLogger.debug(ae);
            }
        } else {
            res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
            res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }
   
    //-----------------------------------------------------------------------------
    /**
     * Handles an Atom POST by calling handler to identify URI, reading/parsing
     * data, calling handler and writing results to response.
     */
    protected void doPost(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
        AtomHandler handler = createAtomRequestHandler(req);
        String userName = handler.getAuthenticatedUsername();
        if (userName != null) {
            String[] pathInfo = getPathInfo(req);
            try {
                if (handler.isCollectionURI(pathInfo)) {
                   
                    if (req.getContentType().startsWith("application/atom+xml")) {

                        // parse incoming entry
                        Entry unsavedEntry = parseEntry(new BufferedReader(
                            new InputStreamReader(
                                req.getInputStream(), "UTF-8")));

                        // call handler to post it
                        Entry savedEntry = handler.postEntry(pathInfo, unsavedEntry);
                       
                        // return alternate link as Location header
                        Iterator links = savedEntry.getOtherLinks().iterator();
                        while (links.hasNext()) {
                            Link link = (Link) links.next();
                            if (link.getRel().equals("edit") || link.getRel() == null) {
                                res.addHeader("Location", link.getHref());
                                break;
                            }
                        }
                        // write entry back out to response
                        res.setStatus(HttpServletResponse.SC_CREATED);
                        res.setContentType("application/atom+xml; charset=utf-8");
                        Writer writer = res.getWriter();
                        serializeEntry(savedEntry, writer);
                        writer.close();
                   
                    } else if (req.getContentType() != null) {
                        // get incoming title and slug from HTTP header
                        String title = req.getHeader("Title");
                        String slug = req.getHeader("Slug");

                        // hand input stream of to hander to post file
                        Entry resource = handler.postMedia(
                            pathInfo, title, slug, req.getContentType(), req.getInputStream());
                       
                        res.setStatus(HttpServletResponse.SC_CREATED);
                        com.sun.syndication.feed.atom.Content content =
                            (com.sun.syndication.feed.atom.Content)resource.getContents().get(0);

                        // return alternate link as Location header
                        Iterator links = resource.getOtherLinks().iterator();
                        while (links.hasNext()) {
                            Link link = (Link) links.next();
                            if (link.getRel().equals("edit") || link.getRel() == null) {
                                res.addHeader("Location", link.getHref());
                                break;
                            }
                        }
                        Writer writer = res.getWriter();
                        serializeEntry(resource, writer);
                        writer.close();
                    } else {
                        res.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
                    }
                   
                } else {
                    res.setStatus(HttpServletResponse.SC_NOT_FOUND);
                }
            } catch (AtomException ae) {
                res.setStatus(ae.getStatus());
                mLogger.debug(ae);
            } catch (Exception ae) {
                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                mLogger.debug(ae);
            }
        } else {
            res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
            res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }
   
    //-----------------------------------------------------------------------------
    /**
     * Handles an Atom PUT by calling handler to identify URI, reading/parsing
     * data, calling handler and writing results to response.
     */
    protected void doPut(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
        AtomHandler handler = createAtomRequestHandler(req);
        String userName = handler.getAuthenticatedUsername();
        if (userName != null) {
            String[] pathInfo = getPathInfo(req);
            try {
                if (handler.isEntryURI(pathInfo)) {
                   
                    // parse incoming entry
                    Entry unsavedEntry = parseEntry(new BufferedReader(
                        new InputStreamReader(
                            req.getInputStream(), "UTF-8")));
                   
                    // call handler to put entry
                    Entry updatedEntry = handler.putEntry(pathInfo, unsavedEntry);
                   
                    // write entry back out to response
                    res.setContentType("application/atom+xml; charset=utf-8");
                    Writer writer = res.getWriter();
                    serializeEntry(updatedEntry, writer);
                    res.setStatus(HttpServletResponse.SC_OK);
                    writer.close();
                   
                } else if (handler.isMediaEditURI(pathInfo)) {
                   
                    // hand input stream to handler
                    Entry updatedEntry = handler.putMedia(
                        pathInfo, req.getContentType(), req.getInputStream());
                                       
                    // write entry back out to response
                    res.setContentType("application/atom+xml; charset=utf-8");
                    Writer writer = res.getWriter();
                    serializeEntry(updatedEntry, writer);
                    writer.close();
                    res.setStatus(HttpServletResponse.SC_OK);
                   
                } else {
                    res.setStatus(HttpServletResponse.SC_NOT_FOUND);
                }
            } catch (AtomException ae) {
                res.setStatus(ae.getStatus());
                mLogger.debug(ae);
            } catch (Exception ae) {
                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                mLogger.debug(ae);
            }
        } else {
            res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
            res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }
   
    //-----------------------------------------------------------------------------
    /**
     * Handle Atom DELETE by calling appropriate handler.
     */
    protected void doDelete(HttpServletRequest req, HttpServletResponse res)
    throws ServletException, IOException {
        AtomHandler handler = createAtomRequestHandler(req);
        String userName = handler.getAuthenticatedUsername();
        if (userName != null) {
            String[] pathInfo = getPathInfo(req);
            try {
                if (handler.isEntryURI(pathInfo)) {
                    handler.deleteEntry(pathInfo);
                    res.setStatus(HttpServletResponse.SC_OK);
                }
                else {
                    res.setStatus(HttpServletResponse.SC_NOT_FOUND);
                }
            } catch (AtomException ae) {
                res.setStatus(ae.getStatus());
                mLogger.debug(ae);
            } catch (Exception ae) {
                res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                mLogger.debug(ae);
            }
        } else {
            res.setHeader("WWW-Authenticate", "BASIC realm=\"Roller\"");
            res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }
   
    //-----------------------------------------------------------------------------
    /**
     * Convenience method to return the PathInfo from the request.
     */
    protected String[] getPathInfo(HttpServletRequest request) {
        String mPathInfo = request.getPathInfo();
        mPathInfo = (mPathInfo!=null) ? mPathInfo : "";
        return StringUtils.split(mPathInfo,"/");
    }
   
    /**
     * Serialize entry to writer.
     */
    public static void serializeEntry(Entry entry, Writer writer)
    throws IllegalArgumentException, FeedException, IOException {
        // Build a feed containing only the entry
        List entries = new ArrayList();
        entries.add(entry);
        Feed feed1 = new Feed();
        feed1.setFeedType(AtomServlet.FEED_TYPE);
        feed1.setEntries(entries);
       
        // Get Rome to output feed as a JDOM document
        WireFeedOutput wireFeedOutput = new WireFeedOutput();
        Document feedDoc = wireFeedOutput.outputJDom(feed1);
       
        // Grab entry element from feed and get JDOM to serialize it
        Element entryElement= (Element)feedDoc.getRootElement().getChildren().get(0);
       
        // Add our own namespaced element, so we can determine if we can
        // count on client to preserve foreign markup as it should.
        Element rollerElement = new Element("atom-draft",
            "http://rollerweblogger.org/namespaces/app");
        rollerElement.setText("9");
        entryElement.addContent(rollerElement);
       
        XMLOutputter outputter = new XMLOutputter();
        outputter.setFormat(Format.getPrettyFormat());
       
        if (mLogger.isDebugEnabled()) {
            StringWriter sw = new StringWriter();
            outputter.output(entryElement, sw);
            mLogger.debug(sw.toString());
            writer.write(sw.toString());
        } else {
            outputter.output(entryElement, writer);
        }       
    }
   
    /**
     * Parse entry from reader.
     */
    public static Entry parseEntry(Reader rd)
        throws JDOMException, IOException, IllegalArgumentException, FeedException {
        // Parse entry into JDOM tree
        SAXBuilder builder = new SAXBuilder();
        Document entryDoc = builder.build(rd);
        Element fetchedEntryElement = entryDoc.getRootElement();
        fetchedEntryElement.detach();
       
        // Put entry into a JDOM document with 'feed' root so that Rome can handle it
        Feed feed = new Feed();
        feed.setFeedType(FEED_TYPE);
        WireFeedOutput wireFeedOutput = new WireFeedOutput();
        Document feedDoc = wireFeedOutput.outputJDom(feed);
        feedDoc.getRootElement().addContent(fetchedEntryElement);
       
        // Check for our special namespaced element. If it's there, then we
        // know that client is not preserving foreign markup.
        Namespace ns = Namespace.getNamespace(
            "http://rollerweblogger.org/namespaces/app");
        Element rollerElement = fetchedEntryElement.getChild("atom-draft", ns);
        if (rollerElement == null) {
            mLogger.debug("Client is NOT preserving foreign markup");
        }
       
        WireFeedInput input = new WireFeedInput();
        Feed parsedFeed = (Feed)input.build(feedDoc);
        return (Entry)parsedFeed.getEntries().get(0);
    }
}
TOP

Related Classes of org.apache.roller.webservices.atomprotocol.AtomServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.