📄 getmapresponse.java
字号:
/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.wms.responses;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geoserver.platform.GeoServerExtensions;
import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
import org.geotools.data.DefaultQuery;
import org.geotools.data.FeatureSource;
import org.geotools.data.Query;
import org.geotools.factory.FactoryConfigurationError;
import org.geotools.feature.IllegalAttributeException;
import org.geotools.feature.SchemaException;
import org.geotools.map.DefaultMapLayer;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.resources.coverage.FeatureUtilities;
import org.geotools.styling.Style;
import org.opengis.filter.Filter;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterNotFoundException;
import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;
import org.springframework.context.ApplicationContext;
import org.vfny.geoserver.Request;
import org.vfny.geoserver.Response;
import org.vfny.geoserver.ServiceException;
import org.vfny.geoserver.global.GeoServer;
import org.vfny.geoserver.global.MapLayerInfo;
import org.vfny.geoserver.global.Service;
import org.vfny.geoserver.global.WMS;
import org.vfny.geoserver.util.CoverageUtils;
import org.vfny.geoserver.wms.GetLegendGraphicProducerSpi;
import org.vfny.geoserver.wms.GetMapProducer;
import org.vfny.geoserver.wms.GetMapProducerFactorySpi;
import org.vfny.geoserver.wms.RasterMapProducer;
import org.vfny.geoserver.wms.WMSMapContext;
import org.vfny.geoserver.wms.WmsException;
import org.vfny.geoserver.wms.requests.GetMapRequest;
import org.vfny.geoserver.wms.responses.map.metatile.MetatileMapProducer;
import com.vividsolutions.jts.geom.Envelope;
/**
* A GetMapResponse object is responsible of generating a map based on a GetMap
* request. The way the map is generated is independent of this class, wich will
* use a delegate object based on the output format requested
*
* @author Gabriel Roldan, Axios Engineering
* @author Simone Giannecchini - GeoSolutions SAS
* @version $Id: GetMapResponse.java 7746 2007-11-13 15:38:35Z aaime $
*/
public class GetMapResponse implements Response {
/** DOCUMENT ME! */
private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(GetMapResponse.class
.getPackage().getName());
/**
* The map producer that will be used for the production of a map in the
* requested format.
*/
private GetMapProducer delegate;
/**
* The map context
*/
private WMSMapContext map;
/**
* WMS module
*/
private WMS wms;
/**
* custom response headers
*/
private HashMap responseHeaders;
String headerContentDisposition;
private ApplicationContext applicationContext;
/**
* Creates a new GetMapResponse object.
*
* @param applicationContext
*/
public GetMapResponse(WMS wms, ApplicationContext applicationContext) {
this.wms = wms;
this.applicationContext = applicationContext;
responseHeaders = new HashMap(10);
}
/**
* Returns any extra headers that this service might want to set in the HTTP
* response object.
*/
public HashMap getResponseHeaders() {
return responseHeaders;
}
/**
* DOCUMENT ME!
*
* @param req
* DOCUMENT ME!
*
* @throws ServiceException
* DOCUMENT ME!
* @throws WmsException
* DOCUMENT ME!
*/
public void execute(Request req) throws ServiceException {
GetMapRequest request = (GetMapRequest) req;
final String outputFormat = request.getFormat();
this.delegate = getDelegate(outputFormat, wms);
// JD:make instance variable in order to release resources later
// final WMSMapContext map = new WMSMapContext();
map = new WMSMapContext(request);
this.delegate.setMapContext(map);
// enable on the fly meta tiling if request looks like a tiled one
if (MetatileMapProducer.isRequestTiled(request, delegate)) {
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER
.finer("Tiled request detected, activating on the fly meta tiler");
}
this.delegate = new MetatileMapProducer(request,
(RasterMapProducer) delegate);
this.delegate.setMapContext(map);
}
final MapLayerInfo[] layers = request.getLayers();
final Style[] styles = (Style[]) request.getStyles().toArray(
new Style[] {});
final Filter[] filters = ((request.getFilter() != null) ? (Filter[]) request
.getFilter().toArray(new Filter[] {})
: null);
// DJB: the WMS spec says that the request must not be 0 area
// if it is, throw a service exception!
final Envelope env = request.getBbox();
if (env == null) {
throw new WmsException("GetMap requests must include a BBOX parameter.");
}
if (env.isNull() || (env.getWidth() <= 0) || (env.getHeight() <= 0)) {
throw new WmsException(new StringBuffer(
"The request bounding box has zero area: ").append(env)
.toString());
}
// DJB DONE: replace by setAreaOfInterest(Envelope,
// CoordinateReferenceSystem)
// with the user supplied SRS parameter
// if there's a crs in the request, use that. If not, assume its 4326
final CoordinateReferenceSystem mapcrs = request.getCrs();
// DJB: added this to be nicer about the "NONE" srs.
if (mapcrs != null) {
map.setAreaOfInterest(env, mapcrs);
} else {
map.setAreaOfInterest(env, DefaultGeographicCRS.WGS84);
}
map.setMapWidth(request.getWidth());
map.setMapHeight(request.getHeight());
map.setBgColor(request.getBgColor());
map.setTransparent(request.isTransparent());
map.setBuffer(request.getBuffer());
map.setPaletteInverter(request.getPalette());
// //
//
// Check to see if we really have something to display. Sometimes width
// or height or both are non positivie or the requested area is null.
//
// ///
if ((request.getWidth() <= 0) || (request.getHeight() <= 0)
|| (map.getAreaOfInterest().getLength(0) <= 0)
|| (map.getAreaOfInterest().getLength(1) <= 0)) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER
.fine("We are not going to render anything because either the are is null ar the dimensions are not positive.");
}
return;
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("setting up map");
}
try { // mapcontext can leak memory -- we make sure we done (see
// finally block)
// track the external caching strategy for any map layers
boolean cachingPossible = request.getHttpServletRequest()
.getMethod().equals("GET");
String featureVersion = request.getFeatureVersion();
int maxAge = Integer.MAX_VALUE;
final int length = layers.length;
for (int i = 0; i < length; i++) {
final Style style = styles[i];
Filter optionalFilter;
try {
optionalFilter = filters[i];
} catch (Exception e) {
optionalFilter = null;
}
final DefaultMapLayer layer;
if(layers[i].getType() == MapLayerInfo.TYPE_REMOTE_VECTOR) {
cachingPossible = false;
final FeatureSource source = layers[i].getRemoteFeatureSource();
layer = new DefaultMapLayer(source, style);
layer.setTitle(layers[i].getName());
final DefaultQuery definitionQuery;
if (optionalFilter != null) {
definitionQuery = new DefaultQuery(source.getSchema()
.getTypeName(), optionalFilter);
definitionQuery.setVersion(featureVersion);
layer.setQuery(definitionQuery);
} else if (featureVersion != null) {
definitionQuery = new DefaultQuery(source.getSchema()
.getTypeName());
definitionQuery.setVersion(featureVersion);
layer.setQuery(definitionQuery);
}
map.addLayer(layer);
} else if (layers[i].getType() == MapLayerInfo.TYPE_VECTOR) {
if (cachingPossible) {
if (layers[i].getFeature().isCachingEnabled()) {
int nma = Integer.parseInt(layers[i].getFeature()
.getCacheMaxAge());
// suppose the map contains multiple cachable
// layers...we can only cache the combined map for
// the
// time specified by the shortest-cached layer.
if (nma < maxAge) {
maxAge = nma;
}
} else {
// if one layer isn't cachable, then we can't cache
// any of them. Disable caching.
cachingPossible = false;
}
}
final FeatureSource source;
// /////////////////////////////////////////////////////////
//
// Adding a feature layer
//
// /////////////////////////////////////////////////////////
try {
source = layers[i].getFeature().getFeatureSource(true);
// NOTE for the feature. Here there was some code that
// sounded like:
// * get the bounding box from feature source
// * eventually reproject it to the actual CRS used for
// map
// * if no intersection, don't bother adding the feature
// source to the map
// This is not an optimization, on the contrary,
// computing the bbox may be
// very expensive depending on the data size. Using
// sigma.openplans.org data
// and a tiled client like OpenLayers, it dragged the
// server to his knees
// and the client simply timed out
} catch (IOException exp) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.log(Level.SEVERE, new StringBuffer(
"Getting feature source: ").append(
exp.getMessage()).toString(), exp);
}
throw new WmsException(null, new StringBuffer(
"Internal error : ").append(exp.getMessage())
.toString());
}
layer = new DefaultMapLayer(source, style);
layer.setTitle(layers[i].getName());
final Filter definitionFilter = layers[i].getFeature()
.getDefinitionQuery();
final DefaultQuery definitionQuery;
if (definitionFilter != null) {
definitionQuery = new DefaultQuery(source.getSchema()
.getTypeName(), definitionFilter);
definitionQuery.setVersion(featureVersion);
layer.setQuery(definitionQuery);
} else if (optionalFilter != null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -