001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/security/owsrequestvalidator/wms/GetMapRequestValidator.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.GETMAP;
039 import static org.deegree.security.owsrequestvalidator.Messages.getString;
040
041 import java.net.URL;
042 import java.util.ArrayList;
043 import java.util.HashMap;
044 import java.util.List;
045 import java.util.Map;
046 import java.util.regex.Matcher;
047 import java.util.regex.Pattern;
048
049 import org.deegree.datatypes.QualifiedName;
050 import org.deegree.datatypes.Types;
051 import org.deegree.framework.log.ILogger;
052 import org.deegree.framework.log.LoggerFactory;
053 import org.deegree.framework.util.ColorUtils;
054 import org.deegree.framework.util.MapUtils;
055 import org.deegree.framework.util.StringTools;
056 import org.deegree.framework.xml.XMLParsingException;
057 import org.deegree.graphics.sld.AbstractStyle;
058 import org.deegree.graphics.sld.NamedLayer;
059 import org.deegree.graphics.sld.NamedStyle;
060 import org.deegree.graphics.sld.SLDFactory;
061 import org.deegree.graphics.sld.StyledLayerDescriptor;
062 import org.deegree.model.crs.CRSFactory;
063 import org.deegree.model.crs.CoordinateSystem;
064 import org.deegree.model.crs.GeoTransformer;
065 import org.deegree.model.feature.Feature;
066 import org.deegree.model.feature.FeatureFactory;
067 import org.deegree.model.feature.FeatureProperty;
068 import org.deegree.model.feature.schema.FeatureType;
069 import org.deegree.model.feature.schema.PropertyType;
070 import org.deegree.model.spatialschema.Envelope;
071 import org.deegree.model.spatialschema.GeometryFactory;
072 import org.deegree.ogcwebservices.InvalidParameterValueException;
073 import org.deegree.ogcwebservices.OGCWebServiceRequest;
074 import org.deegree.ogcwebservices.wms.operation.GetMap;
075 import org.deegree.security.UnauthorizedException;
076 import org.deegree.security.drm.SecurityAccess;
077 import org.deegree.security.drm.SecurityAccessManager;
078 import org.deegree.security.drm.model.Role;
079 import org.deegree.security.drm.model.Service;
080 import org.deegree.security.drm.model.User;
081 import org.deegree.security.owsproxy.Condition;
082 import org.deegree.security.owsproxy.OperationParameter;
083 import org.deegree.security.owsproxy.Request;
084 import org.deegree.security.owsrequestvalidator.Messages;
085 import org.deegree.security.owsrequestvalidator.Policy;
086
087 /**
088 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
089 * @author last edited by: $Author: aschmitz $
090 *
091 * @version 1.1, $Revision: 32121 $, $Date: 2011-10-10 16:51:09 +0200 (Mo, 10 Okt 2011) $
092 *
093 * @since 1.1
094 */
095
096 public class GetMapRequestValidator extends AbstractWMSRequestValidator {
097
098 private static final ILogger LOG = LoggerFactory.getLogger( GetMapRequestValidator.class );
099
100 // known condition parameter
101 private static final String BBOX = "bbox";
102
103 private static final String LAYERS = "layers";
104
105 private static final String BGCOLOR = "bgcolor";
106
107 private static final String TRANSPARENCY = "transparency";
108
109 private static final String RESOLUTION = "resolution";
110
111 private static final String SLD = "sld";
112
113 private static final String INVALIDBBOX = Messages.getString( "GetMapRequestValidator.INVALIDBBOX" );
114
115 private static final String INVALIDLAYER = Messages.getString( "GetMapRequestValidator.INVALIDLAYER" );
116
117 private static final String INVALIDSTYLE = Messages.getString( "GetMapRequestValidator.INVALIDSTYLE" );
118
119 private static final String INVALIDBGCOLOR = Messages.getString( "GetMapRequestValidator.INVALIDBGCOLOR" );
120
121 private static final String INVALIDTRANSPARENCY = Messages.getString( "GetMapRequestValidator.INVALIDTRANSPARENCY" );
122
123 private static final String INVALIDRESOLUTION = Messages.getString( "GetMapRequestValidator.INVALIDRESOLUTION" );
124
125 private static final String INVALIDSLD = Messages.getString( "GetMapRequestValidator.INVALIDSLD" );
126
127 private static final String MISSINGCRS = Messages.getString( "GetMapRequestValidator.MISSINGCRS" );
128
129 private List<String> accessdRes = new ArrayList<String>();
130
131 private static FeatureType mapFT = null;
132
133 private GeoTransformer gt = null;
134
135 static {
136 if ( mapFT == null ) {
137 mapFT = GetMapRequestValidator.createFeatureType();
138 }
139 }
140
141 /**
142 * @param policy
143 */
144 public GetMapRequestValidator( Policy policy ) {
145 super( policy );
146 try {
147 gt = new GeoTransformer( "EPSG:4326" );
148 } catch ( Exception e ) {
149 e.printStackTrace();
150 }
151 }
152
153 /**
154 * validates the incoming GetMap request against the policy assigned to a validator
155 *
156 * @param request
157 * request to validate
158 * @param user
159 * name of the user who likes to perform the request (can be null)
160 */
161 @Override
162 public void validateRequest( OGCWebServiceRequest request, User user )
163 throws InvalidParameterValueException, UnauthorizedException {
164
165 accessdRes.clear();
166 userCoupled = false;
167 Request req = policy.getRequest( "WMS", "GetMap" );
168 // request is valid because no restrictions are made
169 if ( req.isAny() || req.getPreConditions().isAny() ) {
170 return;
171 }
172 Condition condition = req.getPreConditions();
173
174 GetMap wmsreq = (GetMap) request;
175
176 validateVersion( condition, wmsreq.getVersion() );
177 Envelope env = wmsreq.getBoundingBox();
178 try {
179 env = gt.transform( env, wmsreq.getSrs() );
180 } catch ( Exception e ) {
181 throw new InvalidParameterValueException( "condition envelope isn't in the right CRS ", e );
182 }
183 validateBBOX( condition, env );
184 validateLayers( condition, wmsreq.getLayers() );
185 validateBGColor( condition, ColorUtils.toHexCode( "0x", wmsreq.getBGColor() ) );
186 validateTransparency( condition, wmsreq.getTransparency() );
187 validateExceptions( condition, wmsreq.getExceptions() );
188 validateFormat( condition, wmsreq.getFormat() );
189 validateMaxWidth( condition, wmsreq.getWidth() );
190 validateMaxHeight( condition, wmsreq.getHeight() );
191 validateResolution( condition, wmsreq );
192 validateSLD( condition, wmsreq.getSLD_URL() );
193 validateSLD_Body( condition, wmsreq.getStyledLayerDescriptor() );
194
195 if ( userCoupled ) {
196 validateAgainstRightsDB( wmsreq, user );
197 }
198
199 }
200
201 /**
202 * checks if the passed envelope is valid against the maximum bounding box defined in the policy. If
203 * <tt>user</ff> != <tt>null</tt> the maximu valid BBOX will be read from the user/rights repository
204 *
205 * @param condition
206 * condition containing the definition of the valid BBOX
207 * @param envelope
208 * @throws InvalidParameterValueException
209 */
210 private void validateBBOX( Condition condition, Envelope envelope )
211 throws InvalidParameterValueException {
212
213 OperationParameter op = condition.getOperationParameter( BBOX );
214
215 // version is valid because no restrictions are made
216 if ( op.isAny() )
217 return;
218
219 String v = op.getFirstAsString();
220 String[] d = StringTools.toArray( v, ",", false );
221 Envelope env = GeometryFactory.createEnvelope( Double.parseDouble( d[0] ), Double.parseDouble( d[1] ),
222 Double.parseDouble( d[2] ), Double.parseDouble( d[3] ), null );
223
224 try {
225 env = gt.transform( env, d[4] );
226 } catch ( Exception e ) {
227 throw new InvalidParameterValueException( MISSINGCRS, e );
228 }
229
230 if ( !env.contains( envelope ) ) {
231 if ( !op.isUserCoupled() ) {
232 // if not user coupled the validation has failed
233 throw new InvalidParameterValueException( INVALIDBBOX + op.getFirstAsString() );
234 }
235 userCoupled = true;
236 accessdRes.add( "BBOX: " + v );
237 }
238 }
239
240 /**
241 * checks if the passed layres/styles are valid against the layers/styles list defined in the policy. If
242 * <tt>user</ff> != <tt>null</tt> the valid layers/styles will be read from the user/rights repository
243 *
244 * @param condition
245 * condition containing the definition of the valid layers/styles
246 * @param layers
247 * @throws InvalidParameterValueException
248 */
249 private void validateLayers( Condition condition, GetMap.Layer[] layers )
250 throws InvalidParameterValueException {
251
252 OperationParameter op = condition.getOperationParameter( LAYERS );
253
254 // version is valid because no restrictions are made
255 if ( op.isAny() ) {
256 return;
257 }
258
259 List<String> v = op.getValues();
260 // seperate layers from assigned styles
261 Map<String, String> map = new HashMap<String, String>();
262 for ( int i = 0; i < v.size(); i++ ) {
263 String[] tmp = StringTools.toArray( v.get( i ), "|", false );
264 map.put( tmp[0], tmp[1] );
265 }
266
267 for ( int i = 0; i < layers.length; i++ ) {
268 String style = layers[i].getStyleName();
269 String vs = map.get( layers[i].getName() );
270 if ( vs == null ) {
271 if ( !op.isUserCoupled() ) {
272 throw new InvalidParameterValueException( INVALIDLAYER + layers[i].getName() );
273 }
274 accessdRes.add( "Layers: " + layers[i].getName() );
275 userCoupled = true;
276 } else if ( !style.equalsIgnoreCase( "default" ) && vs.indexOf( "$any$" ) < 0 && vs.indexOf( style ) < 0 ) {
277 // a style is valid for a layer if it's the default style
278 // or the layer accepts any style or a style is explicit defined
279 // to be valid
280 if ( !op.isUserCoupled() ) {
281 throw new InvalidParameterValueException( INVALIDSTYLE + layers[i].getName() + ':' + style );
282 }
283 userCoupled = true;
284 accessdRes.add( "Styles: " + style );
285 }
286 }
287
288 }
289
290 /**
291 * checks if the passed bgcolor is valid against the bgcolor(s) defined in the policy. If
292 * <tt>user</ff> != <tt>null</tt> the valid bgcolors will be read from the user/rights repository
293 *
294 * @param condition
295 * condition containing the definition of the valid bgcolors
296 * @param bgcolor
297 * @throws InvalidParameterValueException
298 */
299 private void validateBGColor( Condition condition, String bgcolor )
300 throws InvalidParameterValueException {
301
302 OperationParameter op = condition.getOperationParameter( BGCOLOR );
303
304 // version is valid because no restrictions are made
305 if ( op.isAny() )
306 return;
307
308 List<String> list = op.getValues();
309
310 if ( !list.contains( bgcolor ) ) {
311 if ( !op.isUserCoupled() ) {
312 throw new InvalidParameterValueException( INVALIDBGCOLOR + bgcolor );
313 }
314 accessdRes.add( "BGCOLOR" + bgcolor );
315 userCoupled = true;
316 }
317
318 }
319
320 /**
321 * checks if the passed transparency is valid against the transparency defined in the policy. If
322 * <tt>user</ff> != <tt>null</tt> the valid transparency will be read from the user/rights repository
323 *
324 * @param condition
325 * condition containing the definition of the valid transparency
326 * @param transparency
327 * @throws InvalidParameterValueException
328 */
329 private void validateTransparency( Condition condition, boolean transparency )
330 throws InvalidParameterValueException {
331
332 OperationParameter op = condition.getOperationParameter( TRANSPARENCY );
333
334 // version is valid because no restrictions are made
335 if ( op.isAny() )
336 return;
337
338 List<String> v = op.getValues();
339 String s = "" + transparency;
340 if ( !v.get( 0 ).equals( s ) && !v.get( v.size() - 1 ).equals( s ) ) {
341 if ( !op.isUserCoupled() ) {
342 throw new InvalidParameterValueException( INVALIDTRANSPARENCY + transparency );
343 }
344 userCoupled = true;
345 accessdRes.add( "Transparency: " + transparency );
346 }
347
348 }
349
350 /**
351 * checks if the requested map area/size is valid against the minimum resolution defined in the policy. If
352 * <tt>user</ff> != <tt>null</tt> the valid resolution will be read from the user/rights repository
353 *
354 * @param condition
355 * condition containing the definition of the valid resolution
356 * @throws InvalidParameterValueException
357 */
358 private void validateResolution( Condition condition, GetMap gmr )
359 throws InvalidParameterValueException {
360
361 OperationParameter op = condition.getOperationParameter( RESOLUTION );
362
363 // version is valid because no restrictions are made
364 if ( op.isAny() )
365 return;
366
367 double scale = 0;
368 try {
369 scale = calcScale( gmr );
370 } catch ( Exception e ) {
371 throw new InvalidParameterValueException( StringTools.stackTraceToString( e ) );
372 }
373 double compareRes = 0;
374 compareRes = op.getFirstAsDouble();
375 if ( scale < compareRes ) {
376 if ( !op.isUserCoupled() ) {
377 throw new InvalidParameterValueException( INVALIDRESOLUTION + scale );
378 }
379 userCoupled = true;
380 accessdRes.add( "resolution: " + scale );
381 }
382 }
383
384 /**
385 * checks if the passed reference to a SLD document is valid against the defined in the policy. If
386 * <tt>user</ff> != <tt>null</tt> the valid sld reference addresses will be read from the user/rights repository
387 *
388 * @param condition
389 * condition containing the definition of the valid sldRef
390 * @param sldRef
391 * @throws InvalidParameterValueException
392 */
393 private void validateSLD( Condition condition, URL sldRef )
394 throws InvalidParameterValueException {
395
396 OperationParameter op = condition.getOperationParameter( SLD );
397 OperationParameter gmop = condition.getOperationParameter( LAYERS );
398
399 if ( op == null && sldRef != null ) {
400 throw new InvalidParameterValueException( INVALIDSLD + sldRef );
401 }
402 // sldRef is valid because no restrictions are made
403 if ( sldRef == null || op.isAny() ) {
404 return;
405 }
406
407 // validate reference base of the SLD
408 List<String> list = op.getValues();
409 String port = null;
410 if ( sldRef.getPort() != -1 ) {
411 port = ":" + sldRef.getPort();
412 } else {
413 port = ":80";
414 }
415 String addr = sldRef.getProtocol() + "://" + sldRef.getHost() + port;
416 if ( !list.contains( addr ) ) {
417 if ( !op.isUserCoupled() ) {
418 throw new InvalidParameterValueException( INVALIDSLD + sldRef );
419 }
420 userCoupled = true;
421 }
422
423 // validate referenced dacument to be a valid SLD
424 StyledLayerDescriptor sld = null;
425 try {
426 sld = SLDFactory.createSLD( sldRef );
427 } catch ( XMLParsingException e ) {
428 String s = org.deegree.i18n.Messages.getMessage( "WMS_SLD_IS_NOT_VALID", sldRef );
429 throw new InvalidParameterValueException( s );
430 }
431
432 // validate NamedLayers referenced by the SLD
433 NamedLayer[] nl = sld.getNamedLayers();
434 List<String> v = gmop.getValues();
435 // seperate layers from assigned styles
436 Map<String, String> map = new HashMap<String, String>();
437 for ( int i = 0; i < v.size(); i++ ) {
438 String[] tmp = StringTools.toArray( v.get( i ), "|", false );
439 map.put( tmp[0], tmp[1] );
440 }
441 if ( !userCoupled ) {
442 for ( int i = 0; i < nl.length; i++ ) {
443 AbstractStyle st = nl[i].getStyles()[0];
444 String style = null;
445 if ( st instanceof NamedStyle ) {
446 style = ( (NamedStyle) st ).getName();
447 } else {
448 // use default as name if a UserStyle is defined
449 // to ensure that the style will be accepted by
450 // the validator
451 style = "default";
452 }
453 String vs = map.get( nl[i].getName() );
454 if ( vs == null ) {
455 if ( !op.isUserCoupled() ) {
456 throw new InvalidParameterValueException( INVALIDLAYER + nl[i].getName() );
457 }
458 accessdRes.add( "Layers: " + nl[i].getName() );
459 userCoupled = true;
460 } else if ( !style.equalsIgnoreCase( "default" ) && vs.indexOf( "$any$" ) < 0
461 && vs.indexOf( style ) < 0 ) {
462 // a style is valid for a layer if it's the default style
463 // or the layer accepts any style or a style is explicit defined
464 // to be valid
465 if ( !op.isUserCoupled() ) {
466 throw new InvalidParameterValueException( INVALIDSTYLE + nl[i].getName() + ':' + style );
467 }
468 userCoupled = true;
469 accessdRes.add( "Styles: " + style );
470 }
471 }
472 }
473
474 }
475
476 /**
477 * checks if the passed user is allowed to perform a GetMap request containing a SLD_BODY parameter.
478 *
479 * @param condition
480 * condition containing when SLD_BODY is valid or nots
481 * @param sld_body
482 */
483 private void validateSLD_Body( Condition condition, StyledLayerDescriptor sld_body ) {
484
485 /*
486 *
487 * OperationParameter op = condition.getOperationParameter( SLD_BODY ); // version is valid because no
488 * restrictions are made if ( sld_body == null ||op.isAny() ) return; // at the moment it is just evaluated if
489 * the user is allowed // to perform a SLD request or not. no content validation will // be made boolean
490 * isAllowed = false; if ( op.isUserCoupled() ) { //TODO // get comparator list from security registry } if
491 * (!isAllowed ) { throw new InvalidParameterValueException( INVALIDSLD_BODY ); }
492 */
493 }
494
495 /**
496 * validates the passed WMS GetMap request against a User- and Rights-Management DB.
497 *
498 * @param wmsreq
499 * @param user
500 * @throws InvalidParameterValueException
501 */
502 private void validateAgainstRightsDB( GetMap wmsreq, User user )
503 throws InvalidParameterValueException, UnauthorizedException {
504
505 if ( user == null ) {
506 StringBuffer sb = new StringBuffer( 1000 );
507 sb.append( ' ' );
508 for ( int i = 0; i < accessdRes.size(); i++ ) {
509 sb.append( accessdRes.get( i ) ).append( "; " );
510 }
511 throw new UnauthorizedException( Messages.format( "RequestValidator.NOACCESS", sb ) );
512 }
513
514 Double scale = null;
515 try {
516 scale = new Double( calcScale( wmsreq ) );
517 } catch ( Exception e ) {
518 throw new InvalidParameterValueException( e );
519 }
520
521 // create feature that describes the map request
522 FeatureProperty[] fps = new FeatureProperty[11];
523 fps[0] = FeatureFactory.createFeatureProperty( new QualifiedName( "version" ), wmsreq.getVersion() );
524 fps[1] = FeatureFactory.createFeatureProperty( new QualifiedName( "width" ), new Integer( wmsreq.getWidth() ) );
525 fps[2] = FeatureFactory.createFeatureProperty( new QualifiedName( "height" ), new Integer( wmsreq.getHeight() ) );
526 Envelope env = wmsreq.getBoundingBox();
527 try {
528 env = gt.transform( env, wmsreq.getSrs() );
529 } catch ( Exception e ) {
530 throw new InvalidParameterValueException( "A:condition envelope isn't in the right CRS ", e );
531 }
532 Object geom = null;
533 try {
534 geom = GeometryFactory.createSurface( env, null );
535 } catch ( Exception e1 ) {
536 e1.printStackTrace();
537 }
538 fps[3] = FeatureFactory.createFeatureProperty( new QualifiedName( "GEOM" ), geom );
539 fps[4] = FeatureFactory.createFeatureProperty( new QualifiedName( "format" ), wmsreq.getFormat() );
540 fps[5] = FeatureFactory.createFeatureProperty( new QualifiedName( "bgcolor" ),
541 ColorUtils.toHexCode( "0x", wmsreq.getBGColor() ) );
542 fps[6] = FeatureFactory.createFeatureProperty( new QualifiedName( "transparent" ),
543 "" + wmsreq.getTransparency() );
544 fps[7] = FeatureFactory.createFeatureProperty( new QualifiedName( "exceptions" ), wmsreq.getExceptions() );
545 fps[8] = FeatureFactory.createFeatureProperty( new QualifiedName( "resolution" ), scale );
546 fps[9] = FeatureFactory.createFeatureProperty( new QualifiedName( "sld" ), wmsreq.getSLD_URL() );
547
548 GetMap.Layer[] layers = wmsreq.getLayers();
549 for ( int i = 0; i < layers.length; i++ ) {
550 fps[10] = FeatureFactory.createFeatureProperty( new QualifiedName( "style" ), layers[i].getStyleName() );
551 Feature feature = FeatureFactory.createFeature( "id", mapFT, fps );
552
553 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
554 for ( int ii = 0; ii < fps.length; ii++ ) {
555 LOG.logDebug( "compared property: ", fps[ii] );
556 }
557 }
558
559 if ( securityConfig.getProxiedUrl() == null ) {
560 handleUserCoupledRules( user, feature, layers[i].getName(), "Layer", GETMAP );
561 } else {
562 handleUserCoupledRules( user, feature,
563 "[" + securityConfig.getProxiedUrl() + "]:" + layers[i].getName(), "Layer",
564 GETMAP );
565 // handle custom constraints (currently only maxwidth/height)
566 try {
567 SecurityAccessManager sam = SecurityAccessManager.getInstance();
568 SecurityAccess access = sam.acquireAccess( user );
569 Service service = access.getServiceByAddress( securityConfig.getProxiedUrl() );
570 boolean authorized = false;
571 for ( Role r : user.getRoles( access ) ) {
572 String constr = access.getConstraints( r, service );
573 if ( constr == null ) {
574 authorized = true;
575 break;
576 }
577 Pattern p = Pattern.compile( "maxWidth: ([0-9]+), maxHeight: ([0-9]+)" );
578 Matcher m = p.matcher( constr );
579 if ( m.find() ) {
580 int width = Integer.valueOf( m.group( 1 ) );
581 int height = Integer.valueOf( m.group( 2 ) );
582 if ( width == 0 && height == 0 ) {
583 authorized = true;
584 break;
585 }
586 if ( width >= wmsreq.getWidth() && height >= wmsreq.getHeight() ) {
587 authorized = true;
588 break;
589 }
590 }
591 }
592 if ( !authorized ) {
593 throw new UnauthorizedException( getString( "RequestValidator.UNAUTORIZEDACCESS" ) );
594 }
595 } catch ( UnauthorizedException e ) {
596 throw e;
597 } catch ( Throwable e ) {
598 throw new UnauthorizedException( e );
599 }
600 }
601 }
602
603 }
604
605 /**
606 * calculates the map scale as defined in the OGC WMS 1.1.1 specifications
607 *
608 * @return scale of the map
609 */
610 private double calcScale( GetMap request )
611 throws Exception {
612
613 Envelope bbox = request.getBoundingBox();
614
615 CoordinateSystem crs = CRSFactory.create( request.getSrs() );
616 return MapUtils.calcScale( request.getWidth(), request.getHeight(), bbox, crs, 1 );
617 // would return scale denominator
618 // return MapUtils.calcScale( request.getWidth(), request.getHeight(), bbox, crs, DEFAULT_PIXEL_SIZE );
619 }
620
621 private static FeatureType createFeatureType() {
622 PropertyType[] ftps = new PropertyType[11];
623 ftps[0] = FeatureFactory.createSimplePropertyType( new QualifiedName( "version" ), Types.VARCHAR, false );
624 ftps[1] = FeatureFactory.createSimplePropertyType( new QualifiedName( "width" ), Types.INTEGER, false );
625 ftps[2] = FeatureFactory.createSimplePropertyType( new QualifiedName( "height" ), Types.INTEGER, false );
626 ftps[3] = FeatureFactory.createSimplePropertyType( new QualifiedName( "GEOM" ), Types.GEOMETRY, false );
627 ftps[4] = FeatureFactory.createSimplePropertyType( new QualifiedName( "format" ), Types.VARCHAR, false );
628 ftps[5] = FeatureFactory.createSimplePropertyType( new QualifiedName( "bgcolor" ), Types.VARCHAR, false );
629 ftps[6] = FeatureFactory.createSimplePropertyType( new QualifiedName( "transparent" ), Types.VARCHAR, false );
630 ftps[7] = FeatureFactory.createSimplePropertyType( new QualifiedName( "exceptions" ), Types.VARCHAR, false );
631 ftps[8] = FeatureFactory.createSimplePropertyType( new QualifiedName( "resolution" ), Types.DOUBLE, false );
632 ftps[9] = FeatureFactory.createSimplePropertyType( new QualifiedName( "sld" ), Types.VARCHAR, false );
633 ftps[10] = FeatureFactory.createSimplePropertyType( new QualifiedName( "style" ), Types.VARCHAR, false );
634
635 return FeatureFactory.createFeatureType( "GetMap", false, ftps );
636 }
637
638 }