org.geoserver.wms.web.data.OpenLayersPreviewPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.wms.web.data.OpenLayersPreviewPanel.java

Source

/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
 * (c) 2001 - 2013 OpenPlans
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.wms.web.data;

import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.wicket.Component;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.head.CssHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.head.OnLoadHeaderItem;
import org.apache.wicket.markup.html.IHeaderContributor;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.config.GeoServerDataDirectory;
import org.geoserver.ows.URLMangler.URLType;
import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resources;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.web.wicket.SimpleAjaxLink;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.util.logging.Logging;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Style page tab for displaying an OpenLayers 2 layer preview and legend.
 * Includes a link for changing the current preview layer.
 */
public class OpenLayersPreviewPanel extends StyleEditTabPanel implements IHeaderContributor {

    private static final long serialVersionUID = -8742721113748106000L;

    static final Logger LOGGER = Logging.getLogger(OpenLayersPreviewPanel.class);
    final static Configuration templates;

    static {
        templates = new Configuration();
        templates.setClassForTemplateLoading(OpenLayersPreviewPanel.class, "");
        templates.setObjectWrapper(new DefaultObjectWrapper());
    }

    final Random rand = new Random();
    final Component olPreview;

    public OpenLayersPreviewPanel(String id, AbstractStylePage parent) {
        super(id, parent);
        this.olPreview = new WebMarkupContainer("olPreview").setOutputMarkupId(true);

        // Change layer link
        PropertyModel<String> layerNameModel = new PropertyModel<String>(parent.getLayerModel(), "prefixedName");
        add(new SimpleAjaxLink<String>("change.layer", layerNameModel) {
            private static final long serialVersionUID = 7341058018479354596L;

            public void onClick(AjaxRequestTarget target) {
                ModalWindow popup = parent.getPopup();

                popup.setInitialHeight(400);
                popup.setInitialWidth(600);
                popup.setTitle(new Model<String>("Choose layer to edit"));
                popup.setContent(new LayerChooser(popup.getContentId(), parent));
                popup.show(target);
            }
        });
        add(olPreview);
        setOutputMarkupId(true);

        try {
            ensureLegendDecoration();
        } catch (IOException e) {
            LOGGER.log(Level.WARNING,
                    "Failed to put legend layout file in the data directory, the legend decoration will not appear",
                    e);
        }
    }

    private void ensureLegendDecoration() throws IOException {
        GeoServerDataDirectory dd = GeoServerApplication.get().getBeanOfType(GeoServerDataDirectory.class);
        Resource layouts = dd.get("layouts");
        Resource legend = layouts.get("css-legend.xml");
        if (!Resources.exists(legend)) {
            String legendLayout = IOUtils
                    .toString(OpenLayersPreviewPanel.class.getResourceAsStream("css-legend.xml"));
            OutputStream os = legend.out();
            try {
                IOUtils.write(legendLayout, os);
            } finally {
                os.close();
            }
        }

    }

    public void renderHead(IHeaderResponse header) {
        super.renderHead(header);
        try {
            renderHeaderCss(header);
            renderHeaderScript(header);
        } catch (IOException e) {
            throw new WicketRuntimeException(e);
        } catch (TemplateException e) {
            throw new WicketRuntimeException(e);
        }
    }

    private void renderHeaderCss(IHeaderResponse header) throws IOException, TemplateException {
        Map<String, Object> context = new HashMap<String, Object>();
        context.put("id", olPreview.getMarkupId());
        Template template = templates.getTemplate("ol-style.ftl");
        StringWriter css = new java.io.StringWriter();
        template.process(context, css);
        header.render(CssHeaderItem.forCSS(css.toString(), null));
    }

    private void renderHeaderScript(IHeaderResponse header) throws IOException, TemplateException {
        Map<String, Object> context = new HashMap<String, Object>();
        ReferencedEnvelope bbox = getStylePage().getLayerInfo().getResource().getLatLonBoundingBox();
        WorkspaceInfo workspace = getStylePage().getStyleInfo().getWorkspace();
        context.put("minx", bbox.getMinX());
        context.put("miny", bbox.getMinY());
        context.put("maxx", bbox.getMaxX());
        context.put("maxy", bbox.getMaxY());
        context.put("id", olPreview.getMarkupId());
        context.put("layer", getStylePage().getLayerInfo().getResource().getName());
        context.put("style", getStylePage().getStyleInfo().getName());
        if (workspace != null) {
            context.put("styleWorkspace", workspace.getName());
        }
        context.put("cachebuster", rand.nextInt());
        context.put("resolution", Math.max(bbox.getSpan(0), bbox.getSpan(1)) / 256.0);
        HttpServletRequest req = GeoServerApplication.get().servletRequest();
        String base = ResponseUtils.baseURL(req);
        String baseUrl = ResponseUtils.buildURL(base, "/", null, URLType.RESOURCE);
        context.put("baseUrl", canonicUrl(baseUrl));
        Template template = templates.getTemplate("ol-load.ftl");
        StringWriter script = new java.io.StringWriter();
        template.process(context, script);
        header.render(JavaScriptHeaderItem
                .forUrl(ResponseUtils.buildURL(base, "/openlayers/OpenLayers.js", null, URLType.RESOURCE)));
        header.render(OnLoadHeaderItem.forScript(script.toString()));
    }

    /**
     * Makes sure the url does not end with "/", otherwise we would have URL lik
     * "http://localhost:8080/geoserver//wms?LAYERS=..." and Jetty 6.1 won't digest them...
     * 
     * @param baseUrl
     *
     */
    private String canonicUrl(String baseUrl) {
        if (baseUrl.endsWith("/")) {
            return baseUrl.substring(0, baseUrl.length() - 1);
        } else {
            return baseUrl;
        }
    }

    public String getUpdateCommand() throws IOException, TemplateException {
        Map<String, Object> context = new HashMap<String, Object>();
        context.put("id", olPreview.getMarkupId());
        context.put("cachebuster", rand.nextInt());

        Template template = templates.getTemplate("ol-update.ftl");
        StringWriter script = new java.io.StringWriter();
        template.process(context, script);
        return script.toString();
    }
}