petascope.wcs2.Wcs2Servlet.java Source code

Java tutorial

Introduction

Here is the source code for petascope.wcs2.Wcs2Servlet.java

Source

/*
 * This file is part of rasdaman community.
 *
 * Rasdaman community is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Rasdaman community is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU  General Public License for more details.
 *
 * You should have received a copy of the GNU  General Public License
 * along with rasdaman community.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright 2003 - 2014 Peter Baumann / rasdaman GmbH.
 *
 * For more information please see <http://www.rasdaman.org>
 * or contact Peter Baumann via <baumann@rasdaman.com>.
 */
package petascope.wcs2;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import petascope.ConfigManager;
import petascope.HTTPRequest;
import petascope.core.DbMetadataSource;
import petascope.exceptions.WCSException;
import petascope.exceptions.ExceptionCode;
import petascope.exceptions.PetascopeException;
import petascope.exceptions.rasdaman.RasdamanException;
import petascope.exceptions.SecoreException;
import petascope.util.StringUtil;
import petascope.util.WcsUtil;
import petascope.util.response.MultipartResponse;
import petascope.wcs2.extensions.ExtensionsRegistry;
import petascope.wcs2.extensions.FormatExtension;
import petascope.wcs2.extensions.ProtocolExtension;
import petascope.wcs2.handlers.Response;

/**
 * A servlet handling WCS 2.0 requests.
 *
 * @author Dimitar Misev
 */
public class Wcs2Servlet extends HttpServlet {

    private static Logger log = LoggerFactory.getLogger(Wcs2Servlet.class);
    public static String LOCAL_SERVLET_ADDRESS = "http://localhost:8080/petascope/wcs2";
    // path to the default HTML response of the interface servlet
    private static final String USAGE_FILE = "/templates/wcs2-servlet.html";
    // String containing the HTML code for the default response
    private DbMetadataSource meta;
    private String usageMessage;

    @Override
    public void init() throws ServletException {

        String confDir = this.getServletContext().getInitParameter(ConfigManager.CONF_DIR);

        try {
            ConfigManager.getInstance(confDir);
        } catch (RasdamanException ex) {
            throw new ServletException(ex);
        }

        log.info("WCS 2.0 servlet starting");

        // Read servlet HTML usage message from disk
        try {
            usageMessage = FileUtils.readFileToString(new File(getServletContext().getRealPath(USAGE_FILE)));
        } catch (IOException e) {
            log.error("Error reading default servlet HTML response.", e);
            throw new ServletException("Error reading default servlet HTML response.", e);
        }

        try {
            meta = new DbMetadataSource(ConfigManager.METADATA_DRIVER, ConfigManager.METADATA_URL,
                    ConfigManager.METADATA_USER, ConfigManager.METADATA_PASS, false);
        } catch (Exception e) {
            log.error("Error initializing metadata database", e);
            throw new ServletException("Metadata database initialization error", e);
        }
    }

    /* Build a dictionary of parameter names and values, given a request string */
    private Map<String, String> buildParameterDictionary(String request) {
        HashMap<String, String> map = new HashMap<String, String>(3);
        if (request == null) {
            return map;
        }

        String[] pairs = request.split("&");
        String key = null, val = null;
        int pos = -1;
        for (int i = 0; i < pairs.length; i++) {
            pos = pairs[i].indexOf("=");
            if (pos != -1) {
                key = pairs[i].substring(0, pos);
                val = pairs[i].substring(pos + 1, pairs[i].length());
                map.put(key, val);
            }
        }

        return map;
    }

    private void setServletURL(HttpServletRequest req) {
        if ("".equals(ConfigManager.PETASCOPE_SERVLET_URL))
            ConfigManager.PETASCOPE_SERVLET_URL = req.getRequestURL().toString();
    }

    @Override
    public void doPost(HttpServletRequest req, HttpServletResponse res) {
        doGet(req, res);
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res) {

        long startTime = System.currentTimeMillis();

        setServletURL(req);
        meta.clearCache();

        String request = null;
        try {
            try {
                request = IOUtils.toString(req.getReader());

                log.trace("POST request length: " + req.getContentLength());
                log.trace("GET query string: " + req.getQueryString());
                log.trace("POST request body:\n" + request + "\n----------------------------------------\n");

                Map<String, String> params = buildParameterDictionary(request);
                if (params.containsKey("request")) {
                    request = params.get("request");
                }
                request = StringUtil.urldecode(request, req.getContentType());
                if (request == null || request.length() == 0) {
                    if (req.getQueryString() != null && req.getQueryString().length() > 0) {
                        request = req.getQueryString();
                        request = StringUtil.urldecode(request, req.getContentType());
                    } else {
                        printUsage(res, request);
                        return;
                    }
                }

                log.debug("Petascope Request: \n------START REQUEST--------\n" + request
                        + "\n------END REQUEST------\n");

                handleWcs2Request(request, res, req);
            } catch (WCSException e) {
                throw e;
            } catch (PetascopeException e) {
                throw new WCSException(e.getExceptionCode(), e.getMessage());
            } catch (SecoreException e) {
                throw new WCSException(e.getExceptionCode(), e);
            } catch (Exception e) {
                log.error("Runtime error : {}", e.getMessage());
                throw new WCSException(ExceptionCode.RuntimeError, "Runtime error while processing request", e);
            }
        } catch (WCSException e) {
            printError(res, request, e);
        }
        long elapsedTimeMillis = System.currentTimeMillis() - startTime;
        log.debug("Total Petascope Processing Time : " + elapsedTimeMillis);
    }

    /**
     * Handle WCS 2.0 request.
     *
     * @param input    request string
     * @param response
     * @throws WCSException in case of I/O error, or if the server is unable to handle the request
     */
    private void handleWcs2Request(String input, HttpServletResponse response, HttpServletRequest srvRequest)
            throws WCSException, PetascopeException, SecoreException {
        try {
            HTTPRequest request = this.parseUrl(srvRequest, input);
            log.info("Handling WCS 2.0 request");
            ProtocolExtension pext = ExtensionsRegistry.getProtocolExtension(request);
            if (pext == null) {
                throw new WCSException(ExceptionCode.NoApplicableCode,
                        "No protocol binding extension that can handle this request was found ");
            }
            log.info("Protocol binding extension found: {}", pext.getExtensionIdentifier());
            Response res = pext.handle(request, meta);

            OutputStream os = response.getOutputStream();
            response.setStatus(res.getExitCode());
            if (res.getXml() != null && res.getData() != null) {
                MultipartResponse multi = new MultipartResponse(response);
                multi.startPart(FormatExtension.MIME_GML);
                IOUtils.write(res.getXml(), os);
                multi.endPart();
                multi.startPart(res.getMimeType());
                IOUtils.write(res.getData(), os);
                multi.endPart();
                multi.finish();
            } else {
                try {
                    if (res.getMimeType() != null) {
                        response.setContentType(res.getMimeType());
                    } else {
                        //                    response.setContentType(WcsUtil.MIME_GML);
                        response.setContentType(FormatExtension.MIME_TEXT);
                    }
                    if (res.getXml() != null) {
                        IOUtils.write(res.getXml(), os);
                    } else if (res.getData() != null) {
                        IOUtils.write(res.getData(), os);
                    }
                } finally {
                    if (os != null) {
                        os.flush();
                        os.close();
                    }
                }
            }
        } catch (PetascopeException ex) {
            throw ex;
        } catch (SecoreException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new WCSException(ExceptionCode.RuntimeError, ex);
        }
    }

    private void printUsage(HttpServletResponse httpResponse, String request) throws IOException {
        PrintWriter out = httpResponse.getWriter();
        httpResponse.setContentType("text/html");
        out.write(usageMessage);
        out.flush();
    }

    private void printError(HttpServletResponse response, String message, Exception e) {
        PrintWriter out;
        try {
            out = response.getWriter();
        } catch (IOException e1) {
            log.error("Could not print exception because of IO error.", e1);
            return;
        }

        log.error("Error stack trace:", e);
        if (e instanceof WCSException) {
            String output = WcsUtil.exceptionToXml((WCSException) e);
            response.setStatus(((WCSException) e).getExceptionCode().getHttpErrorCode());
            response.setContentType("text/xml; charset=utf-8");
            out.println(output);
            out.close();
        } else {
            log.trace("setting response mimetype to text/html; charset=utf-8");
            response.setStatus(((WCSException) e).getExceptionCode().getHttpErrorCode());
            response.setContentType("text/html; charset=utf-8");
            log.trace("returning the following error message.", e);
            log.trace("end of error message");

            out.println("<html><head><title>PetaScope</title></head><body>");
            out.println("<h1>An error has occured</h1>");
            out.println("<p>" + message + "</p>");
            out.println("<p>Stack trace:<br/><small>");
            e.printStackTrace(out);
            out.println("</small></p></body></html>");
            out.close();
            log.trace("done with error");
        }
    }

    /**
     * Parses the HTTP servlet request into a Petascope Servlet Request
     *
     * @param srvRequest the http servlet request
     * @param request    the request string needed by parsers
     * @return complete ServletRequest
     */
    private HTTPRequest parseUrl(HttpServletRequest srvRequest, String request) {
        String contextPath = "", pathInfo = "";
        //get rid of the prefix slashes
        if (srvRequest.getContextPath().length() > 1) {
            contextPath = srvRequest.getContextPath().substring(1);
        }
        // [If no extra path info are specified in the request, .getPathInfo() returns `null`]
        if (srvRequest.getPathInfo() != null && srvRequest.getPathInfo().length() > 1) {
            pathInfo = srvRequest.getPathInfo().substring(1);
        }
        HTTPRequest srvReq = new HTTPRequest(contextPath, pathInfo, srvRequest.getQueryString(), request);
        return srvReq;
    }
}