/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2008-2012, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.data.wms.test;
import junit.framework.TestCase;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.StringBuilderWriter;
import org.geotools.data.ResourceInfo;
import org.geotools.data.ServiceInfo;
import org.geotools.data.ows.CRSEnvelope;
import org.geotools.data.ows.Layer;
import org.geotools.data.ows.MultithreadedHttpClient;
import org.geotools.data.ows.OperationType;
import org.geotools.data.ows.Specification;
import org.geotools.data.ows.WMSCapabilities;
import org.geotools.data.wms.WMS1_1_1;
import org.geotools.data.wms.WebMapServer;
import org.geotools.data.wms.request.GetFeatureInfoRequest;
import org.geotools.data.wms.request.GetMapRequest;
import org.geotools.data.wms.request.GetStylesRequest;
import org.geotools.data.wms.response.GetFeatureInfoResponse;
import org.geotools.data.wms.response.GetMapResponse;
import org.geotools.data.wms.response.GetStylesResponse;
import org.geotools.factory.GeoTools;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.CRS.AxisOrder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.styling.NamedLayer;
import org.geotools.styling.SLDParser;
import org.geotools.styling.SLDTransformer;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.StyleFactoryImpl;
import org.geotools.styling.StyledLayerDescriptor;
import org.geotools.styling.builder.NamedLayerBuilder;
import org.geotools.styling.builder.StyledLayerDescriptorBuilder;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import javax.imageio.ImageIO;
import javax.mail.internet.ContentType;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* This test case assume you have a default GeoServer 2.2 installed on 127.0.0.1 (ie localhost).
* <p>
* This is being used to look at WMS 1.1.1 vs WMS 1.3.0 compatibility issues for uDig.
* <p>
*
* <pre>
* <code>
* <Layer queryable="1">
* <Name>nurc:Img_Sample</Name>
* <Title>North America sample imagery</Title>
* <Abstract/>
* <KeywordList>
* <Keyword>WCS</Keyword>
* <Keyword>worldImageSample</Keyword>
* <Keyword>worldImageSample_Coverage</Keyword>
* </KeywordList>
* <CRS>EPSG:4326</CRS>
* <CRS>CRS:84</CRS>
* <EX_GeographicBoundingBox>
* <westBoundLongitude>-130.85168</westBoundLongitude>
* <eastBoundLongitude>-62.0054</eastBoundLongitude>
* <southBoundLatitude>20.7052</southBoundLatitude>
* <northBoundLatitude>54.1141</northBoundLatitude>
* </EX_GeographicBoundingBox>
* <BoundingBox CRS="CRS:84" minx="-130.85168" miny="20.7052" maxx="-62.0054" maxy="54.1141"/>
* <BoundingBox CRS="EPSG:4326" minx="20.7052" miny="-130.85168" maxx="54.1141" maxy="-62.0054"/>
* <Style>
* <Name>raster</Name>
* <Title>Default Raster</Title>
* <Abstract>
* A sample style that draws a raster, good for displaying imagery
* </Abstract>
* <LegendURL width="20" height="20">
* <Format>image/png</Format>
* <OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="http://localhost:8080/geoserver/ows?service=WMS&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=Img_Sample"/>
* </LegendURL>
* </Style>
* </Layer>
* </code>
* </pre>
*
* </p>
*
* @author Jody Garnett
* @source $URL$
*/
public class LocalGeoServerOnlineTest extends TestCase {
static private String LOCAL_GEOSERVER = "http://127.0.0.1:8080/geoserver/ows?SERVICE=WMS&";
static private String LOCAL_LAYERS = "test_shp:TRONCON_ROUTE";
static private WebMapServer wms;
static private WMSCapabilities capabilities;
static private URL serverURL;
static {
try {
serverURL = new URL(LOCAL_GEOSERVER);
} catch (MalformedURLException e) {
serverURL = null;
}
;
}
@Override
protected void setUp() throws Exception {
//System.out.println("CRS configured to forceXY"+System.getProperty("org.geotools.referencing.forceXY"));
//Hints.putSystemDefault(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);
if (wms == null) {
// do setup once!
if (serverURL != null) {
try {
wms = new WebMapServer(serverURL, new MultithreadedHttpClient());
capabilities = wms.getCapabilities();
} catch (Exception eek) {
serverURL = null;
throw eek;
}
}
}
}
public void testCRSEnvelope(){
CRSEnvelope test = new CRSEnvelope( null, -20, -100, 20, 100 );
test.setSRSName("EPSG:4326", false );
CoordinateReferenceSystem crs = test.getCoordinateReferenceSystem();
assertEquals( AxisOrder.NORTH_EAST, CRS.getAxisOrder( crs ) );
test = new CRSEnvelope( null, 100, -20, 100, 20 );
test.setSRSName("EPSG:4326", true );
crs = test.getCoordinateReferenceSystem();
assertEquals( AxisOrder.EAST_NORTH, CRS.getAxisOrder( crs ) );
}
public void testLocalGeoServer() {
assertNotNull(wms);
assertNotNull(capabilities);
assertEquals("Version Negotiation", "1.3.0", capabilities.getVersion());
Layer root = capabilities.getLayer();
assertNotNull(root);
assertNull("root layer does not have a name", root.getName());
assertNotNull("title", root.getTitle());
}
public void testStates() {
Layer states = find("topp:states");
assertNotNull(states);
ResourceInfo info = wms.getInfo(states);
assertNotNull(info);
assertEquals(states.getTitle(), info.getTitle());
ReferencedEnvelope bounds = info.getBounds();
assertNotNull(bounds);
assertFalse(bounds.isEmpty());
}
private Layer find(String name, WMSCapabilities caps) {
for (Layer layer : caps.getLayerList()) {
if (name.equals(layer.getName())) {
return layer;
}
}
return null;
}
private Layer find(String name) {
return find(name, capabilities);
}
public void testServiceInfo() {
ServiceInfo info = wms.getInfo();
assertNotNull(info);
assertEquals(serverURL, wms.getCapabilities().getRequest().getGetCapabilities().getGet());
assertEquals("GeoServer Web Map Service", info.getTitle());
assertNotNull(info.getDescription());
}
String axisName(CoordinateReferenceSystem crs, int dimension) {
return crs.getCoordinateSystem().getAxis(dimension).getName().getCode();
}
public void testImgSample130() throws Exception {
Layer water_bodies = find("topp:tasmania_water_bodies");
assertNotNull("Img_Sample layer found", water_bodies);
CRSEnvelope latLon = water_bodies.getLatLonBoundingBox();
assertEquals("LatLonBoundingBox axis 0 name", "Geodetic longitude",
axisName(latLon.getCoordinateReferenceSystem(), 0));
assertEquals("LatLonBoundingBox axis 0 name", "Geodetic latitude",
axisName(latLon.getCoordinateReferenceSystem(), 1));
boolean globalXY = Boolean.getBoolean("org.geotools.referencing.forceXY");
CRSEnvelope bounds = water_bodies.getBoundingBoxes().get("EPSG:4326");
CoordinateReferenceSystem boundsCRS = bounds.getCoordinateReferenceSystem();
if( globalXY ){
// ensure WMS CRSEnvelope returned according to application globalXY setting
assertEquals( "EPSG:4326", AxisOrder.EAST_NORTH, CRS.getAxisOrder(boundsCRS) );
}
else {
assertEquals( "EPSG:4326", AxisOrder.NORTH_EAST, CRS.getAxisOrder(boundsCRS) );
}
if( CRS.getAxisOrder(boundsCRS) == AxisOrder.EAST_NORTH ){
assertEquals("axis order 0 min", latLon.getMinimum(1), bounds.getMinimum(1));
assertEquals("axis order 1 min", latLon.getMinimum(0), bounds.getMinimum(0));
assertEquals("axis order 1 max", latLon.getMaximum(0), bounds.getMaximum(0));
assertEquals("axis order 1 min", latLon.getMaximum(1), bounds.getMaximum(1));
}
if( CRS.getAxisOrder(boundsCRS) == AxisOrder.NORTH_EAST ){
assertEquals("axis order 0 min", latLon.getMinimum(1), bounds.getMinimum(0));
assertEquals("axis order 1 min", latLon.getMinimum(0), bounds.getMinimum(1));
assertEquals("axis order 1 max", latLon.getMaximum(0), bounds.getMaximum(1));
assertEquals("axis order 1 min", latLon.getMaximum(1), bounds.getMaximum(0));
}
// GETMAP
checkGetMap(wms, water_bodies, DefaultGeographicCRS.WGS84);
checkGetMap(wms, water_bodies, CRS.decode("CRS:84"));
checkGetMap(wms, water_bodies, CRS.decode("EPSG:4326"));
checkGetMap(wms, water_bodies, CRS.decode("urn:x-ogc:def:crs:EPSG::4326"));
// GETFEATURE INFO
checkGetFeatureInfo( wms, water_bodies, DefaultGeographicCRS.WGS84 );
checkGetFeatureInfo(wms, water_bodies, CRS.decode("CRS:84"));
checkGetFeatureInfo( wms, water_bodies, CRS.decode("EPSG:4326") );
checkGetFeatureInfo( wms, water_bodies, CRS.decode("urn:x-ogc:def:crs:EPSG::4326") );
}
public void testImageSample111() throws Exception {
WebMapServer wms111 = new WebMapServer(new URL(serverURL + "&VERSION=1.1.1"));
WMSCapabilities caps = wms111.getCapabilities();
assertEquals("1.1.1", caps.getVersion());
Layer water_bodies = find("topp:tasmania_water_bodies", caps);
assertNotNull("Img_Sample layer found", water_bodies);
CRSEnvelope latLon = water_bodies.getLatLonBoundingBox();
assertEquals("LatLonBoundingBox axis 0 name", "Geodetic longitude",
axisName(latLon.getCoordinateReferenceSystem(), 0));
assertEquals("LatLonBoundingBox axis 1 name", "Geodetic latitude",
axisName(latLon.getCoordinateReferenceSystem(), 1));
CRSEnvelope bounds = water_bodies.getBoundingBoxes().get("EPSG:4326");
CoordinateReferenceSystem boundsCRS = bounds.getCoordinateReferenceSystem();
assertEquals( "EPSG:4326", AxisOrder.EAST_NORTH, CRS.getAxisOrder(boundsCRS) );;
assertEquals("axis order 0 min", latLon.getMinimum(0), bounds.getMinimum(0));
assertEquals("axis order 1 min", latLon.getMinimum(1), bounds.getMinimum(1));
assertEquals("axis order 1 max", latLon.getMaximum(0), bounds.getMaximum(0));
assertEquals("axis order 1 min", latLon.getMaximum(1), bounds.getMaximum(1));
// GETMAP
checkGetMap(wms111, water_bodies, DefaultGeographicCRS.WGS84);
checkGetMap(wms111, water_bodies, CRS.decode("CRS:84"));
checkGetMap(wms111, water_bodies, CRS.decode("EPSG:4326"));
checkGetMap(wms111, water_bodies, CRS.decode("urn:x-ogc:def:crs:EPSG::4326"));
// GETFEATURE INFO
checkGetFeatureInfo( wms111, water_bodies, DefaultGeographicCRS.WGS84 );
checkGetFeatureInfo( wms111, water_bodies, CRS.decode("CRS:84"));
checkGetFeatureInfo( wms111, water_bodies, CRS.decode("EPSG:4326") );
checkGetFeatureInfo( wms111, water_bodies, CRS.decode("urn:x-ogc:def:crs:EPSG::4326") );
}
private String format(OperationType operationType, String search) {
for (String format : operationType.getFormats()) {
if (format.contains(search)) {
return format;
}
}
return null; // not found
}
/**
* Check GetMap request functionality in the provided CRS.
* <p>
* Attempt is made to request the entire image.
*
* @param wms
* @param layer
* @param crs
*/
private void checkGetMap(WebMapServer wms, Layer layer, CoordinateReferenceSystem crs)
throws Exception {
layer.clearCache();
CRSEnvelope latLon = layer.getLatLonBoundingBox();
GeneralEnvelope envelope = wms.getEnvelope(layer, crs);
assertFalse(envelope.isEmpty() || envelope.isNull() || envelope.isInfinite());
assertNotNull("Envelope "+CRS.toSRS(crs), envelope);
GetMapRequest getMap = wms.createGetMapRequest();
OperationType operationType = wms.getCapabilities().getRequest().getGetMap();
getMap.addLayer(layer);
String version = wms.getCapabilities().getVersion();
getMap.setBBox(envelope);
Properties properties = getMap.getProperties();
String srs = null;
if( properties.containsKey("SRS")){
srs = properties.getProperty("SRS");
}
else if( properties.containsKey("CRS")){
srs = properties.getProperty("CRS");
}
assertNotNull( "setBBox supplied SRS information", srs );
String expectedSRS = CRS.toSRS(envelope.getCoordinateReferenceSystem());
assertEquals( "srs matches CRS.toSRS", expectedSRS, srs );
assertTrue( "cite authority:"+srs, srs.contains("CRS") || srs.contains("EPSG") );
//getMap.setSRS( srs );
String format = format(operationType, "jpeg");
getMap.setFormat(format);
getMap.setDimensions(500, 500);
URL url = getMap.getFinalURL();
GetMapResponse response = wms.issueRequest(getMap);
assertEquals("image/jpeg", response.getContentType());
InputStream stream = response.getInputStream();
BufferedImage image = ImageIO.read(stream);
assertNotNull("jpeg", image);
assertEquals(500, image.getWidth());
assertEquals(500, image.getHeight());
int rgb = image.getRGB(70, 420);
Color sample = new Color(rgb);
boolean forceXY = Boolean.getBoolean(GeoTools.FORCE_LONGITUDE_FIRST_AXIS_ORDER);
String context = "srs="+srs+" forceXY="+forceXY+" Version="+version;
if(Color.WHITE.equals(sample)){
System.out.println("FAIL: "+ context+": GetMap BBOX=" + envelope);
System.out.println("--> " + url);
fail( context+": GetMap BBOX=" + envelope );
}
else {
//System.out.println("PASS: "+ context+": GetMap BBOX=" + bbox);
}
}
/**
* Check GetMap request functionality in the provided CRS.
* <p>
* Attempt is made to request the entire image.
*
* @param wms
* @param layer
* @param crs
*/
private void checkGetFeatureInfo(WebMapServer wms, Layer layer, CoordinateReferenceSystem crs)
throws Exception {
layer.clearCache();
CRSEnvelope latLon = layer.getLatLonBoundingBox();
GeneralEnvelope envelope = wms.getEnvelope(layer, crs);
assertFalse(envelope.isEmpty() || envelope.isNull() || envelope.isInfinite());
assertNotNull("Envelope "+CRS.toSRS(crs), envelope);
GetMapRequest getMap = wms.createGetMapRequest();
OperationType operationType = wms.getCapabilities().getRequest().getGetMap();
getMap.addLayer(layer);
String version = wms.getCapabilities().getVersion();
String srs = CRS.toSRS(envelope.getCoordinateReferenceSystem());
getMap.setBBox(envelope);
String format = format(operationType, "jpeg");
getMap.setFormat(format);
getMap.setDimensions(500, 500);
URL url = getMap.getFinalURL();
GetFeatureInfoRequest getFeatureInfo = wms.createGetFeatureInfoRequest(getMap);
getFeatureInfo.setInfoFormat("text/html");
getFeatureInfo.setQueryLayers( Collections.singleton(layer));
getFeatureInfo.setQueryPoint(75, 100);
URL url2 = getFeatureInfo.getFinalURL();
GetFeatureInfoResponse response = wms.issueRequest(getFeatureInfo);
assertEquals("text/html", response.getContentType());
InputStream stream = response.getInputStream();
StringBuilderWriter writer = new StringBuilderWriter();
IOUtils.copy(stream, writer);
String info = writer.toString();
assertTrue( "response available", !info.isEmpty() );
assertTrue( "html", info.contains("<html") || info.contains("<HTML"));
boolean forceXY = Boolean.getBoolean(GeoTools.FORCE_LONGITUDE_FIRST_AXIS_ORDER);
String context = "srs="+srs+" forceXY="+forceXY+" Version="+version;
if( !info.contains("tasmania_water_bodies.3") ){
System.out.println("FAIL: "+ context+": GetFeatureInfo BBOX=" + envelope);
System.out.println("GETMAP --> " + url);
System.out.println("GETFEATUREINFO --> " + url2);
fail( context+": GetFeatureInfo BBOX=" + envelope );
}
}
public void testGetStyle() throws Exception {
String baseUrl = LocalGeoServerOnlineTest.LOCAL_GEOSERVER;
String layers = LocalGeoServerOnlineTest.LOCAL_LAYERS;
URL url = new URL(baseUrl);
GetStylesResponse wmsResponse = null;
GetStylesRequest wmsRequest = null;
StyleFactory styleFactory = new StyleFactoryImpl();
WebMapServer server = new WebMapServer(url) {
// GetStyle is only implemented in WMS 1.1.1
protected void setupSpecifications() {
specs = new Specification[1];
specs[0] = new WMS1_1_1();
}
};
wmsRequest = server.createGetStylesRequest();
wmsRequest.setLayers(layers);
// Test URL
String queryParamters = wmsRequest.getFinalURL().getQuery();
Map parameters = new HashMap();
String[] rawParameters = queryParamters.split("&");
for(String param : rawParameters){
String [] keyValue = param.split("=");
parameters.put(keyValue[0],keyValue[1]);
}
assertTrue(parameters.size() >= 4);
assertEquals("WMS", parameters.get("SERVICE"));
assertEquals("GetStyles", parameters.get("REQUEST"));
assertEquals("1.1.1", parameters.get("VERSION"));
assertEquals(layers, parameters.get("LAYERS"));
wmsResponse = server.issueRequest(wmsRequest);
// Set encoding of response from HTTP content-type header
ContentType contentType = new ContentType(wmsResponse.getContentType());
InputStreamReader stream;
if(contentType.getParameter("charset") != null)
stream = new InputStreamReader(wmsResponse.getInputStream(), contentType.getParameter("charset"));
else
stream = new InputStreamReader(wmsResponse.getInputStream());
Style[] styles = (new SLDParser(styleFactory, stream)).readXML();
assert styles.length > 0;
SLDTransformer styleTransform = new SLDTransformer();
StyledLayerDescriptorBuilder SLDBuilder = new StyledLayerDescriptorBuilder();
NamedLayerBuilder namedLayerBuilder = SLDBuilder.namedLayer();
namedLayerBuilder.name(layers);
org.geotools.styling.builder.StyleBuilder styleBuilder = namedLayerBuilder.style();
for(int i =0; i<styles.length; i++){
styleBuilder.reset(styles[i]);
styles[i] = styleBuilder.build();
}
NamedLayer namedLayer = namedLayerBuilder.build();
for(Style style: styles)
namedLayer.addStyle(style);
StyledLayerDescriptor sld = (new StyledLayerDescriptorBuilder()).build();
sld.addStyledLayer(namedLayer);
String xml = styleTransform.transform(sld);
assert xml.length() > 300;
}
}