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

Java tutorial

Introduction

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

Source

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

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.NumberTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.validation.IValidatable;
import org.apache.wicket.validation.IValidator;
import org.apache.wicket.validation.ValidationError;
import org.apache.wicket.validation.validator.RangeValidator;
import org.geoserver.catalog.LegendInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.catalog.impl.LegendInfoImpl;
import org.geoserver.config.GeoServer;
import org.geoserver.ows.util.ResponseUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.web.wicket.GeoServerAjaxFormLink;

/**
 * Allows setting the data for using an ExternalImage
 * 
 * 
 */
@SuppressWarnings("serial")
public class ExternalGraphicPanel extends Panel {
    private static final long serialVersionUID = 5098470683723890874L;

    private TextField<String> onlineResource;
    private TextField<String> format;
    private TextField<Integer> width;
    private TextField<Integer> height;
    private WebMarkupContainer table;
    private GeoServerAjaxFormLink autoFill;

    private Form<StyleInfo> showhideForm;

    private AjaxButton show;
    private AjaxButton hide;

    private Model<String> showhideStyleModel = new Model<String>("");

    /**
     * @param id
     * @param model Must return a {@link ResourceInfo}
     */
    public ExternalGraphicPanel(String id, final CompoundPropertyModel<StyleInfo> styleModel,
            final Form<?> styleForm) {
        super(id, styleModel);

        // container for ajax updates
        final WebMarkupContainer container = new WebMarkupContainer("externalGraphicContainer");
        container.setOutputMarkupId(true);
        add(container);

        table = new WebMarkupContainer("list");
        table.setOutputMarkupId(true);

        IModel<String> bind = styleModel.bind("legend.onlineResource");
        onlineResource = new TextField<String>("onlineResource", bind);
        onlineResource.add(new IValidator<String>() {
            final List<String> EXTENSIONS = Arrays.asList(new String[] { "png", "gif", "jpeg", "jpg" });

            @Override
            public void validate(IValidatable<String> input) {
                String value = input.getValue();
                int last = value == null ? -1 : value.lastIndexOf('.');
                if (last == -1 || !EXTENSIONS.contains(value.substring(last + 1).toLowerCase())) {
                    ValidationError error = new ValidationError();
                    error.setMessage("Not an image");
                    error.addKey("nonImage");
                    input.error(error);
                    return;
                }
                URI uri = null;
                try {
                    uri = new URI(value);
                } catch (URISyntaxException e1) {
                    // Unable to check if absolute
                }
                if (uri != null && uri.isAbsolute()) {
                    try {
                        String baseUrl = baseURL(onlineResource.getForm());
                        if (!value.startsWith(baseUrl)) {
                            onlineResource.warn("Recommend use of styles directory at " + baseUrl);
                        }
                        URL url = uri.toURL();
                        URLConnection conn = url.openConnection();
                        if ("text/html".equals(conn.getContentType())) {
                            ValidationError error = new ValidationError();
                            error.setMessage("Unable to access image");
                            error.addKey("imageUnavailable");
                            input.error(error);
                            return; // error message back!
                        }
                    } catch (MalformedURLException e) {
                        ValidationError error = new ValidationError();
                        error.setMessage("Unable to access image");
                        error.addKey("imageUnavailable");
                        input.error(error);
                    } catch (IOException e) {
                        ValidationError error = new ValidationError();
                        error.setMessage("Unable to access image");
                        error.addKey("imageUnavailable");
                        input.error(error);
                    }
                    return; // no further checks possible
                } else {
                    GeoServerResourceLoader resources = GeoServerApplication.get().getResourceLoader();
                    try {
                        File styles = resources.find("styles");
                        String[] path = value.split(Pattern.quote(File.separator));
                        WorkspaceInfo wsInfo = styleModel.getObject().getWorkspace();
                        File test = null;
                        if (wsInfo != null) {
                            String wsName = wsInfo.getName();
                            List<String> list = new ArrayList();
                            list.addAll(Arrays.asList("workspaces", wsName, "styles"));
                            list.addAll(Arrays.asList(path));
                            test = resources.find(list.toArray(new String[list.size()]));
                        }
                        if (test == null) {
                            test = resources.find(styles, path);
                        }
                        if (test == null) {
                            ValidationError error = new ValidationError();
                            error.setMessage("File not found in styles directory");
                            error.addKey("imageNotFound");
                            input.error(error);
                        }
                    } catch (IOException e) {
                        ValidationError error = new ValidationError();
                        error.setMessage("File not found in styles directory");
                        error.addKey("imageNotFound");
                        input.error(error);
                    }
                }
            }
        });
        onlineResource.setOutputMarkupId(true);
        table.add(onlineResource);

        // add the autofill button
        autoFill = new GeoServerAjaxFormLink("autoFill", styleForm) {
            @Override
            public void onClick(AjaxRequestTarget target, Form<?> form) {

                URLConnection conn = getExternalGraphic(target, form);
                if (conn == null) {
                    ValidationError error = new ValidationError();
                    error.setMessage("Unable to access image");
                    error.addKey("imageUnavailable");
                    onlineResource.error(error);
                } else {
                    format.setModelValue(new String[] { conn.getContentType() });
                    BufferedImage image;
                    try {
                        image = ImageIO.read(conn.getInputStream());
                        width.setModelValue(new String[] { "" + image.getWidth() });
                        height.setModelValue(new String[] { "" + image.getHeight() });
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    target.add(format);
                    target.add(width);
                    target.add(height);
                }
            }
        };

        table.add(autoFill);

        format = new TextField<String>("format", styleModel.bind("legend.format"));
        format.setOutputMarkupId(true);
        table.add(format);

        width = new TextField<Integer>("width", styleModel.bind("legend.width"), Integer.class);
        width.add(RangeValidator.minimum(0));
        width.setRequired(true);
        width.setOutputMarkupId(true);
        table.add(width);

        height = new TextField<Integer>("height", styleModel.bind("legend.height"), Integer.class);
        height.add(RangeValidator.minimum(0));
        height.setRequired(true);
        height.setOutputMarkupId(true);
        table.add(height);

        table.add(new AttributeModifier("style", showhideStyleModel));

        container.add(table);

        showhideForm = new Form<StyleInfo>("showhide") {
            @Override
            protected void onSubmit() {
                super.onSubmit();
            }
        };
        showhideForm.setMarkupId("showhideForm");
        container.add(showhideForm);
        showhideForm.setMultiPart(true);

        show = new AjaxButton("show") {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                updateVisibility(true);
                target.add(ExternalGraphicPanel.this);
            }
        };
        container.add(show);
        showhideForm.add(show);

        hide = new AjaxButton("hide") {
            private static final long serialVersionUID = 1L;

            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                onlineResource.setModelObject("");
                onlineResource.clearInput();
                format.setModelObject("");
                format.clearInput();
                width.setModelObject(0);
                width.clearInput();
                height.setModelObject(0);
                height.clearInput();

                updateVisibility(false);
                target.add(ExternalGraphicPanel.this);
            }
        };
        container.add(hide);
        showhideForm.add(hide);

        LegendInfo legend = styleModel.getObject().getLegend();
        boolean visible = legend != null && legend.getOnlineResource() != null
                && !legend.getOnlineResource().isEmpty();
        updateVisibility(visible);

    }

    /**
     * Lookup base URL using provided form
     * @param form
     * @see ResponseUtils
     * @return baseUrl
     */
    protected String baseURL(Form<?> form) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) form.getRequest().getContainerRequest();
        String baseUrl = GeoServerExtensions.getProperty("PROXY_BASE_URL");
        if (StringUtils.isEmpty(baseUrl)) {
            GeoServer gs = GeoServerApplication.get().getGeoServer();
            baseUrl = gs.getGlobal().getSettings().getProxyBaseUrl();
            if (StringUtils.isEmpty(baseUrl)) {
                return ResponseUtils.baseURL(httpServletRequest);
            }
        }
        return baseUrl;
    }

    /**
     * Validates the external graphic and returns a connection to the graphic.
     * If validation fails, error messages will be added to the passed form
     * 
     * @param target
     * @param form
     * @return URLConnection to the External Graphic file
     */
    protected URLConnection getExternalGraphic(AjaxRequestTarget target, Form<?> form) {
        onlineResource.processInput();
        if (onlineResource.getModelObject() != null) {
            URL url = null;
            try {
                String baseUrl = baseURL(form);
                String external = onlineResource.getModelObject().toString();

                URI uri = new URI(external);
                if (uri.isAbsolute()) {
                    url = uri.toURL();
                    if (!external.startsWith(baseUrl)) {
                        form.warn("Recommend use of styles directory at " + baseUrl);
                    }
                } else {
                    WorkspaceInfo wsInfo = ((StyleInfo) getDefaultModelObject()).getWorkspace();
                    if (wsInfo != null) {
                        url = new URL(ResponseUtils.appendPath(baseUrl, "styles", wsInfo.getName(), external));
                    } else {
                        url = new URL(ResponseUtils.appendPath(baseUrl, "styles", external));
                    }
                }

                URLConnection conn = url.openConnection();
                if ("text/html".equals(conn.getContentType())) {
                    form.error("Unable to access url");
                    return null; // error message back!
                }
                return conn;

            } catch (FileNotFoundException notFound) {
                form.error("Unable to access " + url);
            } catch (Exception e) {
                e.printStackTrace();
                form.error("Recommend use of styles directory at " + e);
            }
        }
        return null;
    }

    /**
     * @return the value of the onlineResource field
     */
    protected String getOnlineResource() {
        return onlineResource.getInput();
    }

    private void updateVisibility(boolean b) {
        if (b) {
            showhideStyleModel.setObject("");
        } else {
            showhideStyleModel.setObject("display:none");
        }
        //table.setVisible(b); 
        autoFill.setVisible(b);
        hide.setVisible(b);
        show.setVisible(!b);
    }
}