com.stackframe.sarariman.RootServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.stackframe.sarariman.RootServlet.java

Source

/*
 * Copyright (C) 2013 StackFrame, LLC
 * This code is licensed under GPLv2.
 */
package com.stackframe.sarariman;

import com.google.common.io.CharStreams;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 *
 * @author mcculley
 */
public class RootServlet extends WebDAVServlet {

    private Document makePROPFINDResponseDepth0(String contextPath) {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document d = db.newDocument();
            d.setXmlStandalone(true);

            Element multistatus = d.createElementNS("DAV:", "multistatus");
            d.appendChild(multistatus);

            Element response = d.createElementNS("DAV:", "response");
            multistatus.appendChild(response);

            Element propstat = d.createElementNS("DAV:", "propstat");
            response.appendChild(propstat);

            Element prop = d.createElementNS("DAV:", "prop");
            propstat.appendChild(prop);

            Element addressBookHomeSet = d.createElementNS("urn:ietf:params:xml:ns:carddav",
                    "addressbook-home-set");
            prop.appendChild(addressBookHomeSet);

            Element href = d.createElementNS("DAV:", "href");
            addressBookHomeSet.appendChild(href);

            href.appendChild(d.createTextNode(String.format("%s/addressbooks/", contextPath)));

            Element getContentLength = d.createElementNS("DAV:", "getcontentlength");
            prop.appendChild(getContentLength);

            Element resourceType = d.createElementNS("DAV:", "resourcetype");
            prop.appendChild(resourceType);

            Element collection = d.createElementNS("DAV:", "collection");
            resourceType.appendChild(collection);

            Element creationDate = d.createElementNS("DAV:", "creationdate");
            prop.appendChild(creationDate);
            creationDate.appendChild(d.createTextNode(formattedDate()));

            Element getLastModified = d.createElementNS("DAV:", "getlastmodified");
            prop.appendChild(getLastModified);
            getLastModified.appendChild(d.createTextNode(formattedDate()));

            Element status = d.createElementNS("DAV:", "status");
            propstat.appendChild(status);
            status.appendChild(d.createTextNode("HTTP/1.1 200 OK"));

            return d;
        } catch (ParserConfigurationException e) {
            throw new AssertionError(e);
        }
    }

    private Document makePROPFINDResponseDepth1(String contextPath) {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document d = db.newDocument();
            d.setXmlStandalone(true);

            Element multistatus = d.createElementNS("DAV:", "multistatus");
            d.appendChild(multistatus);

            Element response = d.createElementNS("DAV:", "response");
            multistatus.appendChild(response);

            Element href = d.createElementNS("DAV:", "href");
            response.appendChild(href);

            href.appendChild(d.createTextNode(String.format("%s/addressbooks/", contextPath)));

            Element propstat = d.createElementNS("DAV:", "propstat");
            response.appendChild(propstat);

            Element prop = d.createElementNS("DAV:", "prop");
            propstat.appendChild(prop);

            Element getContentLength = d.createElementNS("DAV:", "getcontentlength");
            prop.appendChild(getContentLength);

            Element resourceType = d.createElementNS("DAV:", "resourcetype");
            prop.appendChild(resourceType);

            Element collection = d.createElementNS("DAV:", "collection");
            resourceType.appendChild(collection);

            Element creationDate = d.createElementNS("DAV:", "creationdate");
            prop.appendChild(creationDate);
            creationDate.appendChild(d.createTextNode(formattedDate()));

            Element getLastModified = d.createElementNS("DAV:", "getlastmodified");
            prop.appendChild(getLastModified);
            getLastModified.appendChild(d.createTextNode(formattedDate()));

            Element status = d.createElementNS("DAV:", "status");
            propstat.appendChild(status);
            status.appendChild(d.createTextNode("HTTP/1.1 200 OK"));

            return d;
        } catch (ParserConfigurationException e) {
            throw new AssertionError(e);
        }
    }

    private static void serialize(Document document, Writer writer) {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        transformerFactory.setAttribute("indent-number", new Integer(4));
        try {
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            StreamResult result = new StreamResult(writer);
            transformer.transform(new DOMSource(document), result);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String serialize(Document document) {
        StringWriter sw = new StringWriter();
        serialize(document, sw);
        return sw.toString();
    }

    private Iterable<String> headers(HttpServletRequest request) {
        Collection<String> headers = new ArrayList<String>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            Enumeration<String> values = request.getHeaders(name);
            while (values.hasMoreElements()) {
                String value = values.nextElement();
                headers.add(name + ": " + value);
            }
        }

        return headers;
    }

    @Override
    protected void doPropfind(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.err.println("in RootServlet::doPropfind pathInfo=" + request.getPathInfo() + " requestURI="
                + request.getRequestURI());
        String requestDocument = CharStreams.toString(new InputStreamReader(request.getInputStream(), "UTF-8"));
        System.err.println("in RootServlet::doPropfind headers='" + headers(request) + "'");
        String depth = request.getHeader("depth");
        System.err.println("in RootServlet::doPropfind depth='" + depth + "'");
        System.err.println("in RootServlet::doPropfind requestDocument='" + requestDocument + "'");
        Document d;
        if (depth.equals("0")) {
            d = makePROPFINDResponseDepth0(request.getContextPath());
        } else {
            d = makePROPFINDResponseDepth1(request.getContextPath());
        }

        System.err.println("going to send response:");
        System.err.println(serialize(d));
        PrintWriter writer = response.getWriter();
        serialize(d, writer);
        writer.close();
        response.setStatus(207);
    }

    private static String formattedDate() {
        return formattedDate(new Date());
    }

    private static String formattedDate(Date date) {
        // TimeZone tz = TimeZone.getTimeZone("UTC");
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
        //df.setTimeZone(tz);
        return df.format(date);
    }

    @Override
    protected void doOptions(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setHeader("DAV", "1, addressbook");
    }

    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("home.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("home.jsp").forward(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "servlet for the root page";
    }

}