package org.geoserver.wcs;
import static org.geoserver.data.test.MockData.TASMANIA_BM;
import static org.geoserver.data.test.MockData.WORLD;
import static org.vfny.geoserver.wcs.WcsException.WcsExceptionCode.InvalidParameterValue;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.mail.BodyPart;
import javax.mail.Multipart;
import javax.servlet.ServletResponse;
import javax.xml.namespace.QName;
import junit.framework.Test;
import org.apache.commons.io.IOUtils;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.data.test.MockData;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geometry.Envelope2D;
import org.geotools.referencing.CRS;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridEnvelope;
import org.vfny.geoserver.wcs.WcsException;
import org.w3c.dom.Document;
import com.mockrunner.mock.web.MockHttpServletResponse;
public class GetCoverageTest extends AbstractGetCoverageTest {
private static final QName MOSAIC = new QName(MockData.SF_URI, "rasterFilter", MockData.SF_PREFIX);
/**
* This is a READ ONLY TEST so we can use one time setup
*/
public static Test suite() {
return new OneTimeTestSetup(new GetCoverageTest());
}
@Override
protected String getLogConfiguration() {
return "/DEFAULT_LOGGING.properties";
}
@Override
protected void populateDataDirectory(MockData dataDirectory) throws Exception {
super.populateDataDirectory(dataDirectory);
// this also adds the raster style
dataDirectory.addCoverage(MOSAIC,
MockData.class.getResource("raster-filter-test.zip"), null, "raster");
}
// public void testNullGridOrigin() throws Exception {
// String request = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + //
// "<wcs:GetCoverage service=\"WCS\" " + //
// "xmlns:ows=\"http://www.opengis.net/ows/1.1\"\r\n" + //
// " xmlns:wcs=\"http://www.opengis.net/wcs/1.1.1\"\r\n" + //
// " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \r\n" + //
// " xsi:schemaLocation=\"http://www.opengis.net/wcs/1.1.1 " + //
// "schemas/wcs/1.1.1/wcsAll.xsd\"\r\n" + //
// " version=\"1.1.1\" >\r\n" + //
// " <ows:Identifier>wcs:BlueMarble</ows:Identifier>\r\n" + //
// " <wcs:DomainSubset>\r\n" + //
// " <ows:BoundingBox crs=\"urn:ogc:def:crs:EPSG:6.6:4326\">\r\n" + //
// " <ows:LowerCorner>-90 -180</ows:LowerCorner>\r\n" + //
// " <ows:UpperCorner>90 180</ows:UpperCorner>\r\n" + //
// " </ows:BoundingBox>\r\n" + //
// " </wcs:DomainSubset>\r\n" + //
// " <wcs:Output format=\"image/tiff\">\r\n" + //
// " <wcs:GridCRS>\r\n" + //
// " <wcs:GridBaseCRS>urn:ogc:def:crs:EPSG:6.6:4326</wcs:GridBaseCRS>\r\n" + //
// " <wcs:GridType>urn:ogc:def:method:WCS:1.1:2dSimpleGrid</wcs:GridType>\r\n" + //
// " <wcs:GridOffsets>-1 2</wcs:GridOffsets>\r\n" + //
// " </wcs:GridCRS>\r\n" + //
// " </wcs:Output>\r\n" + //
// "</wcs:GetCoverage>";
//
// executeGetCoverageXml(request);
// }
public void testKvpBasic() throws Exception {
Map<String, Object> raw = baseMap();
final String getLayerId = getLayerId(TASMANIA_BM);
raw.put("identifier", getLayerId);
raw.put("format", "image/tiff");
raw.put("BoundingBox", "-90,-180,90,180,urn:ogc:def:crs:EPSG:6.6:4326");
raw.put("store", "false");
raw.put("GridBaseCRS", "urn:ogc:def:crs:EPSG:6.6:4326");
GridCoverage[] coverages = executeGetCoverageKvp(raw);
assertEquals(1, coverages.length);
GridCoverage2D coverage = (GridCoverage2D) coverages[0];
assertEquals(CRS.decode("urn:ogc:def:crs:EPSG:6.6:4326"), coverage.getEnvelope()
.getCoordinateReferenceSystem());
}
public void testAntimeridianWorld() throws Exception {
// for the moment, just make sure we don't die and return something, see
Map<String, Object> raw = baseMap();
final String getLayerId = getLayerId(WORLD);
raw.put("identifier", getLayerId);
raw.put("format", "image/geotiff");
raw.put("BoundingBox", "175,10,-175,20,urn:ogc:def:crs:OGC:1.3:CRS84");
raw.put("store", "false");
// raw.put("GridBaseCRS", "urn:ogc:def:crs:EPSG:6.6:4326");
GridCoverage[] coverages = executeGetCoverageKvp(raw);
assertEquals(1, coverages.length);
GridCoverage2D coverage = (GridCoverage2D) coverages[0];
assertEquals(CRS.decode("urn:ogc:def:crs:EPSG:6.6:4326"), coverage.getEnvelope()
.getCoordinateReferenceSystem());
}
public void testAntimeridianTaz() throws Exception {
// for the moment, just make sure we don't die and return something, see
Map<String, Object> raw = baseMap();
final String getLayerId = getLayerId(TASMANIA_BM);
raw.put("identifier", getLayerId);
raw.put("format", "image/geotiff");
raw.put("store", "false");
// complete coverage from left side of request bbox
raw.put("BoundingBox", "145,-80,-175,0,urn:ogc:def:crs:OGC:1.3:CRS84");
executeGetCoverageKvp(raw);
// partial coverage from left side of request bbox
raw.put("BoundingBox", "147,-80,-175,0,urn:ogc:def:crs:OGC:1.3:CRS84");
executeGetCoverageKvp(raw);
// partial coverage from both left and right side
raw.put("BoundingBox", "147.2,-80,147,0,urn:ogc:def:crs:OGC:1.3:CRS84");
executeGetCoverageKvp(raw);
// partial coverage from right side
raw.put("BoundingBox", "175,-80,147,0,urn:ogc:def:crs:OGC:1.3:CRS84");
executeGetCoverageKvp(raw);
// full coverage from right side
raw.put("BoundingBox", "175,-80,150,0,urn:ogc:def:crs:OGC:1.3:CRS84");
executeGetCoverageKvp(raw);
}
public void testWrongFormatParams() throws Exception {
Map<String, Object> raw = baseMap();
final String getLayerId = getLayerId(TASMANIA_BM);
raw.put("identifier", getLayerId);
raw.put("format", "SuperCoolFormat");
raw.put("BoundingBox", "-45,146,-42,147,urn:ogc:def:crs:EPSG:6.6:4326");
try {
executeGetCoverageKvp(raw);
fail("When did we learn to encode SuperCoolFormat?");
} catch (WcsException e) {
assertEquals(InvalidParameterValue.toString(), e.getCode());
assertEquals("format", e.getLocator());
}
}
// public void testDefaultGridOrigin() throws Exception {
// Map<String, Object> raw = new HashMap<String, Object>();
// final String getLayerId = getLayerId(TASMANIA_BM);
// raw.put("identifier", getLayerId);
// raw.put("format", "image/geotiff");
// raw.put("BoundingBox", "-45,146,-42,147,urn:ogc:def:crs:EPSG:6.6:4326");
//
// GridCoverage[] coverages = executeGetCoverageKvp(raw);
// AffineTransform2D tx = (AffineTransform2D) coverages[0].getGridGeometry().getGridToCRS();
// assertEquals(0.0, tx.getTranslateX());
// assertEquals(0.0, tx.getTranslateY());
// }
public void testWrongGridOrigin() throws Exception {
Map<String, Object> raw = baseMap();
final String getLayerId = getLayerId(TASMANIA_BM);
raw.put("identifier", getLayerId);
raw.put("format", "image/geotiff");
raw.put("BoundingBox", "-45,146,-42,147,urn:ogc:def:crs:EPSG:6.6:4326");
raw.put("GridOrigin", "12,13,14");
try {
executeGetCoverageKvp(raw);
fail("We should have had a WcsException here?");
} catch (WcsException e) {
assertEquals(InvalidParameterValue.name(), e.getCode());
assertEquals("GridOrigin", e.getLocator());
}
}
public void testWorkspaceQualified() throws Exception {
String queryString = "&request=getcoverage&service=wcs&version=1.1.1&&format=image/geotiff"
+ "&BoundingBox=-45,146,-42,147,urn:ogc:def:crs:EPSG:6.6:4326";
ServletResponse r = getAsServletResponse("wcs?identifier=" + TASMANIA_BM.getLocalPart()
+ queryString);
assertTrue(r.getContentType().startsWith("multipart/related"));
Document dom = getAsDOM("cdf/wcs?identifier=" + TASMANIA_BM.getLocalPart() + queryString);
assertEquals("ows:ExceptionReport", dom.getDocumentElement().getNodeName());
}
public void testLayerQualified() throws Exception {
String queryString = "&request=getcoverage&service=wcs&version=1.1.1&&format=image/geotiff"
+ "&BoundingBox=-45,146,-42,147,urn:ogc:def:crs:EPSG:6.6:4326";
ServletResponse r = getAsServletResponse("wcs/BlueMarble/wcs?identifier=BlueMarble"
+ queryString);
assertTrue(r.getContentType().startsWith("multipart/related"));
Document dom = getAsDOM("wcs/DEM/wcs?identifier=BlueMarble" + queryString);
assertEquals("ows:ExceptionReport", dom.getDocumentElement().getNodeName());
}
public void testLargerThanData() throws Exception {
MockHttpServletResponse response = getAsServletResponse(
"wcs/BlueMarble/wcs?identifier=" + getLayerId(TASMANIA_BM)
+ "&request=getcoverage&service=wcs&version=1.1.1&&format=image/geotiff"
+ "&BoundingBox=-90,-180,90,180,urn:ogc:def:crs:EPSG:6.6:4326&GridBaseCRS=EPSG:4326");
// parse the multipart, check there are two parts
Multipart multipart = getMultipart(response);
assertEquals(2, multipart.getCount());
BodyPart coveragePart = multipart.getBodyPart(1);
assertEquals("image/tiff;subtype=\"geotiff\"", coveragePart.getContentType());
assertEquals("<theCoverage>", coveragePart.getHeader("Content-ID")[0]);
// save
File tiffFile = File.createTempFile("wcs", "", new File("target"));
IOUtils.copy(coveragePart.getInputStream(), new FileOutputStream(tiffFile));
// make sure we can read the coverage back
GeoTiffReader reader = new GeoTiffReader(tiffFile);
GridCoverage2D result = reader.read(null);
// see that we got the entire coverage, but nothing more
CoverageInfo ci = getCatalog().getCoverageByName(TASMANIA_BM.getLocalPart());
GridCoverage2D original = (GridCoverage2D) ci.getGridCoverage(null, null);
// the grid should be swapped, axis flipping...
GridEnvelope originalRange = original.getGridGeometry().getGridRange();
GridEnvelope actualRange = result.getGridGeometry().getGridRange();
assertEquals(originalRange.getSpan(0), actualRange.getSpan(1));
assertEquals(originalRange.getSpan(1), actualRange.getSpan(0));
// check also the geographic bounds
Envelope2D originalEnv = original.getEnvelope2D();
Envelope2D actualEnv = result.getEnvelope2D();
assertEquals(originalEnv.getMinX(), actualEnv.getMinY(), 1e-6);
assertEquals(originalEnv.getMinY(), actualEnv.getMinX(), 1e-6);
assertEquals(originalEnv.getMaxX(), actualEnv.getMaxY(), 1e-6);
assertEquals(originalEnv.getMaxY(), actualEnv.getMaxX(), 1e-6);
// cleanup
tiffFile.delete();
}
public void testInputLimits() throws Exception {
try {
// ridicolous limit, just one byte
setInputLimit(1);
String queryString = "&request=getcoverage&service=wcs&version=1.1.1&&format=image/geotiff"
+ "&BoundingBox=-45,146,-42,147,urn:ogc:def:crs:EPSG:6.6:4326";
Document dom = getAsDOM("wcs/BlueMarble/wcs?identifier=" + getLayerId(TASMANIA_BM)
+ queryString);
//print(dom);
// check it's an error, check we're getting it because of the input limits
assertEquals("ows:ExceptionReport", dom.getDocumentElement().getNodeName());
String error = xpath.evaluate("/ows:ExceptionReport/ows:Exception/ows:ExceptionText/text()", dom);
assertTrue(error.matches(".*read too much data.*"));
} finally {
setInputLimit(0);
}
}
public void testOutputLimits() throws Exception {
try {
// ridicolous limit, just one byte
setOutputLimit(1);
String queryString = "&request=getcoverage&service=wcs&version=1.1.1&&format=image/geotiff"
+ "&BoundingBox=-45,146,-42,147,urn:ogc:def:crs:EPSG:6.6:4326";
Document dom = getAsDOM("wcs/wcs?identifier=" + getLayerId(TASMANIA_BM)
+ queryString);
//print(dom);
// check it's an error, check we're getting it because of the output limits
assertEquals("ows:ExceptionReport", dom.getDocumentElement().getNodeName());
String error = xpath.evaluate("/ows:ExceptionReport/ows:Exception/ows:ExceptionText/text()", dom);
assertTrue(error.matches(".*generate too much data.*"));
} finally {
setOutputLimit(0);
}
}
public void testRasterFilterGreen() throws Exception {
String queryString = "wcs?identifier=" + getLayerId(MOSAIC) + "&request=getcoverage" +
"&service=wcs&version=1.1.1&&format=image/tiff" +
"&BoundingBox=0,0,1,1,urn:ogc:def:crs:EPSG:6.6:4326" +
"&CQL_FILTER=location like 'green%25'";
MockHttpServletResponse response = getAsServletResponse(queryString);
// parse the multipart, check there are two parts
Multipart multipart = getMultipart(response);
assertEquals(2, multipart.getCount());
BodyPart coveragePart = multipart.getBodyPart(1);
assertEquals("image/tiff", coveragePart.getContentType());
assertEquals("<theCoverage>", coveragePart.getHeader("Content-ID")[0]);
// make sure we can read the coverage back
ImageReader reader = ImageIO.getImageReadersByFormatName("tiff").next();
reader.setInput(ImageIO.createImageInputStream(coveragePart.getInputStream()));
RenderedImage image = reader.read(0);
// check the pixel
int[] pixel = new int[3];
image.getData().getPixel(0, 0, pixel);
assertEquals(0, pixel[0]);
assertEquals(255, pixel[1]);
assertEquals(0, pixel[2]);
}
public void testRasterFilterRed() throws Exception {
String queryString = "wcs?identifier=" + getLayerId(MOSAIC) + "&request=getcoverage" +
"&service=wcs&version=1.1.1&&format=image/tiff" +
"&BoundingBox=0,0,1,1,urn:ogc:def:crs:EPSG:6.6:4326" +
"&CQL_FILTER=location like 'red%25'";
MockHttpServletResponse response = getAsServletResponse(queryString);
// parse the multipart, check there are two parts
Multipart multipart = getMultipart(response);
assertEquals(2, multipart.getCount());
BodyPart coveragePart = multipart.getBodyPart(1);
assertEquals("image/tiff", coveragePart.getContentType());
assertEquals("<theCoverage>", coveragePart.getHeader("Content-ID")[0]);
// make sure we can read the coverage back
ImageReader reader = ImageIO.getImageReadersByFormatName("tiff").next();
reader.setInput(ImageIO.createImageInputStream(coveragePart.getInputStream()));
RenderedImage image = reader.read(0);
// check the pixel
int[] pixel = new int[3];
image.getData().getPixel(0, 0, pixel);
assertEquals(255, pixel[0]);
assertEquals(0, pixel[1]);
assertEquals(0, pixel[2]);
}
}