org.mapfish.print.map.image.wms.WmsLayer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of print-lib Show documentation
Show all versions of print-lib Show documentation
Library for generating PDFs and images from online webmapping services
package org.mapfish.print.map.image.wms;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.google.common.io.Closer;
import com.vividsolutions.jts.util.Assert;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.mapfish.print.attribute.map.MapfishMapContext;
import org.mapfish.print.config.Configuration;
import org.mapfish.print.http.HttpRequestCache;
import org.mapfish.print.http.MfClientHttpRequestFactory;
import org.mapfish.print.map.geotools.StyleSupplier;
import org.mapfish.print.map.image.AbstractSingleImageLayer;
import org.mapfish.print.map.style.json.ColorParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.net.URI;
import java.util.List;
import java.util.concurrent.ExecutorService;
import javax.annotation.Nonnull;
import javax.imageio.ImageIO;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
/**
* Wms layer.
*/
public final class WmsLayer extends AbstractSingleImageLayer {
private static final Logger LOGGER = LoggerFactory.getLogger(WmsLayer.class);
private final WmsLayerParam params;
private final MetricRegistry registry;
private final Configuration configuration;
private ClientHttpRequest imageRequest;
/**
* Constructor.
*
* @param executorService the thread pool for doing the rendering.
* @param styleSupplier the style to use when drawing the constructed grid coverage on the map.
* @param params the params from the request data.
* @param registry the metrics registry.
* @param configuration the configuration.
*/
protected WmsLayer(
@Nonnull final ExecutorService executorService,
@Nonnull final StyleSupplier styleSupplier,
@Nonnull final WmsLayerParam params,
@Nonnull final MetricRegistry registry,
@Nonnull final Configuration configuration) {
super(executorService, styleSupplier, params);
this.params = params;
this.registry = registry;
this.configuration = configuration;
}
@Override
protected BufferedImage loadImage(
@Nonnull final MfClientHttpRequestFactory requestFactory,
@Nonnull final MapfishMapContext transformer) throws Throwable {
final String baseMetricName = WmsLayer.class.getName() + ".read." +
this.imageRequest.getURI().getHost();
try (Closer closer = Closer.create()) {
final Timer.Context timerDownload = this.registry.timer(baseMetricName).time();
LOGGER.info("Query the WMS image {}.", this.imageRequest.getURI());
final ClientHttpResponse response = closer.register(this.imageRequest.execute());
Assert.isTrue(response != null, "No response, see error above");
Assert.equals(HttpStatus.OK, response.getStatusCode(), String.format("Http status code for %s " +
"was not OK. It " +
"was: %s. The " +
"response message " +
"was: '%s'",
this.imageRequest.getURI(),
response.getStatusCode(),
response.getStatusText()));
final List contentType = response.getHeaders().get("Content-Type");
if (contentType == null || contentType.size() != 1) {
LOGGER.debug("The WMS image {} don't return a valid content type header.",
this.imageRequest.getURI());
} else if (!contentType.get(0).startsWith("image/")) {
byte[] data = new byte[response.getBody().available()];
response.getBody().read(data);
LOGGER.debug("We get a wrong WMS image for {}, content type: {}\nresult:\n{}",
this.imageRequest.getURI(), contentType.get(0), new String(data, "UTF-8"));
this.registry.counter(baseMetricName + ".error").inc();
return createErrorImage(transformer.getPaintArea());
}
final BufferedImage image = ImageIO.read(response.getBody());
if (image == null) {
LOGGER.warn("The WMS image {} is an image format that can be decoded",
this.imageRequest.getURI());
this.registry.counter(baseMetricName + ".error").inc();
return createErrorImage(transformer.getPaintArea());
} else {
timerDownload.stop();
}
return image;
} catch (Throwable e) {
this.registry.counter(baseMetricName + ".error").inc();
throw e;
}
}
private BufferedImage createErrorImage(final Rectangle area) {
final BufferedImage bufferedImage = new BufferedImage(area.width, area.height, TYPE_INT_ARGB_PRE);
final Graphics2D graphics = bufferedImage.createGraphics();
try {
graphics.setBackground(ColorParser.toColor(this.configuration.getTransparentTileErrorColor()));
graphics.clearRect(0, 0, area.width, area.height);
return bufferedImage;
} finally {
graphics.dispose();
}
}
/**
* Get the HTTP params.
*
* @return the HTTP params
*/
public WmsLayerParam getParams() {
return this.params;
}
/**
* If supported by the WMS server, a parameter "angle" can be set on "customParams" or "mergeableParams".
* In this case the rotation will be done natively by the WMS.
*/
@Override
public boolean supportsNativeRotation() {
return this.params.useNativeAngle &&
(this.params.serverType == WmsLayerParam.ServerType.MAPSERVER ||
this.params.serverType == WmsLayerParam.ServerType.GEOSERVER);
}
@Override
public RenderType getRenderType() {
return RenderType.fromMimeType(this.params.imageFormat);
}
@Override
public void cacheResources(
@Nonnull final HttpRequestCache httpRequestCache,
@Nonnull final MfClientHttpRequestFactory requestFactory,
@Nonnull final MapfishMapContext transformer, @Nonnull final String jobId) {
try {
final MapfishMapContext layerTransformer = getLayerTransformer(transformer);
final WmsLayerParam wmsLayerParam = this.params;
final URI commonUri = new URI(wmsLayerParam.getBaseUrl());
final Rectangle paintArea = layerTransformer.getPaintArea();
final ReferencedEnvelope envelope = layerTransformer.getBounds().toReferencedEnvelope(paintArea);
URI uri = WmsUtilities.makeWmsGetLayerRequest(wmsLayerParam, commonUri, paintArea.getSize(),
layerTransformer.getDPI(),
layerTransformer.getRotation(), envelope);
this.imageRequest = WmsUtilities.createWmsRequest(requestFactory, uri, this.params.method);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy