Skip to content

Commit

Permalink
[GEOS-8581]: WMS GetCapabilities limited CRSs output boundingBoxes im…
Browse files Browse the repository at this point in the history
…provements
  • Loading branch information
dromagnoli committed Feb 12, 2018
1 parent 45bf1cb commit a3fd16c
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* (c) 2018 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms.capabilities;

import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.renderer.crs.ProjectionHandler;
import org.geotools.renderer.crs.ProjectionHandlerFinder;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;

/**
* Extends ProjectionHandler in order to allow transforming a bbox into a
* target CRS when generating the Capabilities, therefore dealing with
* potential transformation exceptions due to domains out of validity.
*
*/
class CapabilitiesTransformerProjectionHandler extends ProjectionHandler {

public CapabilitiesTransformerProjectionHandler(ProjectionHandler handler)
throws FactoryException {
super(handler.getSourceCRS(), handler.getValidAreaBounds(), handler.getRenderingEnvelope());
}

@Override
protected ReferencedEnvelope transformEnvelope(ReferencedEnvelope envelope,
CoordinateReferenceSystem targetCRS) throws TransformException, FactoryException {
return super.transformEnvelope(envelope, targetCRS);
}

/**
* Create a CapabilitiesTransformerProjectionHandler for transformations from
* sourceCrs to targetCrs.
*
* @param sourceCrs the source CoordinateReferenceSystem
* @param targetCrs the target CoordinateReferenceSystem
* @return a proper ProjectionHandler or null if unable to get one.
*
* @throws MismatchedDimensionException
* @throws FactoryException
*/
public static CapabilitiesTransformerProjectionHandler create(
CoordinateReferenceSystem sourceCrs, CoordinateReferenceSystem targetCrs)
throws MismatchedDimensionException, FactoryException {
ProjectionHandler handler = ProjectionHandlerFinder
.getHandler(new ReferencedEnvelope(targetCrs), sourceCrs, false);
if (handler != null) {
return new CapabilitiesTransformerProjectionHandler(handler);
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand All @@ -38,7 +37,6 @@
import org.geoserver.catalog.AuthorityURLInfo;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.DataLinkInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.KeywordInfo;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerIdentifierInfo;
Expand All @@ -48,7 +46,6 @@
import org.geoserver.catalog.Predicates;
import org.geoserver.catalog.PublishedInfo;
import org.geoserver.catalog.PublishedType;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WMSLayerInfo;
import org.geoserver.catalog.WorkspaceInfo;
Expand All @@ -59,6 +56,7 @@
import org.geoserver.ows.URLMangler.URLType;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.json.JSONType;
import org.geoserver.wms.ExtendedCapabilitiesProvider;
import org.geoserver.wms.GetCapabilities;
import org.geoserver.wms.GetCapabilitiesRequest;
Expand All @@ -71,6 +69,8 @@
import org.geotools.referencing.CRS;
import org.geotools.referencing.CRS.AxisOrder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.renderer.crs.ProjectionHandler;
import org.geotools.renderer.crs.ProjectionHandlerFinder;
import org.geotools.styling.Style;
import org.geotools.util.NumberRange;
import org.geotools.util.logging.Logging;
Expand All @@ -91,7 +91,6 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.vividsolutions.jts.geom.Envelope;
import org.geoserver.wfs.json.JSONType;

/**
* Geotools xml framework based encoder for a Capabilities WMS 1.3.0 document.
Expand Down Expand Up @@ -1508,15 +1507,36 @@ private void handleAdditionalBBox(ReferencedEnvelope bbox, String crs, Published
continue; //already did this one
}

CoordinateReferenceSystem targetCrs = null;
try {
ReferencedEnvelope tbbox = bbox.transform(CRS.decode(srs), true);
targetCrs = CRS.decode(srs);
ReferencedEnvelope tbbox = bbox.transform(targetCrs, true);
handleBBox(tbbox, srs);
}
catch(Exception e) {
LOGGER.warning(String.format("Unable to transform bounding box for '%s' layer" +
" to %s", layer != null ? layer.getName() : "root", srs));
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
} catch(Exception e) {
// An exception is occurred during transformation. Try using a ProjectionHandler
try {
// Try transformation with a ProjectionHandler
CapabilitiesTransformerProjectionHandler handler = CapabilitiesTransformerProjectionHandler.
create(targetCrs, bbox.getCoordinateReferenceSystem());
if (handler == null) {
// Still no luck. Report the original issue
LOGGER.warning(String.format(
"Unable to transform bounding box for '%s' layer"
+ " to %s", layer != null ? layer.getName() : "root", srs));
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
}
} else {
ReferencedEnvelope tbbox = handler.transformEnvelope(bbox, targetCrs);
handleBBox(tbbox, srs);
}
} catch (FactoryException | TransformException e1) {
LOGGER.warning(String.format(
"Unable to transform bounding box for '%s' layer" + " to %s",
layer != null ? layer.getName() : "root", srs));
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, e1.getLocalizedMessage(), e1);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
import org.geotools.xml.transform.Translator;
import org.opengis.feature.type.Name;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;
import org.opengis.util.InternationalString;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -1438,15 +1439,36 @@ private void handleAdditionalBBox(ReferencedEnvelope bbox, String srs, Published
continue; //already did this one
}

CoordinateReferenceSystem targetCrs = null;
try {
ReferencedEnvelope tbbox = bbox.transform(CRS.decode(crs), true);
targetCrs = CRS.decode(crs);
ReferencedEnvelope tbbox = bbox.transform(targetCrs, true);
handleBBox(tbbox, crs);
}
catch(Exception e) {
LOGGER.warning(String.format("Unable to transform bounding box for '%s' layer" +
" to %s", layer != null ? layer.getName() : "root", srs));
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
} catch(Exception e) {
// An exception is occurred during transformation. Try using a ProjectionHandler
try {
// Try transformation with a ProjectionHandler
CapabilitiesTransformerProjectionHandler handler = CapabilitiesTransformerProjectionHandler.
create(targetCrs, bbox.getCoordinateReferenceSystem());
if (handler == null) {
// Still no luck. Report the original issue
LOGGER.warning(String.format(
"Unable to transform bounding box for '%s' layer"
+ " to %s", layer != null ? layer.getName() : "root", crs));
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
}
} else {
ReferencedEnvelope tbbox = handler.transformEnvelope(bbox, targetCrs);
handleBBox(tbbox, crs);
}
} catch (FactoryException | TransformException e1) {
LOGGER.warning(String.format(
"Unable to transform bounding box for '%s' layer" + " to %s",
layer != null ? layer.getName() : "root", crs));
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, e1.getLocalizedMessage(), e1);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void addSRSAndSetFlag() {
WMSInfo wms = getWMS().getServiceInfo();
wms.getSRS().add("4326");
wms.getSRS().add("3005");
wms.getSRS().add("3857");
wms.setBBOXForEachCRS(true);
getGeoServer().save(wms);
}
Expand All @@ -31,6 +32,7 @@ public void removeSRS() {
WMSInfo wms = getWMS().getServiceInfo();
wms.getSRS().remove("4326");
wms.getSRS().remove("3005");
wms.getSRS().remove("3857");
wms.setBBOXForEachCRS(false);
getGeoServer().save(wms);
}
Expand All @@ -42,13 +44,15 @@ public void testBBOXForEachCRS() throws Exception {
String layer = MockData.PRIMITIVEGEOFEATURE.getLocalPart();
assertXpathExists("//Layer[Name='"+layer+"']/BoundingBox[@SRS = 'EPSG:4326']", doc);
assertXpathNotExists("//Layer[Name='"+layer+"']/BoundingBox[@SRS = 'EPSG:3005']", doc);
assertXpathNotExists("//Layer[Name='"+layer+"']/BoundingBox[@SRS = 'EPSG:3857']", doc);

addSRSAndSetFlag();

doc = getAsDOM("sf/PrimitiveGeoFeature/wms?service=WMS&request=getCapabilities&version=1.1.0", true);

assertXpathExists("//Layer[Name='"+layer+"']/BoundingBox[@SRS = 'EPSG:4326']", doc);
assertXpathExists("//Layer[Name='"+layer+"']/BoundingBox[@SRS = 'EPSG:3005']", doc);
assertXpathExists("//Layer[Name='"+layer+"']/BoundingBox[@SRS = 'EPSG:3857']", doc);
}

@Test
Expand All @@ -57,11 +61,13 @@ public void testRootLayer() throws Exception {

assertXpathNotExists("/WMT_MS_Capabilities/Capability/Layer/BoundingBox[@SRS = 'EPSG:4326']", doc);
assertXpathNotExists("/WMT_MS_Capabilities/Capability/Layer/BoundingBox[@SRS = 'EPSG:3005']", doc);
assertXpathNotExists("/WMT_MS_Capabilities/Capability/Layer/BoundingBox[@SRS = 'EPSG:3857']", doc);

addSRSAndSetFlag();
doc = getAsDOM("sf/PrimitiveGeoFeature/wms?service=WMS&request=getCapabilities&version=1.1.0", true);

assertXpathExists("/WMT_MS_Capabilities/Capability/Layer/BoundingBox[@SRS = 'EPSG:4326']", doc);
assertXpathExists("/WMT_MS_Capabilities/Capability/Layer/BoundingBox[@SRS = 'EPSG:3005']", doc);
assertXpathExists("/WMT_MS_Capabilities/Capability/Layer/BoundingBox[@SRS = 'EPSG:3857']", doc);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

public class LayerGroupWorkspaceTest extends WMSTestSupport {

LayerGroupInfo global, global2, sf, cite, nested;
LayerGroupInfo global, global2, sf, cite, nested, world;

@Before
public void prepare() throws Exception {
Expand Down Expand Up @@ -60,6 +60,10 @@ public void prepare() throws Exception {
layer(cat, MockData.BUILDINGS));
cite.setWorkspace(cat.getWorkspaceByName("cite"));
cat.add(cite);

world = createLayerGroup(cat, "world", "world base", layer(cat, MockData.WORLD),
layer(cat, MockData.WORLD));
cat.add(world);
}

@After
Expand All @@ -72,6 +76,7 @@ public void rollback() throws Exception {
cat.remove(sf);
cat.remove(global);
cat.remove(global2);
cat.remove(world);
}

LayerInfo layer(Catalog cat, QName name) {
Expand Down Expand Up @@ -125,6 +130,7 @@ public void testGlobalCapabilities() throws Exception {

assertXpathExists("//Layer[Name='" + layer + "']/BoundingBox[@SRS = 'EPSG:4326']", dom);
assertXpathExists("//Layer[Name='" + layer + "']/BoundingBox[@SRS = 'EPSG:3005']", dom);
assertXpathExists("//Layer[Name='" + layer + "']/BoundingBox[@SRS = 'EPSG:3857']", dom);
}

@Test
Expand Down Expand Up @@ -237,6 +243,10 @@ public void testWorkspaceCapabilities() throws Exception {

assertXpathExists("//Layer[Name='" + layer + "']/BoundingBox[@SRS = 'EPSG:4326']", dom);
assertXpathExists("//Layer[Name='" + layer + "']/BoundingBox[@SRS = 'EPSG:3005']", dom);
assertXpathExists("//Layer[Name='" + layer + "']/BoundingBox[@SRS = 'EPSG:3857']", dom);

layer = "world";
assertXpathExists("//Layer[Name='" + layer + "']/BoundingBox[@SRS = 'EPSG:3857']", dom);
}

@Test
Expand Down Expand Up @@ -399,6 +409,7 @@ void addSRSAndSetFlag() {
WMSInfo wms = getWMS().getServiceInfo();
wms.getSRS().add("4326");
wms.getSRS().add("3005");
wms.getSRS().add("3857");
wms.setBBOXForEachCRS(true);
getGeoServer().save(wms);
}
Expand All @@ -408,6 +419,7 @@ public void removeSRS() {
WMSInfo wms = getWMS().getServiceInfo();
wms.getSRS().remove("4326");
wms.getSRS().remove("3005");
wms.getSRS().remove("3857");
wms.setBBOXForEachCRS(false);
getGeoServer().save(wms);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void addSRSAndSetFlag() {
WMSInfo wms = getWMS().getServiceInfo();
wms.getSRS().add("4326");
wms.getSRS().add("3005");
wms.getSRS().add("3857");
wms.setBBOXForEachCRS(true);
getGeoServer().save(wms);
}
Expand All @@ -38,6 +39,7 @@ public void removeSRS() {
WMSInfo wms = getWMS().getServiceInfo();
wms.getSRS().remove("4326");
wms.getSRS().remove("3005");
wms.getSRS().remove("3857");
wms.setBBOXForEachCRS(false);
getGeoServer().save(wms);
}
Expand All @@ -49,12 +51,14 @@ public void testBBOXForEachCRS() throws Exception {
String layer = MockData.PRIMITIVEGEOFEATURE.getLocalPart();
assertXpathExists("//wms:Layer[wms:Name='"+ layer+"']/wms:BoundingBox[@CRS = 'EPSG:4326']", doc);
assertXpathNotExists("//wms:Layer[wms:Name='"+ layer+"']/wms:BoundingBox[@CRS = 'EPSG:3005']", doc);
assertXpathNotExists("//wms:Layer[wms:Name='"+ layer+"']/wms:BoundingBox[@CRS = 'EPSG:3857']", doc);

addSRSAndSetFlag();
doc = getAsDOM("sf/PrimitiveGeoFeature/wms?service=WMS&request=getCapabilities&version=1.3.0", true);

assertXpathExists("//wms:Layer[wms:Name='"+layer+"']/wms:BoundingBox[@CRS = 'EPSG:4326']", doc);
assertXpathExists("//wms:Layer[wms:Name='"+layer+"']/wms:BoundingBox[@CRS = 'EPSG:3005']", doc);
assertXpathExists("//wms:Layer[wms:Name='"+layer+"']/wms:BoundingBox[@CRS = 'EPSG:3857']", doc);
}

@Test
Expand All @@ -63,11 +67,13 @@ public void testRootLayer() throws Exception {

assertXpathNotExists("/wms:WMS_Capabilities/wms:Capability/wms:Layer/wms:BoundingBox[@CRS = 'EPSG:4326']", doc);
assertXpathNotExists("/wms:WMS_Capabilities/wms:Capability/wms:Layer/wms:BoundingBox[@CRS = 'EPSG:3005']", doc);
assertXpathNotExists("/wms:WMS_Capabilities/wms:Capability/wms:Layer/wms:BoundingBox[@CRS = 'EPSG:3857']", doc);

addSRSAndSetFlag();
doc = getAsDOM("sf/PrimitiveGeoFeature/wms?service=WMS&request=getCapabilities&version=1.3.0", true);

assertXpathExists("/wms:WMS_Capabilities/wms:Capability/wms:Layer/wms:BoundingBox[@CRS = 'EPSG:4326']", doc);
assertXpathExists("/wms:WMS_Capabilities/wms:Capability/wms:Layer/wms:BoundingBox[@CRS = 'EPSG:3005']", doc);
assertXpathExists("/wms:WMS_Capabilities/wms:Capability/wms:Layer/wms:BoundingBox[@CRS = 'EPSG:3857']", doc);
}
}

0 comments on commit a3fd16c

Please sign in to comment.