Skip to content

Commit

Permalink
Have OpenSearch not balk at empty keys (non EO opensearch clients wil…
Browse files Browse the repository at this point in the history
…l send those by following the url template)
  • Loading branch information
aaime committed May 3, 2017
1 parent 52d748a commit 2dc8c4e
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@

<!-- Dispatcher callback to force kvp parsing in absence of any kvp param -->
<bean id="oseoDispatcherCallback" class="org.geoserver.opensearch.eo.OSEODispatcherCallback" />
<!-- Filter to force service and version in case they are missing to avoid KVP parsing issues -->
<bean id="oseoServiceFilter" class="org.geoserver.opensearch.eo.OSEOFilter" />

<!-- kvp request readers -->
<bean id="oseoDescriptionRequestKvpParser" class="org.geoserver.opensearch.eo.kvp.DescriptionRequestKvpReader" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
*/
package org.geoserver.opensearch.eo;

import java.util.HashSet;
import java.util.Map;

import org.geoserver.opensearch.eo.response.AtomSearchResponse;
import org.geoserver.ows.AbstractDispatcherCallback;
import org.geoserver.ows.Request;
import org.geoserver.platform.Service;
import org.geoserver.platform.ServiceException;
import org.geoserver.security.Response;
import org.springframework.util.StringUtils;

/**
* Temporary trick to force GeoServer KVP parsing of description when there is no KVP param at all
Expand All @@ -22,18 +25,31 @@ public class OSEODispatcherCallback extends AbstractDispatcherCallback {
@Override
public Service serviceDispatched(Request request, Service service) throws ServiceException {
final Map kvp = request.getKvp();
if("oseo".equals(request.getService()) && kvp.isEmpty()) {
if("description".equals(request.getRequest())) {
kvp.put("service", "oseo");
// the raw kvp is normally not even initialized
final Map rawKvp = request.getRawKvp();
if("oseo".equalsIgnoreCase(request.getService()) ) {
if(kvp.isEmpty()) {
if("description".equals(request.getRequest())) {
kvp.put("service", "oseo");
// the raw kvp is normally not even initialized
request.setRawKvp(kvp);
} else if("search".equals(request.getRequest())) {
kvp.put("service", "oseo");
kvp.put("httpAccept", AtomSearchResponse.MIME);
}
// make sure the raw kvp is not empty, ever (the current code
// leaves it empty if the request has no search params)
request.setRawKvp(kvp);
} else if("search".equals(request.getRequest())) {
kvp.put("service", "oseo");
kvp.put("httpAccept", AtomSearchResponse.MIME);
} else {
// skip everything that has an empty value, in OpenSearch it should be ignored
// (clients following the template to the letter will create keys with empty value)
for (String key : new HashSet<String>(request.getRawKvp().keySet())) {
Object value = rawKvp.get(key);
if(!(value instanceof String) || StringUtils.isEmpty((String) value)) {
rawKvp.remove(key);
kvp.remove(key);
}
}
}
// make sure the raw kvp is not empty, ever (the current code
// leaves it empty if the request has no search params)
request.setRawKvp(kvp);
}
return service;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* (c) 2017 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.opensearch.eo;

import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.geoserver.filters.GeoServerFilter;

public class OSEOFilter implements GeoServerFilter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {
// nothing to do
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
HttpServletRequest requestHTTP = (HttpServletRequest)request;
if (requestNeedsWrapper(requestHTTP)) {
request = new RequestWrapper(requestHTTP);
}
}
chain.doFilter(request, response);

}

private boolean requestNeedsWrapper(HttpServletRequest requestHTTP) {
return "GET".equalsIgnoreCase(requestHTTP.getMethod()) && !(new CaseInsensitiveMap(requestHTTP.getParameterMap()).containsKey("service"))
&& (requestHTTP.getPathInfo().endsWith("search") || requestHTTP.getPathInfo().endsWith("description"));
}

@Override
public void destroy() {
// nothing to do
}

private static class RequestWrapper extends HttpServletRequestWrapper {
private String request;

private RequestWrapper(HttpServletRequest wrapped) {
super(wrapped);
if(wrapped.getPathInfo().endsWith("search")) {
request = "search";
} else {
request = "description";
}
}

@Override
public Enumeration getParameterNames() {
return Collections.enumeration(getParameterMap().keySet());
}

@Override
public Map<String,String[]> getParameterMap() {
Map<String, String[]> original = super.getParameterMap();
Map filtered = new HashMap<String, String[]>(original);
filtered.put("service", "OSEO");
filtered.put("version", "1.0.0");
filtered.put("request", request);
return filtered;
}

@Override
public String[] getParameterValues(String name) {
if ("service".equalsIgnoreCase(name)) {
return new String[] {"OSEO"};
}
if ("request".equalsIgnoreCase(name)) {
return new String[] {request};
}
return super.getParameterValues(name);
}

@Override
public String getParameter(String name) {
if ("service".equalsIgnoreCase(name)) {
return "OSEO";
}
if ("request".equalsIgnoreCase(name)) {
return request;
}
return super.getParameter(name);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.spatial.DWithin;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.springframework.util.StringUtils;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
Expand Down Expand Up @@ -183,7 +184,7 @@ private Filter readFilter(Map rawKvp, Collection<Parameter<?>> parameters) throw
List<Filter> filters = new ArrayList<>();
for (Parameter<?> parameter : parameters) {
Object value = rawKvp.get(parameter.key);
if (value != null && !NOT_FILTERS.contains(parameter.key)) {
if (!StringUtils.isEmpty(value) && !NOT_FILTERS.contains(parameter.key)) {
Filter filter = null;
if (SEARCH_TERMS.key.equals(parameter.key)) {
filter = buildSearchTermsFilter(value);
Expand Down Expand Up @@ -592,7 +593,7 @@ private Object parseParameter(Parameter<?> parameter, String value) {
Object converted = Converters.convert(value, parameter.getType(), SAFE_CONVERSION_HINTS);
if (converted == null) {
throw new OWS20Exception(
value + " of key " + parameter.key + " cannot be converted to a "
"Value '" + value + "' of key " + parameter.key + " cannot be converted to a "
+ parameter.getType().getSimpleName(),
OWSExceptionCode.InvalidParameterValue, parameter.key);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.servlet.Filter;
import javax.xml.XMLConstants;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
Expand Down Expand Up @@ -60,6 +63,10 @@ public class OSEOTestSupport extends GeoServerSystemTestSupport {
throw new RuntimeException("Could not parse the OpenSearch schemas", e);
}
}

protected List<Filter> getFilters() {
return Collections.singletonList(new OSEOFilter());
}

@Override
protected void setUpTestData(SystemTestData testData) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,33 @@ public void testProductById() throws Exception {
public void testAllSentinel2Products() throws Exception {
Document dom = getAsDOM(
"oseo/search?parentId=SENTINEL2&httpAccept=" + AtomSearchResponse.MIME);
print(dom);
// print(dom);

assertFirstPageSentinel2Products(dom);
}

@Test
public void testAllSentinel2EmptyParams() throws Exception {
// a URL generated by a client following the opensearch template to the letter (without
// omitting the keys for missing params like OpenSearch for EO suggests to)
Document dom = getAsDOM(
"oseo/search?parentId=SENTINEL2&searchTerms=&startIndex=&count=&uid=&box="
+ "&name=&lat=&lon=&radius=&geometry=&geoRelation="
+ "&timeStart=&timeEnd=&timeRelation=&illuminationAzimuthAngle="
+ "&illuminationZenithAngle=&illuminationElevationAngle=&resolution=&identifier="
+ "&productQualityDegradationStatus=&archivingCenter=&parentIdentifier="
+ "&productionStatus=&acquisitionSubtype=&acquisitionType=&productQualityStatus="
+ "&processorName=&orbitDirection=&processingCenter=&sensorMode=&processingMode="
+ "&swathIdentifier=&creationDate=&modificationDate=&processingDate="
+ "&availabilityTime=&acquisitionStation=&orbitNumber=&track=&frame="
+ "&startTimeFromAscendingNode=&completionTimeFromAscendingNode="
+ "&cloudCover=&snowCover=&httpAccept=atom");
print(dom);

assertFirstPageSentinel2Products(dom);
}

private void assertFirstPageSentinel2Products(Document dom) {
assertThat(dom, hasXPath("/at:feed/os:totalResults", equalTo("19")));

// check that filtering worked
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.geoserver.opensearch.eo.OpenSearchParameters.*;
import static org.geoserver.opensearch.eo.kvp.SearchRequestKvpReader.COUNT_KEY;
import static org.geoserver.opensearch.eo.kvp.SearchRequestKvpReader.PARENT_ID_KEY;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.*;
Expand Down Expand Up @@ -418,6 +419,13 @@ public void testCollectionSensorTypeList() throws Exception {
assertBinaryFilter(children.get(2), OpenSearchAccess.EO_NAMESPACE, "sensorType", "ALTIMETRIC");
}

@Test
public void testCloudCoverEmpty() throws Exception {
Map<String, String> map = toMap("parentId", "SENTINEL2", "cloudCover", "");
Filter filter = parseAndGetFilter(map);
assertThat(filter, equalTo(Filter.INCLUDE));
}

@Test
public void testCloudCoverGreater() throws Exception {
Map<String, String> map = toMap("parentId", "SENTINEL2", "cloudCover", "[30");
Expand Down
1 change: 1 addition & 0 deletions src/wms/src/main/java/applicationContext.xml
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@
</bean>
<bean id="startIndexKvpParser" class="org.geoserver.ows.kvp.IntegerKvpParser">
<constructor-arg value="startIndex"/>
<property name="service" value="WMS"/>
</bean>
<bean id="angleKvpParser" class="org.geoserver.ows.kvp.DoubleKvpParser">
<constructor-arg value="angle"/>
Expand Down

0 comments on commit 2dc8c4e

Please sign in to comment.