001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.vfny.geoserver.wms.responses.map.openlayers;
006:
007: import java.io.IOException;
008: import java.io.OutputStream;
009: import java.io.OutputStreamWriter;
010: import java.nio.charset.Charset;
011: import java.util.ArrayList;
012: import java.util.Enumeration;
013: import java.util.HashMap;
014: import java.util.HashSet;
015: import java.util.List;
016: import java.util.Map;
017: import java.util.Set;
018: import java.util.logging.Level;
019: import java.util.logging.Logger;
020:
021: import javax.servlet.http.HttpServletRequest;
022:
023: import org.geoserver.ows.util.RequestUtils;
024: import org.geotools.geometry.jts.ReferencedEnvelope;
025: import org.opengis.referencing.crs.CoordinateReferenceSystem;
026: import org.opengis.referencing.crs.ProjectedCRS;
027: import org.vfny.geoserver.ServiceException;
028: import org.vfny.geoserver.global.WMS;
029: import org.vfny.geoserver.wms.GetMapProducer;
030: import org.vfny.geoserver.wms.WmsException;
031: import org.vfny.geoserver.wms.requests.GetMapRequest;
032: import org.vfny.geoserver.wms.responses.AbstractGetMapProducer;
033:
034: import freemarker.ext.beans.BeansWrapper;
035: import freemarker.template.Configuration;
036: import freemarker.template.Template;
037: import freemarker.template.TemplateException;
038:
039: public class OpenLayersMapProducer extends AbstractGetMapProducer
040: implements GetMapProducer {
041: /** A logger for this class. */
042: private static final Logger LOGGER = org.geotools.util.logging.Logging
043: .getLogger("org.vfny.geoserver.responses.wms.map.openlayers");
044:
045: /**
046: * Set of parameters that we can ignore, since they are not part of the
047: * OpenLayers WMS request
048: */
049: private static final Set ignoredParameters;
050:
051: static {
052: ignoredParameters = new HashSet();
053: ignoredParameters.add("REQUEST");
054: ignoredParameters.add("TILED");
055: ignoredParameters.add("BBOX");
056: ignoredParameters.add("SERVICE");
057: ignoredParameters.add("VERSION");
058: ignoredParameters.add("FORMAT");
059: }
060:
061: /**
062: * static freemaker configuration
063: */
064: static Configuration cfg;
065:
066: static {
067: cfg = new Configuration();
068: cfg.setClassForTemplateLoading(OpenLayersMapProducer.class, "");
069: BeansWrapper bw = new BeansWrapper();
070: bw.setExposureLevel(BeansWrapper.EXPOSE_PROPERTIES_ONLY);
071: cfg.setObjectWrapper(bw);
072: }
073:
074: /**
075: * wms configuration
076: */
077: WMS wms;
078:
079: /**
080: * The current template
081: */
082: Template template;
083:
084: public OpenLayersMapProducer(WMS wms) {
085: this .wms = wms;
086: mime = "text/html";
087: }
088:
089: public void writeTo(OutputStream out) throws ServiceException,
090: IOException {
091: try {
092: // create the template
093: Template template = cfg
094: .getTemplate("OpenLayersMapTemplate.ftl");
095: HashMap map = new HashMap();
096: map.put("context", mapContext);
097: map.put("request", mapContext.getRequest());
098: map.put("maxResolution", new Double(
099: getMaxResolution(mapContext.getAreaOfInterest())));
100: String proxifiedBaseUrl = RequestUtils.proxifiedBaseURL(
101: mapContext.getRequest().getBaseUrl(), mapContext
102: .getRequest().getServiceRef()
103: .getGeoServer().getProxyBaseUrl());
104: map.put("baseUrl", canonicUrl(proxifiedBaseUrl));
105: map.put("parameters", getLayerParameter(mapContext
106: .getRequest().getHttpServletRequest()));
107: map.put("units", getOLUnits(mapContext.getRequest()));
108:
109: if (mapContext.getLayerCount() == 1) {
110: map.put("layerName", mapContext.getLayer(0).getTitle());
111: } else {
112: map.put("layerName", "Geoserver layers");
113: }
114:
115: template.setOutputEncoding("UTF-8");
116: template.process(map, new OutputStreamWriter(out, Charset
117: .forName("UTF-8")));
118: } catch (TemplateException e) {
119: throw new WmsException(e);
120: }
121:
122: mapContext = null;
123: template = null;
124: }
125:
126: /**
127: * OL does support only a limited number of unit types, we have to try and
128: * return one of those, otherwise the scale won't be shown. From the OL
129: * guide: possible values are ‘degrees’ (or ‘dd’), ‘m’, ‘ft’, ‘km’, ‘mi’,
130: * ‘inches’.
131: *
132: * @param request
133: * @return
134: */
135: private String getOLUnits(GetMapRequest request) {
136: CoordinateReferenceSystem crs = request.getCrs();
137: // first rough approximation, meters for projected CRS, degrees for the
138: // others
139: String result = crs instanceof ProjectedCRS ? "m" : "degrees";
140: try {
141: String unit = crs.getCoordinateSystem().getAxis(0)
142: .getUnit().toString();
143: if ("°".equals(unit) || "degrees".equals(unit)
144: || "dd".equals(unit))
145: result = "degrees";
146: else if ("m".equals(unit) || "meters".equals(unit))
147: result = "m";
148: else if ("km".equals(unit) || "kilometers".equals(unit))
149: result = "mi";
150: else if ("in".equals(unit) || "inches".equals(unit))
151: result = "inches";
152: else if ("ft".equals(unit) || "feets".equals(unit))
153: result = "ft";
154: else if ("mi".equals(unit) || "miles".equals(unit))
155: result = "mi";
156: } catch (Exception e) {
157: LOGGER.log(Level.WARNING,
158: "Error trying to determine unit of measure", e);
159: }
160: return result;
161: }
162:
163: /**
164: * Returns a list of maps with the name and value of each parameter that we
165: * have to forward to OpenLayers. Forwarded parameters are all the provided
166: * ones, besides a short set contained in {@link #ignoredParameters}.
167: *
168: *
169: *
170: * @param request
171: * @return
172: */
173: private List getLayerParameter(HttpServletRequest request) {
174: List result = new ArrayList();
175: Enumeration en = request.getParameterNames();
176:
177: while (en.hasMoreElements()) {
178: String paramName = (String) en.nextElement();
179:
180: if (ignoredParameters.contains(paramName.toUpperCase())) {
181: continue;
182: }
183:
184: // this won't work for multi-valued parameters, but we have none so
185: // far (they
186: // are common just in HTML forms...)
187: Map map = new HashMap();
188: map.put("name", paramName);
189: map.put("value", request.getParameter(paramName));
190: result.add(map);
191: }
192:
193: return result;
194: }
195:
196: /**
197: * Makes sure the url does not end with "/", otherwise we would have URL lik
198: * "http://localhost:8080/geoserver//wms?LAYERS=..." and Jetty 6.1 won't
199: * digest them...
200: *
201: * @param baseUrl
202: * @return
203: */
204: private String canonicUrl(String baseUrl) {
205: if (baseUrl.endsWith("/")) {
206: return baseUrl.substring(0, baseUrl.length() - 1);
207: } else {
208: return baseUrl;
209: }
210: }
211:
212: private double getMaxResolution(ReferencedEnvelope areaOfInterest) {
213: double w = areaOfInterest.getWidth();
214: double h = areaOfInterest.getHeight();
215:
216: return ((w > h) ? w : h) / 256;
217: }
218:
219: public void produceMap() throws WmsException {
220: }
221:
222: }
|