/* (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.CssUrlReferenceHeaderItem;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptUrlReferenceHeaderItem;
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(new CssUrlReferenceHeaderItem(ResponseUtils.buildURL(base, "/openlayers3/ol.css", null, URLType.RESOURCE), null, null));
header.render(new JavaScriptUrlReferenceHeaderItem(ResponseUtils.buildURL(base, "/openlayers3/ol.js", null, URLType.RESOURCE), null, false, "UTF-8", null));
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();
}
}