Skip to content

Commit 49134eb

Browse files
committed
WMTS CITE compliance fixes
1 parent 76c34e0 commit 49134eb

File tree

6 files changed

+156
-100
lines changed

6 files changed

+156
-100
lines changed

geowebcache/core/src/main/java/org/geowebcache/service/OWSException.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,26 @@ public String toString() {
5555
str.append(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
5656
str.append(
5757
" xsi:schemaLocation=\"http://www.opengis.net/ows/1.1 http://geowebcache.org/schema/ows/1.1.0/owsExceptionReport.xsd\">\n");
58-
str.append(" <Exception exceptionCode=\"" + exceptionCode + "\" locator=\"" + locator + "\">\n");
58+
if (locator != null) {
59+
str.append(" <Exception exceptionCode=\"" + exceptionCode + "\" locator=\"" + locator + "\">\n");
60+
} else {
61+
str.append(" <Exception exceptionCode=\"" + exceptionCode + "\">\n");
62+
}
63+
5964
str.append(" <ExceptionText>" + exceptionText + "</ExceptionText>\n");
6065
str.append(" </Exception>\n");
6166
str.append("</ExceptionReport>\n");
6267

6368
return str.toString();
6469
}
70+
71+
/** Returns the OWS exception <code>code</code> attribute */
72+
public String getExceptionCode() {
73+
return exceptionCode;
74+
}
75+
76+
/** Returns the OWS exception <code>locator</code> attribute */
77+
public String getLocator() {
78+
return locator;
79+
}
6580
}

geowebcache/wmts/src/main/java/org/geowebcache/service/wmts/WMTSGetCapabilities.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,10 @@ private void serviceIdentification(XMLBuilder xml, ServiceInformation servInfo)
297297
appendTag(xml, "ows:Title", servInfo.getTitle(), "Web Map Tile Service - GeoWebCache");
298298
appendTag(xml, "ows:Abstract", servInfo.getDescription(), null);
299299

300-
if (servInfo != null && servInfo.getKeywords() != null) {
300+
// a keywords element cannot be empty
301+
if (servInfo != null
302+
&& servInfo.getKeywords() != null
303+
&& !servInfo.getKeywords().isEmpty()) {
301304
xml.indentElement("ows:Keywords");
302305
Iterator<String> keywordIter = servInfo.getKeywords().iterator();
303306
while (keywordIter.hasNext()) {
@@ -453,17 +456,17 @@ private void layer(XMLBuilder xml, TileLayer layer, String baseurl, Set<GridSet>
453456

454457
appendTag(xml, "ows:Identifier", layer.getName(), null);
455458

459+
// WMTS 1.0 Layer is a ows:DatasetDescriptionSummary, which in turn can hold a ows:Metadata,
460+
// which finally
461+
// has the xlink:simpleAttrs attribute group, see https://www.w3.org/1999/xlink.xsd.
462+
// Unfortunately those links do not have a format attribute, so we can't use them for
463+
// metadata links.
456464
if (layer.getMetadataURLs() != null) {
457465
for (MetadataURL metadataURL : layer.getMetadataURLs()) {
458-
xml.indentElement("MetadataURL");
459-
xml.attribute("type", metadataURL.getType());
460-
xml.simpleElement("Format", metadataURL.getFormat(), true);
461-
xml.indentElement("OnlineResource")
462-
.attribute("xmlns:xlink", "http://www.w3.org/1999/xlink")
466+
xml.indentElement("ows:Metadata")
463467
.attribute("xlink:type", "simple")
464468
.attribute("xlink:href", metadataURL.getUrl().toString())
465469
.endElement();
466-
xml.endElement();
467470
}
468471
}
469472

geowebcache/wmts/src/main/java/org/geowebcache/service/wmts/WMTSGetFeatureInfo.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ protected void writeResponse(RuntimeStats stats) throws OWSException {
6767
TileLayer layer = convTile.getLayer();
6868

6969
GridSet gridSet = convTile.getGridSubset().getGridSet();
70-
if (gridSet.getTileHeight() < j || j < 0) {
70+
if (gridSet.getTileHeight() <= j || j < 0) {
7171
throw new OWSException(
7272
400, "PointIJOutOfRange", "J", "J was " + j + ", must be between 0 and " + gridSet.getTileHeight());
7373
}
7474

75-
if (gridSet.getTileWidth() < i || i < 0) {
75+
if (gridSet.getTileWidth() <= i || i < 0) {
7676
throw new OWSException(
7777
400, "PointIJOutOfRange", "I", "I was " + i + ", must be between 0 and " + gridSet.getTileWidth());
7878
}

geowebcache/wmts/src/main/java/org/geowebcache/service/wmts/WMTSService.java

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.geowebcache.util.NullURLMangler;
5151
import org.geowebcache.util.ServletUtils;
5252
import org.geowebcache.util.URLMangler;
53+
import org.springframework.http.MediaType;
5354

5455
public class WMTSService extends Service {
5556

@@ -248,6 +249,21 @@ public Conveyor getConveyor(HttpServletRequest request, HttpServletResponse resp
248249

249250
public Conveyor getRestConveyor(HttpServletRequest request, HttpServletResponse response)
250251
throws GeoWebCacheException, OWSException {
252+
// CITE compliance, if the representation is not available a 406 should be returned
253+
// This is also the behavior mandated by the HTTP standard
254+
String accept = request.getHeader("Accept");
255+
if (accept != null) {
256+
List<MediaType> mediaTypes = MediaType.parseMediaTypes(accept);
257+
boolean representationAvailable = false;
258+
for (MediaType mediaType : mediaTypes) {
259+
if (mediaType.includes(MediaType.APPLICATION_XML)) {
260+
representationAvailable = true;
261+
break;
262+
}
263+
}
264+
if (!representationAvailable) throw new HttpErrorCodeException(406, "Representation not available");
265+
}
266+
251267
final String path = request.getPathInfo();
252268

253269
// special simpler case for GetCapabilities
@@ -302,14 +318,13 @@ public Conveyor getKvpConveyor(HttpServletRequest request, HttpServletResponse r
302318
// if provided handle accepted versions parameter
303319
if (acceptedVersions != null) {
304320
// we only support version 1.0.0, so make sure that's one of the accepted versions
305-
String[] versions = acceptedVersions.split("\\s*,\\s*");
306-
int foundIndex = Arrays.binarySearch(versions, "1.0.0");
307-
if (foundIndex < 0) {
321+
List<String> versions = Arrays.asList(acceptedVersions.split("\\s*,\\s*"));
322+
if (!versions.contains("1.0.0")) {
308323
// no supported version is accepted
309324
throw new OWSException(
310325
400,
311326
"VersionNegotiationFailed",
312-
null,
327+
"null",
313328
"List of versions in AcceptVersions parameter value, in GetCapabilities "
314329
+ "operation request, did not include any version supported by this server.");
315330
}
@@ -409,6 +424,8 @@ private ConveyorTile getTile(
409424
}
410425

411426
MimeType mimeType = null;
427+
// the format should be present and valid also for GetFeatureInfo, while in CITE compliance
428+
// mode
412429
if (reqType == RequestType.TILE) {
413430
String format = values.get("format");
414431
if (format == null) {
@@ -437,6 +454,14 @@ private ConveyorTile getTile(
437454
"INFOFORMAT",
438455
"Unable to determine requested INFOFORMAT, " + infoFormat);
439456
}
457+
458+
if (isCiteCompliant() && !isRestRequest(request)) {
459+
String format = values.get("format");
460+
if (format == null) {
461+
throw new OWSException(
462+
400, "MissingParameterValue", "FORMAT", "Unable to determine requested FORMAT, " + format);
463+
}
464+
}
440465
}
441466

442467
final String tilematrixset = values.get("tilematrixset");
@@ -485,7 +510,7 @@ private ConveyorTile getTile(
485510
throw new OWSException(
486511
400,
487512
"TileOutOfRange",
488-
"TILECOLUMN",
513+
"TILECOL",
489514
"Column " + x + " is out of range, min: " + gridCov[0] + " max:" + gridCov[2]);
490515
}
491516

@@ -621,7 +646,7 @@ ServerConfiguration getMainConfiguration() {
621646
*
622647
* @return TRUE if GWC main configuration or at least one of the WMTS extensions forces CITE compliance
623648
*/
624-
private boolean isCiteCompliant() {
649+
protected boolean isCiteCompliant() {
625650
// let's see if main GWC configuration forces WMTS implementation to be CITE compliant
626651
if (mainConfiguration != null && mainConfiguration.isWmtsCiteCompliant()) {
627652
return true;

geowebcache/wmts/src/test/java/org/geowebcache/service/wmts/WMTSRestTest.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.junit.Assert.assertArrayEquals;
1919
import static org.junit.Assert.assertEquals;
2020
import static org.junit.Assert.assertFalse;
21+
import static org.junit.Assert.assertThrows;
2122
import static org.junit.Assert.assertTrue;
2223
import static org.mockito.ArgumentMatchers.any;
2324
import static org.mockito.ArgumentMatchers.anyInt;
@@ -64,6 +65,7 @@
6465
import org.geowebcache.layer.meta.VectorLayerMetadata;
6566
import org.geowebcache.mime.ApplicationMime;
6667
import org.geowebcache.mime.MimeType;
68+
import org.geowebcache.service.HttpErrorCodeException;
6769
import org.geowebcache.service.OWSException;
6870
import org.geowebcache.stats.RuntimeStats;
6971
import org.geowebcache.storage.StorageBroker;
@@ -142,6 +144,15 @@ public void testGetCap() throws Exception {
142144
doc);
143145
}
144146

147+
@Test
148+
public void testGetCapInvalidFormat() throws Exception {
149+
MockHttpServletRequest req = new MockHttpServletRequest();
150+
req.setPathInfo("geowebcache/service/wmts/rest/WMTSCapabilities.xml");
151+
req.addHeader("Accept", "invalid/format");
152+
HttpErrorCodeException exception = assertThrows(HttpErrorCodeException.class, () -> dispatch(req));
153+
assertEquals(406, exception.getErrorCode());
154+
}
155+
145156
@Test
146157
public void testGetTileWithStyle() throws Exception {
147158
MockHttpServletRequest req = new MockHttpServletRequest();

0 commit comments

Comments
 (0)