package org.deegree.securityproxy.wms.request; import static java.lang.String.format; import static java.util.Arrays.asList; import static org.deegree.securityproxy.request.parser.OwsRequestParserUtils.checkRequiredParameter; import static org.deegree.securityproxy.request.parser.OwsRequestParserUtils.checkSingleRequiredParameter; import static org.deegree.securityproxy.request.parser.OwsRequestParserUtils.evaluateVersion; import static org.deegree.securityproxy.request.KvpNormalizer.normalizeKvpMap; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.deegree.securityproxy.request.OwsServiceVersion; import org.deegree.securityproxy.request.UnsupportedRequestTypeException; import org.deegree.securityproxy.request.parser.OwsRequestParser; import com.vividsolutions.jts.geom.Envelope; /** * Parses an incoming {@link javax.servlet.http.HttpServletRequest} into a * {@link org.deegree.securityproxy.wms.request.WmsRequest}. * * @author <a href="stenger@lat-lon.de">Dirk Stenger</a> * @author last edited by: $Author: stenger $ * @version $Revision: $, $Date: $ */ public class WmsRequestParser implements OwsRequestParser { public static final OwsServiceVersion VERSION_130 = new OwsServiceVersion( 1, 3, 0 ); public static final String WMS_SERVICE = "WMS"; public static final String GETCAPABILITIES = "GetCapabilities"; public static final String GETFEATUREINFO = "GetFeatureInfo"; public static final String GETMAP = "GetMap"; private static final String REQUEST = "request"; private static final String SERVICE = "service"; private static final String VERSION = "version"; private static final String LAYERS = "layers"; private static final String CRS = "crs"; private static final String BBOX = "bbox"; private static final String WIDTH = "width"; private static final String HEIGHT = "height"; private static final String FORMAT = "format"; private static final String STYLES = "styles"; private static final String QUERY_LAYERS = "query_layers"; private static final String INFO_FORMAT = "info_format"; private static final String I = "i"; private static final String J = "j"; private final List<OwsServiceVersion> supportedVersion = asList( VERSION_130 ); @Override @SuppressWarnings("unchecked") public WmsRequest parse( HttpServletRequest request ) throws UnsupportedRequestTypeException { if ( request == null ) throw new IllegalArgumentException( "Request must not be null!" ); String serviceName = evaluateServiceName( request ); Map<String, String[]> normalizedParameterMap = normalizeKvpMap( request.getParameterMap() ); checkParameters( normalizedParameterMap ); return parseRequest( serviceName, normalizedParameterMap ); } Envelope parseBbox( String bboxParameter ) { String[] coordinates = bboxParameter.split( "," ); if ( coordinates.length != 4 ) { String msg = format( "Format of Parameter 'BBox' is invalid, must be minX,minY,maxX,maxY, was %s", bboxParameter ); throw new IllegalArgumentException( msg ); } double minX = parseDouble( "minX", coordinates[0] ); double minY = parseDouble( "minY", coordinates[1] ); double maxX = parseDouble( "maxY", coordinates[2] ); double maxY = parseDouble( "maxY", coordinates[3] ); return new Envelope( minX, maxX, minY, maxY ); } private WmsRequest parseRequest( String serviceName, Map<String, String[]> normalizedParameterMap ) throws UnsupportedRequestTypeException { String type = normalizedParameterMap.get( REQUEST )[0]; if ( GETCAPABILITIES.equalsIgnoreCase( type ) ) return parseGetCapabilitiesRequest( serviceName, normalizedParameterMap ); if ( GETFEATUREINFO.equalsIgnoreCase( type ) ) return parseGetFeatureInfoRequest( serviceName, normalizedParameterMap ); if ( GETMAP.equalsIgnoreCase( type ) ) return parseGetMapRequest( serviceName, normalizedParameterMap ); throw new IllegalArgumentException( "Unrecognized operation type: " + type ); } private WmsRequest parseGetMapRequest( String serviceName, Map<String, String[]> normalizedParameterMap ) { checkGetMapParameters( normalizedParameterMap ); OwsServiceVersion version = evaluateVersion( VERSION, normalizedParameterMap, supportedVersion ); List<String> separatedLayers = extractLayers( normalizedParameterMap.get( LAYERS ) ); Envelope bbox = extractBbox( normalizedParameterMap.get( BBOX ) ); String crs = extractCrs( normalizedParameterMap.get( CRS ) ); String format = extractFormat( normalizedParameterMap.get( FORMAT ) ); return new WmsRequest( GETMAP, version, separatedLayers, serviceName, bbox, crs, format ); } private WmsRequest parseGetFeatureInfoRequest( String serviceName, Map<String, String[]> normalizedParameterMap ) { checkGetFeatureInfoParameters( normalizedParameterMap ); OwsServiceVersion version = evaluateVersion( VERSION, normalizedParameterMap, supportedVersion ); List<String> separatedLayers = extractLayers( normalizedParameterMap.get( LAYERS ) ); List<String> separatedQueryLayers = extractLayers( normalizedParameterMap.get( QUERY_LAYERS ) ); return new WmsRequest( GETFEATUREINFO, version, separatedLayers, separatedQueryLayers, serviceName ); } private WmsRequest parseGetCapabilitiesRequest( String serviceName, Map<String, String[]> normalizedParameterMap ) throws UnsupportedRequestTypeException { checkGetCapabilitiesParameters( normalizedParameterMap ); OwsServiceVersion version = evaluateVersion( VERSION, normalizedParameterMap, supportedVersion ); return new WmsRequest( GETCAPABILITIES, version, serviceName ); } private String evaluateServiceName( HttpServletRequest request ) { String servletPath = request.getServletPath(); if ( servletPath == null ) throw new IllegalArgumentException( "Service name must not be null!" ); if ( servletPath.contains( "/" ) ) { String[] splittedServletPath = servletPath.split( "/" ); return splittedServletPath[splittedServletPath.length - 1]; } return servletPath; } private List<String> extractLayers( String[] layerParameters ) { List<String> separatedLayers = new ArrayList<String>(); if ( layerParameters != null ) { for ( String layerParameter : layerParameters ) { Collections.addAll( separatedLayers, layerParameter.split( "," ) ); } } return separatedLayers; } private Envelope extractBbox( String[] bboxParameters ) { String bboxParameter = bboxParameters[0]; return parseBbox( bboxParameter ); } private String extractCrs( String[] crsParameters ) { return crsParameters[0]; } private String extractFormat( String[] formatParameters ) { return formatParameters[0]; } private double parseDouble( String coordName, String coordinate ) { try { return Double.parseDouble( coordinate.trim() ); } catch ( NumberFormatException e ) { String msg = format( "Coordinate %s is not a valid double value: %s", coordName, coordinate ); throw new IllegalArgumentException( msg ); } } private void checkParameters( Map<String, String[]> normalizedParameterMap ) { checkRequestParameter( normalizedParameterMap ); } private void checkServiceParameter( Map<String, String[]> normalizedParameterMap ) throws UnsupportedRequestTypeException { String serviceType = checkSingleRequiredParameter( normalizedParameterMap, SERVICE ); if ( !"wms".equalsIgnoreCase( serviceType ) ) { String msg = "Request must contain a \"service\" parameter with value \"wms\""; throw new UnsupportedRequestTypeException( msg ); } } private void checkRequestParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, REQUEST ); } private void checkGetMapParameters( Map<String, String[]> normalizedParameterMap ) { checkLayersParameter( normalizedParameterMap ); checkStylesParameter( normalizedParameterMap ); checkCrsParameter( normalizedParameterMap ); checkBboxParameter( normalizedParameterMap ); checkWidthParameter( normalizedParameterMap ); checkHeightParameter( normalizedParameterMap ); checkFormatParameter( normalizedParameterMap ); } private void checkGetFeatureInfoParameters( Map<String, String[]> normalizedParameterMap ) { checkQueryLayersParameter( normalizedParameterMap ); checkInfoFormatParameter( normalizedParameterMap ); checkIParameter( normalizedParameterMap ); checkJParameter( normalizedParameterMap ); checkLayersParameter( normalizedParameterMap ); checkStylesParameter( normalizedParameterMap ); checkCrsParameter( normalizedParameterMap ); checkBboxParameter( normalizedParameterMap ); checkWidthParameter( normalizedParameterMap ); checkHeightParameter( normalizedParameterMap ); checkFormatParameter( normalizedParameterMap ); } private void checkGetCapabilitiesParameters( Map<String, String[]> normalizedParameterMap ) throws UnsupportedRequestTypeException { checkServiceParameter( normalizedParameterMap ); } private void checkLayersParameter( Map<String, String[]> normalizedParameterMap ) { checkRequiredParameter( normalizedParameterMap, LAYERS ); } private void checkStylesParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, STYLES ); } private void checkCrsParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, CRS ); } private void checkBboxParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, BBOX ); } private void checkWidthParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, WIDTH ); } private void checkHeightParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, HEIGHT ); } private void checkQueryLayersParameter( Map<String, String[]> normalizedParameterMap ) { checkRequiredParameter( normalizedParameterMap, QUERY_LAYERS ); } private void checkInfoFormatParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, INFO_FORMAT ); } private void checkIParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, I ); } private void checkJParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, J ); } private void checkFormatParameter( Map<String, String[]> normalizedParameterMap ) { checkSingleRequiredParameter( normalizedParameterMap, FORMAT ); } }