view flys-client/src/main/java/de/intevation/flys/client/server/MapPrintServiceImpl.java @ 2504:425bc486a40f

Generate map print spec dynamically from artifact flys-client/trunk@4349 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 04 May 2012 18:31:03 +0000
parents e3bd1f412421
children 47d07709ba09
line wrap: on
line source
package de.intevation.flys.client.server;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.OutputStream;

import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.LinkedHashMap;

import javax.servlet.ServletException;

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

import de.intevation.artifacts.common.ArtifactNamespaceContext;

import de.intevation.artifacts.common.utils.ClientProtocolUtils;
import de.intevation.artifacts.common.utils.JSON;
import de.intevation.artifacts.common.utils.StringUtils;
import de.intevation.artifacts.common.utils.XMLUtils;

import de.intevation.artifacts.httpclient.exceptions.ConnectionException;

import de.intevation.artifacts.httpclient.http.HttpClient;
import de.intevation.artifacts.httpclient.http.HttpClientImpl;

import de.intevation.flys.client.shared.model.MapConfig;

import org.apache.log4j.Logger;

import org.mapfish.print.MapPrinter;

import org.mapfish.print.output.OutputFactory;
import org.mapfish.print.output.OutputFormat;

import org.mapfish.print.utils.PJsonObject;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class MapPrintServiceImpl
extends      HttpServlet
{
    private static final Logger log =
        Logger.getLogger(MapPrintServiceImpl.class);

    protected static String generateSpec(
        Document document,
        double minX, double minY,
        double maxX, double maxY
    ) {
        System.err.println(XMLUtils.toString(document));
        MapConfig mapConfig = MapHelper.parseConfig(document);

        Map<String, Object> spec = new LinkedHashMap<String, Object>();
        spec.put("layout", "A4 portrait");
        spec.put("title", "FLYS Druck");
        spec.put("srs", "EPSG:" + mapConfig.getSrid());
        spec.put("dpi", Integer.valueOf(254));
        spec.put("units", "degrees");
        spec.put("outputFormat", "pdf");

        List<Object> layers = new ArrayList<Object>();

        String ns = ArtifactNamespaceContext.NAMESPACE_URI;

        NodeList facets = document.getElementsByTagNameNS(ns, "facet");

        for (int i = 0, N = facets.getLength(); i < N; ++i) {
            Element element = (Element)facets.item(i);
            if (!element.getParentNode().getLocalName().equals("layers")) {
                continue;
            }
            Map<String, Object> layer = new LinkedHashMap<String, Object>();

            layer.put("type", "WMS");
            List<Object> subLayers = new ArrayList<Object>(1);
            subLayers.add(element.getAttributeNS(ns, "layers"));
            layer.put("layers", subLayers);
            layer.put("baseURL", element.getAttributeNS(ns, "url"));
            layer.put("format", "image/png");

            layers.add(layer);
        }

        spec.put("layers", layers);
        spec.put("name", "Name");

        List<Object> pages = new ArrayList<Object>(1);

        spec.put("pages", pages);

        Map<String, Object> page = new LinkedHashMap<String, Object>();

        List<Object> bounds = new ArrayList<Object>(4);
        bounds.add(Double.valueOf(minX));
        bounds.add(Double.valueOf(minY));
        bounds.add(Double.valueOf(maxX));
        bounds.add(Double.valueOf(maxY));

        page.put("bbox", bounds);

        page.put("mapTitle", "FLYS Karte");
        page.put("comment", "Eine mit FLYS gedruckte Karte.");
        page.put("rotation", Integer.valueOf(0));

        pages.add(page);

        return JSON.toJSONString(spec);
    }


    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) 
    throws  ServletException, IOException
    {
        log.info("MapPrintServiceImpl.doGet");

        String uuid = req.getParameter("uuid");

        if (uuid == null || !StringUtils.checkUUID(uuid)) {
            throw new ServletException("Missing or misspelled UUID");
        }

        String minXS = req.getParameter("minx");
        String maxXS = req.getParameter("maxx");
        String minYS = req.getParameter("miny");
        String maxYS = req.getParameter("maxy");

        if (minXS == null || maxXS == null
        ||  minYS == null || maxYS == null) {
            throw new ServletException("Missing minX, minY, maxX or maxY");
        }

        double minX, maxX, minY, maxY;

        try {
            minX = Double.parseDouble(minXS);
            minY = Double.parseDouble(minYS);
            maxX = Double.parseDouble(maxXS);
            maxY = Double.parseDouble(maxYS);
        }
        catch (NumberFormatException nfe) {
            throw new ServletException("Misspelled minX, minY, maxX or maxY");
        }

        String mapType = req.getParameter("maptype");

        if (mapType == null || !mapType.equals("map")) {
            mapType = "floodmap";
        }

        String url = getURL();

        Document request = ClientProtocolUtils.newOutCollectionDocument(
            uuid, mapType, mapType);

        Document result;
        try {
            HttpClient client = new HttpClientImpl(url);
            InputStream    is = client.collectionOut(request, uuid, mapType);
            try {
                result = XMLUtils.parseDocument(is);
            }
            finally {
                is.close();
            }
        }
        catch (ConnectionException ce) {
            log.error(ce);
            throw new ServletException(ce);
        }

        String spec = generateSpec(
            result,
            minX, minY,
            maxX, maxY);

        if (log.isDebugEnabled()) {
            log.debug(spec);
            //System.err.println(spec);
        }

        producePDF(spec, resp);
    }

    protected String getURL() throws ServletException {
        String url = getServletContext().getInitParameter("server-url");
        if (url == null) {
            throw new ServletException("Missing server-url");
        }
        return url;
    }

    protected MapPrinter getMapPrinter() throws ServletException, IOException {
        String configPath = getInitParameter("config");
        if (configPath == null) {
            throw new ServletException("Missing configuration in web.xml");
        }

        File configFile = new File(configPath);
        if (!configFile.isAbsolute()) {
            configFile = new File(getServletContext().getRealPath(configPath));
        }

        if (!configFile.isFile() || !configFile.canRead()) {
            throw new ServletException("Cannot read '" + configFile + "'");
        }

        return new MapPrinter(configFile);
    }


    protected void producePDF(String json, HttpServletResponse resp)
    throws ServletException, IOException
    {
        PJsonObject jsonSpec = MapPrinter.parseSpec(json);

        MapPrinter printer = getMapPrinter();

        OutputFormat outputFormat = OutputFactory.create(
            printer.getConfig(), jsonSpec);

        resp.setHeader("Content-Disposition", "attachment;filename=print.pdf");
        resp.setHeader("Content-Type", "application/pdf");

        // XXX: Streaming the generated PDF directly
        // to the request out does not work. :-/
        File tmpFile = File.createTempFile("map-printing", null);

        try {
            OutputStream out =
                new BufferedOutputStream(
                new FileOutputStream(tmpFile));
            try {
                outputFormat.print(printer, jsonSpec, out, "");
                out.flush();
            }
            catch (Exception e) {
                log.error(e);
                throw new ServletException(e);
            }
            finally {
                printer.stop();
                out.close();
            }
            InputStream in =
                new BufferedInputStream(
                new FileInputStream(tmpFile));
            out = resp.getOutputStream();
            try {
                byte [] buf = new byte[4096];
                int r;
                while ((r = in.read(buf)) >= 0) {
                    out.write(buf, 0, r);
                }
                out.flush();
            }
            finally {
                in.close();
                out.close();
            }
        }
        finally {
            if (tmpFile.exists()) {
                tmpFile.delete();
            }
        }
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org