001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/security/owsrequestvalidator/wms/GetFeatureInfoRequestValidator.java $
002 /*----------------------------------------------------------------------------
003 This file is part of deegree, http://deegree.org/
004 Copyright (C) 2001-2009 by:
005 Department of Geography, University of Bonn
006 and
007 lat/lon GmbH
008
009 This library is free software; you can redistribute it and/or modify it under
010 the terms of the GNU Lesser General Public License as published by the Free
011 Software Foundation; either version 2.1 of the License, or (at your option)
012 any later version.
013 This library is distributed in the hope that it will be useful, but WITHOUT
014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016 details.
017 You should have received a copy of the GNU Lesser General Public License
018 along with this library; if not, write to the Free Software Foundation, Inc.,
019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020
021 Contact information:
022
023 lat/lon GmbH
024 Aennchenstr. 19, 53177 Bonn
025 Germany
026 http://lat-lon.de/
027
028 Department of Geography, University of Bonn
029 Prof. Dr. Klaus Greve
030 Postfach 1147, 53001 Bonn
031 Germany
032 http://www.geographie.uni-bonn.de/deegree/
033
034 e-mail: info@deegree.org
035 ----------------------------------------------------------------------------*/
036 package org.deegree.security.owsrequestvalidator.wms;
037
038 import static org.deegree.security.drm.model.RightType.GETFEATUREINFO;
039
040 import java.util.List;
041
042 import org.deegree.datatypes.QualifiedName;
043 import org.deegree.datatypes.Types;
044 import org.deegree.model.feature.Feature;
045 import org.deegree.model.feature.FeatureFactory;
046 import org.deegree.model.feature.FeatureProperty;
047 import org.deegree.model.feature.schema.FeatureType;
048 import org.deegree.model.feature.schema.PropertyType;
049 import org.deegree.ogcwebservices.InvalidParameterValueException;
050 import org.deegree.ogcwebservices.OGCWebServiceRequest;
051 import org.deegree.ogcwebservices.wms.operation.GetFeatureInfo;
052 import org.deegree.ogcwebservices.wms.operation.GetMap;
053 import org.deegree.security.UnauthorizedException;
054 import org.deegree.security.drm.model.User;
055 import org.deegree.security.owsproxy.Condition;
056 import org.deegree.security.owsproxy.OperationParameter;
057 import org.deegree.security.owsproxy.Request;
058 import org.deegree.security.owsrequestvalidator.Messages;
059 import org.deegree.security.owsrequestvalidator.Policy;
060 import org.deegree.security.owsrequestvalidator.RequestValidator;
061
062 /**
063 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
064 * @author last edited by: $Author: mschneider $
065 *
066 * @version 1.1, $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
067 *
068 * @since 1.1
069 */
070
071 class GetFeatureInfoRequestValidator extends RequestValidator {
072
073 // known condition parameter
074 private static final String INFOLAYERS = "featureInfoLayers";
075
076 private static final String INFOFORMAT = "infoFormat";
077
078 private static final String FEATURECOUNT = "maxFeatureCount";
079
080 private static final String INVALIDCLICKPOINT = Messages.getString( "GetFeatureInfoRequestValidator.INVALIDCLICKPOINT" );
081
082 private static final String INVALIDLAYER = Messages.getString( "GetFeatureInfoRequestValidator.INVALIDLAYER" );
083
084 private static final String INVALIDFORMAT = Messages.getString( "GetFeatureInfoRequestValidator.INVALIDFORMAT" );
085
086 private static final String INAVLIDFEATURECOUNT = Messages.getString( "GetFeatureInfoRequestValidator.INAVLIDFEATURECOUNT" );
087
088 private static FeatureType gfiFT = null;
089
090 static {
091 if ( gfiFT == null ) {
092 gfiFT = GetFeatureInfoRequestValidator.createFeatureType();
093 }
094 }
095
096 /**
097 * @param policy
098 */
099 public GetFeatureInfoRequestValidator( Policy policy ) {
100 super( policy );
101 }
102
103 /**
104 * validates the incoming GetFeatureInfo request against the policy assigned to a validator
105 *
106 * @param request
107 * request to validate
108 * @param user
109 * name of the user who likes to perform the request (can be null)
110 */
111 @Override
112 public void validateRequest( OGCWebServiceRequest request, User user )
113 throws InvalidParameterValueException, UnauthorizedException {
114
115 userCoupled = false;
116 Request req = policy.getRequest( "WMS", "GetFeatureInfo" );
117 // request is valid because no restrictions are made
118 if ( req.isAny() || req.getPreConditions().isAny() ) {
119 return;
120 }
121 Condition condition = req.getPreConditions();
122
123 GetFeatureInfo wmsreq = (GetFeatureInfo) request;
124
125 // validate the GetMap request contained in the
126 // GetFeatureInfo request
127 GetMapRequestValidator gmrv = new GetMapRequestValidator( policy );
128 GetMap gmr = wmsreq.getGetMapRequestCopy();
129 gmrv.validateRequest( gmr, user );
130
131 validateXY( gmr, wmsreq );
132 validateInfoLayers( condition, wmsreq.getQueryLayers() );
133 validateInfoFormat( condition, wmsreq.getInfoFormat() );
134 validateFeatureCount( condition, wmsreq.getFeatureCount() );
135
136 if ( userCoupled ) {
137 validateAgainstRightsDB( wmsreq, user );
138 }
139
140 }
141
142 /**
143 * validates the click point (x,y coordinate) to be located within the map image that has been base of the
144 * GetFeatureInfo request
145 *
146 * @param gmr
147 * @param gfir
148 * @throws InvalidParameterValueException
149 */
150 private void validateXY( GetMap gmr, GetFeatureInfo gfir )
151 throws InvalidParameterValueException {
152
153 int x = gfir.getClickPoint().x;
154 int y = gfir.getClickPoint().y;
155
156 int width = gmr.getWidth();
157 int height = gmr.getHeight();
158
159 if ( x < 0 || x >= width || y < 0 || y >= height ) {
160 throw new InvalidParameterValueException( INVALIDCLICKPOINT );
161 }
162
163 }
164
165 /**
166 * validates if the requested info layers layers are valid against the policy/condition. If the passed user <>null
167 * this is checked against the user- and rights-management system/repository
168 *
169 * @param condition
170 * @param layers
171 * @throws InvalidParameterValueException
172 */
173 private void validateInfoLayers( Condition condition, String[] layers )
174 throws InvalidParameterValueException {
175
176 OperationParameter op = condition.getOperationParameter( INFOLAYERS );
177
178 // version is valid because no restrictions are made
179 if ( op.isAny() )
180 return;
181
182 List<String> validLayers = op.getValues();
183 if ( op.isUserCoupled() ) {
184 userCoupled = true;
185 } else {
186 for ( int i = 0; i < layers.length; i++ ) {
187 if ( !validLayers.contains( layers[i] ) ) {
188 throw new InvalidParameterValueException( INVALIDLAYER + layers[i] );
189 }
190 }
191 }
192 }
193
194 /**
195 * checks if the passed format is valid against the format defined in the policy. If <tt>user</ff> != <tt>null</tt>
196 * format will be compared against the user/rights repository
197 *
198 * @param condition
199 * condition containing the definition of the valid format
200 * @param format
201 * @throws InvalidParameterValueException
202 */
203 private void validateInfoFormat( Condition condition, String format )
204 throws InvalidParameterValueException {
205
206 OperationParameter op = condition.getOperationParameter( INFOFORMAT );
207
208 // version is valid because no restrictions are made
209 if ( op.isAny() ) {
210 return;
211 }
212
213 List<String> list = op.getValues();
214 if ( op.isUserCoupled() ) {
215 userCoupled = true;
216 } else {
217 if ( !list.contains( format ) ) {
218 throw new InvalidParameterValueException( INVALIDFORMAT + format );
219 }
220 }
221
222 }
223
224 /**
225 * checks if the passed featureCount is valid against the featureCount defined in the policy and if it is greater
226 * zero. If <tt>user</ff> != <tt>null</tt> featureCount will be compared against the user/rights repository
227 *
228 * @param condition
229 * @param featureCount
230 * @throws InvalidParameterValueException
231 */
232 private void validateFeatureCount( Condition condition, int featureCount )
233 throws InvalidParameterValueException {
234
235 OperationParameter op = condition.getOperationParameter( FEATURECOUNT );
236
237 // version is valid because no restrictions are made
238 if ( op.isAny() )
239 return;
240
241 if ( op.isUserCoupled() ) {
242 userCoupled = true;
243 } else {
244 if ( featureCount < 1 || featureCount > op.getFirstAsInt() ) {
245 throw new InvalidParameterValueException( INAVLIDFEATURECOUNT + featureCount );
246 }
247 }
248 }
249
250 /**
251 * validates the passed WMS GetMap request against a User- and Rights-Management DB.
252 *
253 * @param wmsreq
254 * @param user
255 * @throws InvalidParameterValueException
256 */
257 private void validateAgainstRightsDB( GetFeatureInfo wmsreq, User user )
258 throws InvalidParameterValueException, UnauthorizedException {
259
260 if ( user == null ) {
261 throw new UnauthorizedException( "no access to anonymous user" );
262 }
263
264 // create feature that describes the map request
265 FeatureProperty[] fps = new FeatureProperty[6];
266 fps[0] = FeatureFactory.createFeatureProperty( new QualifiedName( "version" ), wmsreq.getVersion() );
267 Integer x = new Integer( wmsreq.getClickPoint().x );
268 fps[1] = FeatureFactory.createFeatureProperty( new QualifiedName( "x" ), x );
269 Integer y = new Integer( wmsreq.getClickPoint().y );
270 fps[2] = FeatureFactory.createFeatureProperty( new QualifiedName( "y" ), y );
271 fps[3] = FeatureFactory.createFeatureProperty( new QualifiedName( "infoformat" ), wmsreq.getInfoFormat() );
272 fps[4] = FeatureFactory.createFeatureProperty( new QualifiedName( "exceptions" ), wmsreq.getExceptions() );
273 Integer fc = new Integer( wmsreq.getFeatureCount() );
274 fps[5] = FeatureFactory.createFeatureProperty( new QualifiedName( "featurecount" ), fc );
275
276 Feature feature = FeatureFactory.createFeature( "id", gfiFT, fps );
277 String[] layer = wmsreq.getQueryLayers();
278 for ( int i = 0; i < layer.length; i++ ) {
279 if ( securityConfig.getProxiedUrl() == null ) {
280 handleUserCoupledRules( user, feature, layer[i], "Layer", GETFEATUREINFO );
281 } else {
282 handleUserCoupledRules( user, feature, "[" + securityConfig.getProxiedUrl() + "]:" + layer[i], "Layer",
283 GETFEATUREINFO );
284 }
285 }
286 }
287
288 private static FeatureType createFeatureType() {
289 PropertyType[] ftps = new PropertyType[6];
290 ftps[0] = FeatureFactory.createSimplePropertyType( new QualifiedName( "version" ), Types.INTEGER, false );
291 ftps[1] = FeatureFactory.createSimplePropertyType( new QualifiedName( "x" ), Types.INTEGER, false );
292 ftps[2] = FeatureFactory.createSimplePropertyType( new QualifiedName( "y" ), Types.INTEGER, false );
293 ftps[3] = FeatureFactory.createSimplePropertyType( new QualifiedName( "infoformat" ), Types.VARCHAR, false );
294 ftps[4] = FeatureFactory.createSimplePropertyType( new QualifiedName( "exceptions" ), Types.VARCHAR, false );
295 ftps[5] = FeatureFactory.createSimplePropertyType( new QualifiedName( "featurecount" ), Types.INTEGER, false );
296
297 return FeatureFactory.createFeatureType( "GetFeatureInfo", false, ftps );
298 }
299
300 }