001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/security/owsrequestvalidator/GetCapabilitiesResponseValidator.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; 037 038 import static org.deegree.framework.util.CharsetUtils.getSystemCharset; 039 import static org.deegree.security.drm.model.RightType.GETFEATURE; 040 import static org.deegree.security.drm.model.RightType.GETMAP; 041 042 import java.io.ByteArrayInputStream; 043 import java.io.ByteArrayOutputStream; 044 import java.io.IOException; 045 import java.io.InputStreamReader; 046 import java.io.PrintWriter; 047 import java.io.StringReader; 048 import java.net.MalformedURLException; 049 import java.net.URL; 050 import java.util.List; 051 import java.util.Properties; 052 053 import javax.xml.transform.OutputKeys; 054 055 import org.deegree.framework.log.ILogger; 056 import org.deegree.framework.log.LoggerFactory; 057 import org.deegree.framework.util.MimeTypeMapper; 058 import org.deegree.framework.util.StringTools; 059 import org.deegree.framework.xml.XMLFragment; 060 import org.deegree.framework.xml.XMLParsingException; 061 import org.deegree.model.metadata.iso19115.Linkage; 062 import org.deegree.model.metadata.iso19115.OnlineResource; 063 import org.deegree.ogcwebservices.InvalidParameterValueException; 064 import org.deegree.ogcwebservices.OGCWebServiceRequest; 065 import org.deegree.ogcwebservices.csw.capabilities.CatalogueCapabilities; 066 import org.deegree.ogcwebservices.csw.capabilities.CatalogueCapabilitiesDocument; 067 import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException; 068 import org.deegree.ogcwebservices.wfs.capabilities.FeatureTypeList; 069 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 070 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument; 071 import org.deegree.ogcwebservices.wfs.capabilities.WFSFeatureType; 072 import org.deegree.ogcwebservices.wms.XMLFactory; 073 import org.deegree.ogcwebservices.wms.capabilities.Layer; 074 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities; 075 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument; 076 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory; 077 import org.deegree.owscommon_new.DCP; 078 import org.deegree.owscommon_new.HTTP; 079 import org.deegree.owscommon_new.Operation; 080 import org.deegree.security.GeneralSecurityException; 081 import org.deegree.security.UnauthorizedException; 082 import org.deegree.security.drm.SecurityAccess; 083 import org.deegree.security.drm.SecurityAccessManager; 084 import org.deegree.security.drm.model.SecuredObject; 085 import org.deegree.security.drm.model.User; 086 import org.deegree.security.owsproxy.Condition; 087 import org.deegree.security.owsproxy.OperationParameter; 088 import org.deegree.security.owsproxy.Request; 089 import org.deegree.security.owsrequestvalidator.wms.GetMapRequestValidator; 090 import org.w3c.dom.Document; 091 092 /** 093 * 094 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 095 * @author last edited by: $Author: mschneider $ 096 * 097 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 098 */ 099 public class GetCapabilitiesResponseValidator extends ResponseValidator { 100 101 private static final ILogger LOG = LoggerFactory.getLogger( GetCapabilitiesResponseValidator.class ); 102 103 private static final String INVALIDSERVICE = Messages.getString( "GetCapabilitiesResponseValidator.INVALIDSERVICE" ); 104 105 private String proxyURL = null; 106 107 /** 108 * @param policy 109 * @param proxyURL 110 */ 111 public GetCapabilitiesResponseValidator( Policy policy, String proxyURL ) { 112 super( policy ); 113 this.proxyURL = proxyURL; 114 } 115 116 /** 117 * validates the passed object as a response to a OWS request. The validity of the response may is assigned to 118 * specific user rights. If the passed user is <>null this will be evaluated. <br> 119 * the reponse may contain three valid kinds of objects: 120 * <ul> 121 * <li>a serialized image 122 * <li>a xml encoded exception 123 * <li>a svg-encoded vector image 124 * </ul> 125 * Each of these types can be identified by the mime-type of the response that is also passed to the method. <br> 126 * If something basic went wrong it is possible that not further specified kind of object is passed as response. In 127 * this case the method will throw an <tt>InvalidParameterValueException</tt> to avoid sending bad responses to the 128 * client. 129 * 130 * @param service 131 * service which produced the response (WMS, WFS ...) 132 * @param response 133 * @param mime 134 * mime-type of the response 135 * @param user 136 * @return the new response array 137 * @throws InvalidParameterValueException 138 * @throws UnauthorizedException 139 * @see GetMapRequestValidator#validateRequest(OGCWebServiceRequest, User) 140 */ 141 @Override 142 public byte[] validateResponse( String service, byte[] response, String mime, User user ) 143 throws InvalidParameterValueException, UnauthorizedException { 144 145 Request req = policy.getRequest( service, "GetCapabilities" ); 146 if ( req == null ) { 147 throw new InvalidParameterValueException( INVALIDSERVICE + service ); 148 } 149 // request is valid because no restrictions are made 150 if ( req.isAny() || req.getPostConditions().isAny() ) { 151 return response; 152 } 153 154 if ( MimeTypeMapper.isKnownOGCType( mime ) ) { 155 // if the mime-type is a known OGC mime-type it must be an XML 156 // document. probably it is a capabilities document but it also 157 // could be an 158 response = validateXML( service, response, user ); 159 } else if ( mime.equals( "text/xml" ) ) { 160 // if the mime-type isn't an image type but 'text/xml' 161 // it could be an exception 162 response = validateXML( service, response, user ); 163 } else { 164 throw new InvalidParameterValueException( UNKNOWNMIMETYPE + mime ); 165 } 166 167 return response; 168 } 169 170 /** 171 * splits document string into 'core' capabilities document and xml header 172 * 173 * @param xml 174 * @return the splitted document 175 * @throws InvalidParameterValueException 176 */ 177 private String[] clearCapabilities( byte[] xml ) 178 throws InvalidParameterValueException { 179 InputStreamReader isr = new InputStreamReader( new ByteArrayInputStream( xml ) ); 180 StringBuffer sb = new StringBuffer( 50000 ); 181 int c = 0; 182 try { 183 while ( ( c = isr.read() ) > -1 ) { 184 sb.append( (char) c ); 185 } 186 isr.close(); 187 } catch ( IOException e ) { 188 String s = Messages.format( "GetCapabilitiesResponseValidator.CAPAREAD", e.getMessage() ); 189 throw new InvalidParameterValueException( s ); 190 } 191 // WMS <= 1.1.1 192 int pos = sb.indexOf( "<WMT_MS_Capabilities" ); 193 // WMS 1.3 194 if ( pos < 0 ) { 195 pos = sb.indexOf( "WMS_Capabilities" ); 196 } 197 // WFS 1.1.0 198 if ( pos < 0 ) { 199 pos = sb.indexOf( "WFS_Capabilities" ); 200 } 201 // CSW 2.0.0 202 if ( pos < 0 ) { 203 pos = sb.indexOf( "Capabilities" ); 204 } 205 // WCS 1.0.0 206 if ( pos < 0 ) { 207 pos = sb.indexOf( "WCS_Capabilities" ); 208 } 209 210 // just if pos is > -1 it makes sense to find the starting 211 // index of the root element 212 if ( pos > -1 ) { 213 pos = pos + 4; 214 char ch = '$'; 215 // find starting index of the root element 216 while ( ch != '<' && pos > 0 ) { 217 pos--; 218 ch = sb.charAt( pos ); 219 } 220 // if the least char read does not equal '<' the parsed document 221 // is not an XML document 222 if ( ch != '<' ) { 223 pos = -1; 224 } 225 } 226 String[] o = new String[2]; 227 if ( pos > 0 ) { 228 // XML header / doctype 229 o[0] = sb.substring( 0, pos ); 230 } else { 231 o[0] = ""; 232 } 233 if ( pos > -1 ) { 234 // xml document starting at the root element 235 o[1] = sb.substring( pos ); 236 } else { 237 // no XML document 238 o[0] = "ERROR"; 239 o[1] = sb.toString(); 240 } 241 242 return o; 243 } 244 245 /** 246 * validates the passed xml to be valid against the policy 247 * 248 * @param service 249 * service which produced the response (WMS, WFS ...) 250 * @param xml 251 * @param user 252 * @throws InvalidParameterValueException 253 */ 254 private byte[] validateXML( String service, byte[] xml, User user ) 255 throws InvalidParameterValueException, UnauthorizedException { 256 257 String[] st = clearCapabilities( xml ); 258 if ( st[0].equals( "ERROR" ) ) { 259 LOG.logError( st[1] ); 260 String s = Messages.format( "GetCapabilitiesResponseValidator.NOCAPADOC", st[1] ); 261 throw new InvalidParameterValueException( s ); 262 } 263 Document doc = null; 264 try { 265 XMLFragment frag = new XMLFragment(); 266 frag.load( new StringReader( st[1] ), XMLFragment.DEFAULT_URL ); 267 doc = frag.getRootElement().getOwnerDocument(); 268 } catch ( Exception e ) { 269 LOG.logError( e.getMessage(), e ); 270 String s = Messages.getString( "GetCapabilitiesResponseValidator.ALLCAPAPARSE" ); 271 throw new InvalidParameterValueException( s ); 272 } 273 String root = doc.getDocumentElement().getNodeName(); 274 if ( root.equalsIgnoreCase( "Exception" ) ) { 275 // if the xml contains a exception the reponse is valid! 276 } else if ( "WMS".equals( service ) ) { 277 try { 278 xml = validateWMSCapabilities( doc, user ); 279 } catch ( XMLParsingException e ) { 280 LOG.logError( e.getMessage(), e ); 281 throw new InvalidParameterValueException( "invalid WMS capabilities" ); 282 } 283 } else if ( "WFS".equals( service ) ) { 284 xml = validateWFSCapabilities( doc, user ); 285 } else if ( "WCS".equals( service ) ) { 286 xml = validateWCSCapabilities( doc, user ); 287 } else if ( "CSW".equals( service ) ) { 288 xml = validateCSWCapabilities( doc ); 289 } 290 291 StringBuffer sb = new StringBuffer( xml.length + st[0].length() ); 292 sb.append( st[0] ); 293 String s = new String( xml ); 294 int p = s.indexOf( "?>" ); 295 if ( p > -1 ) { 296 sb.append( s.substring( p + 2, s.length() ) ); 297 } else { 298 sb.append( s ); 299 } 300 s = sb.toString(); 301 if ( s.indexOf( "<?xml version" ) > 1 ) { 302 s = StringTools.replace( s, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>", "", false ); 303 s = StringTools.replace( s, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "", false ); 304 } 305 306 // TODO 307 // regular expression 308 // s = sb.toString().replaceAll( "<?...?>", "" ); 309 310 return s.getBytes(); 311 } 312 313 /** 314 * 315 * @param doc 316 * @param user 317 * @return nothing, an exception is thrown 318 */ 319 private byte[] validateWCSCapabilities( Document doc, User user ) { 320 // TODO 321 // implement support for WCS 322 throw new UnsupportedOperationException(); 323 } 324 325 /** 326 * validates the passed xml to be valid against the policy 327 * 328 * @param user 329 * @throws InvalidParameterValueException 330 * @throws XMLParsingException 331 */ 332 private byte[] validateWMSCapabilities( Document doc, User user ) 333 throws InvalidParameterValueException, UnauthorizedException, XMLParsingException { 334 335 WMSCapabilitiesDocument cdoc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getDocumentElement() ); 336 WMSCapabilities capa = null; 337 try { 338 capa = (WMSCapabilities) cdoc.parseCapabilities(); 339 } catch ( InvalidCapabilitiesException e ) { 340 LOG.logError( e.getMessage(), e ); 341 String s = Messages.format( "GetCapabilitiesResponseValidator.WMSCAPAPARSE", e.getMessage() ); 342 throw new InvalidParameterValueException( s ); 343 } 344 capa = filterWMSLayers( capa, user ); 345 346 List<Operation> ops = capa.getOperationMetadata().getOperations(); 347 for ( Operation operation : ops ) { 348 setNewOnlineResource( operation ); 349 } 350 351 ByteArrayOutputStream bos = new ByteArrayOutputStream( 50000 ); 352 byte[] b; 353 try { 354 cdoc = XMLFactory.export( capa ); 355 Properties properties = new Properties(); 356 // setting this to system charset is no problem, as later on it will be converted to a different encoding 357 // again anyway 358 // not using byte arrays might solve the problems here... 359 properties.setProperty( OutputKeys.ENCODING, getSystemCharset() ); 360 cdoc.write( bos, properties ); 361 b = bos.toByteArray(); 362 bos.close(); 363 } catch ( Exception e ) { 364 LOG.logError( e.getMessage(), e ); 365 String s = Messages.format( "GetCapabilitiesResponseValidator.WMSCAPAEXPORT", e.getMessage() ); 366 throw new InvalidParameterValueException( s ); 367 } 368 369 return b; 370 371 } 372 373 /** 374 * 375 * @param op 376 */ 377 private void setNewOnlineResource( Operation op ) { 378 if ( op.getDCP() != null ) { 379 List<DCP> dcps = op.getDCP(); 380 for ( DCP dcp : dcps ) { 381 HTTP http = (HTTP) dcp; 382 List<OnlineResource> links = http.getLinks(); 383 try { 384 int size = links.size(); 385 links.clear(); 386 OnlineResource proxy = new OnlineResource( new Linkage( new URL( proxyURL ) ) ); 387 for ( int i = 0; i < size; ++i ) 388 links.add( proxy ); 389 } catch ( MalformedURLException e1 ) { 390 LOG.logError( e1.getLocalizedMessage(), e1 ); 391 } 392 } 393 } 394 } 395 396 /** 397 * Sets the proxy online resource in the old owscommon Operation class. To be removed soon! 398 * 399 * @param op 400 */ 401 private void setNewOnlineResourceInOldOperation( org.deegree.ogcwebservices.getcapabilities.Operation op ) { 402 if ( op.getDCPs() != null ) { 403 for ( int i = 0; i < op.getDCPs().length; i++ ) { 404 org.deegree.ogcwebservices.getcapabilities.HTTP http = (org.deegree.ogcwebservices.getcapabilities.HTTP) op.getDCPs()[i].getProtocol(); 405 try { 406 if ( http.getGetOnlineResources().length > 0 ) { 407 URL urls[] = new URL[http.getGetOnlineResources().length]; 408 for ( int k = 0; k < http.getGetOnlineResources().length; ++k ) 409 urls[k] = new URL( proxyURL ); 410 http.setGetOnlineResources( urls ); 411 } 412 if ( http.getPostOnlineResources().length > 0 ) { 413 URL urls[] = new URL[http.getPostOnlineResources().length]; 414 for ( int k = 0; k < http.getPostOnlineResources().length; ++k ) 415 urls[k] = new URL( proxyURL ); 416 http.setPostOnlineResources( urls ); 417 } 418 } catch ( MalformedURLException e1 ) { 419 e1.printStackTrace(); 420 } 421 } 422 } 423 } 424 425 /** 426 * validates the passed xml to be valid against the policy 427 * 428 * @param user 429 * @throws InvalidParameterValueException 430 * @throws UnauthorizedException 431 */ 432 private byte[] validateWFSCapabilities( Document doc, User user ) 433 throws InvalidParameterValueException, UnauthorizedException { 434 435 WFSCapabilities capa = null; 436 try { 437 WFSCapabilitiesDocument capaDoc = new WFSCapabilitiesDocument(); 438 capaDoc.setRootElement( doc.getDocumentElement() ); 439 capa = (WFSCapabilities) capaDoc.parseCapabilities(); 440 } catch ( Exception e ) { 441 LOG.logError( e.getMessage(), e ); 442 String s = Messages.format( "GetCapabilitiesResponseValidator.INVALIDWFSCAPA", e.getMessage() ); 443 throw new InvalidParameterValueException( s ); 444 } 445 446 capa = filterWFSFeatureType( capa, user ); 447 448 org.deegree.ogcwebservices.getcapabilities.Operation[] ops = capa.getOperationsMetadata().getOperations(); 449 for ( int i = 0; i < ops.length; i++ ) { 450 setNewOnlineResourceInOldOperation( ops[i] ); 451 } 452 453 WFSCapabilitiesDocument capaDoc = null; 454 try { 455 capaDoc = org.deegree.ogcwebservices.wfs.XMLFactory.export( capa ); 456 } catch ( Exception e ) { 457 throw new InvalidParameterValueException( e ); 458 } 459 ByteArrayOutputStream bos = new ByteArrayOutputStream( 20000 ); 460 PrintWriter pr = new PrintWriter( bos ); 461 capaDoc.write( pr ); 462 return bos.toByteArray(); 463 464 } 465 466 /** 467 * validates the passed xml to be valid against the policy 468 * 469 * @param doc 470 * @return the new response 471 * @throws InvalidParameterValueException 472 */ 473 private byte[] validateCSWCapabilities( Document doc ) 474 throws InvalidParameterValueException { 475 CatalogueCapabilities capa = null; 476 try { 477 CatalogueCapabilitiesDocument capaDoc = new CatalogueCapabilitiesDocument(); 478 capaDoc.setRootElement( doc.getDocumentElement() ); 479 capa = (CatalogueCapabilities) capaDoc.parseCapabilities(); 480 } catch ( Exception e ) { 481 LOG.logError( e.getMessage(), e ); 482 throw new InvalidParameterValueException( 483 Messages.format( 484 "GetCapabilitiesResponseValidator.INVALIDWFSCAPA", 485 e.getMessage() ) ); 486 } 487 488 org.deegree.ogcwebservices.getcapabilities.Operation[] ops = capa.getOperationsMetadata().getOperations(); 489 for ( int i = 0; i < ops.length; i++ ) { 490 setNewOnlineResourceInOldOperation( ops[i] ); 491 } 492 493 CatalogueCapabilitiesDocument capaDoc = null; 494 try { 495 capaDoc = org.deegree.ogcwebservices.csw.XMLFactory_2_0_0.export( capa, null ); 496 } catch ( Exception e ) { 497 throw new InvalidParameterValueException( e ); 498 } 499 ByteArrayOutputStream bos = new ByteArrayOutputStream( 20000 ); 500 PrintWriter pr = new PrintWriter( bos ); 501 capaDoc.write( pr ); 502 return bos.toByteArray(); 503 } 504 505 /** 506 * filters the wms capabilities to rturn just the valid layers 507 * 508 * @param capa 509 * @param user 510 */ 511 private WMSCapabilities filterWMSLayers( WMSCapabilities capa, User user ) 512 throws UnauthorizedException { 513 514 Request req = policy.getRequest( "WMS", "GetCapabilities" ); 515 Condition con = req.getPostConditions(); 516 OperationParameter op = con.getOperationParameter( "layers" ); 517 if ( op.isAny() ) 518 return capa; 519 520 Layer layer = capa.getLayer(); 521 if ( op.isUserCoupled() && user != null ) { 522 try { 523 SecurityAccessManager sam = SecurityAccessManager.getInstance(); 524 SecurityAccess access = sam.acquireAccess( user ); 525 // call recursive method to remove all 'named' layers not 526 // included in the list from the capabilities 527 layer = removeWMSLayer( layer, user, access ); 528 } catch ( Exception e ) { 529 LOG.logError( e.getMessage(), e ); 530 throw new UnauthorizedException( Messages.format( "GetCapabilitiesResponseValidator.INVALIDUSER", user ) ); 531 } 532 } else { 533 // get list of valid wms layers 534 List<?> list = op.getValues(); 535 // call recursive method to remove all 'named' layers not 536 // included in the list from the capabilities 537 layer = removeWMSLayer( layer, list ); 538 } 539 capa.setLayer( layer ); 540 return capa; 541 542 } 543 544 /** 545 * recursive method that removes all 'named' layers (layers that has a name in addtion to a title) from the layer 546 * tree thats root node (layer) is passed to the method and that not present in the passed <tt>List</tt> 547 * 548 * @param layer 549 * @param validLayers 550 */ 551 private Layer removeWMSLayer( Layer layer, List<?> validLayers ) { 552 Layer[] layers = layer.getLayer(); 553 for ( int i = 0; i < layers.length; i++ ) { 554 if ( layers[i].getName() != null && !validLayers.contains( layers[i].getName() ) ) { 555 layer.removeLayer( layers[i].getName() ); 556 } else { 557 removeWMSLayer( layers[i], validLayers ); 558 if ( layers[i].getLayer().length == 0 && layers[i].getName() == null ) { 559 layer.removeLayerByTitle( layers[i].getTitle() ); 560 } 561 } 562 } 563 return layer; 564 } 565 566 /** 567 * recursive method that removes all 'named' layers (layers that has a name in addition to a title) from the layer 568 * tree thats root node (layer) is passed to the method and the passed user doesn't have a GetMap right on. 569 * 570 * @param layer 571 * layer to validate 572 * @param user 573 * user whose rights are considered 574 * @param access 575 * object to access DRM registry 576 * 577 */ 578 private Layer removeWMSLayer( Layer layer, User user, SecurityAccess access ) 579 throws GeneralSecurityException { 580 Layer[] layers = layer.getLayer(); 581 for ( int i = 0; i < layers.length; i++ ) { 582 if ( layers[i].getName() != null ) { 583 SecuredObject secObj = null; 584 try { 585 // must be in try-catch block because an exception will be thrown 586 // if no SecuredObject with the passed layer exists 587 if ( policy.getSecurityConfig().getProxiedUrl() == null ) { 588 secObj = access.getSecuredObjectByName( layers[i].getName(), "Layer" ); 589 } else { 590 secObj = access.getSecuredObjectByName( "[" + policy.getSecurityConfig().getProxiedUrl() + "]:" 591 + layers[i].getName(), "Layer" ); 592 } 593 } catch ( Exception e ) { 594 LOG.logDebug( "Lookup failed? ", e.getLocalizedMessage() ); 595 } 596 if ( secObj == null || user.getRights( access, secObj ).getRight( secObj, GETMAP ) == null ) { 597 // remove the layer from the capabilities if it's not known 598 // by the DRM registry or if the user doesn't have a GetMap 599 // right on it 600 layer.removeLayer( layers[i].getName() ); 601 } 602 } else { 603 removeWMSLayer( layers[i], user, access ); 604 if ( layers[i].getLayer().length == 0 && layers[i].getName() == null ) { 605 layer.removeLayerByTitle( layers[i].getTitle() ); 606 } 607 } 608 } 609 return layer; 610 } 611 612 /** 613 * @param capa 614 * @param user 615 * @return the new capabilities 616 * @throws UnauthorizedException 617 */ 618 private WFSCapabilities filterWFSFeatureType( WFSCapabilities capa, User user ) 619 throws UnauthorizedException { 620 621 Request req = policy.getRequest( "WFS", "GetCapabilities" ); 622 Condition con = req.getPostConditions(); 623 OperationParameter op = con.getOperationParameter( "featureTypes" ); 624 if ( op.isAny() ) 625 return capa; 626 627 if ( op.isUserCoupled() && user != null ) { 628 try { 629 SecurityAccessManager sam = SecurityAccessManager.getInstance(); 630 SecurityAccess access = sam.acquireAccess( user ); 631 FeatureTypeList ftl = capa.getFeatureTypeList(); 632 WFSFeatureType[] ft = ftl.getFeatureTypes(); 633 StringBuffer sb = new StringBuffer( 200 ); 634 for ( int i = 0; i < ft.length; i++ ) { 635 SecuredObject secObj = null; 636 try { 637 // must be in try-catch block because an exception will be thrown 638 // if no SecuredObject with the passed layer exists 639 sb.delete( 0, sb.length() ); 640 sb.append( '{' ).append( ft[i].getName().getNamespace().toASCIIString() ); 641 sb.append( "}:" ).append( ft[i].getName().getLocalName() ); 642 if ( policy.getSecurityConfig().getProxiedUrl() == null ) { 643 secObj = access.getSecuredObjectByName( sb.toString(), "Featuretype" ); 644 } else { 645 secObj = access.getSecuredObjectByName( "[" + policy.getSecurityConfig().getProxiedUrl() 646 + "]:" + sb, "Featuretype" ); 647 } 648 } catch ( Exception e ) { 649 LOG.logDebug( "Lookup failed? ", e.getLocalizedMessage() ); 650 } 651 if ( secObj == null || user.getRights( access, secObj ).getRight( secObj, GETFEATURE ) == null ) { 652 ftl.removeFeatureType( ft[i] ); 653 } 654 } 655 } catch ( Exception e ) { 656 LOG.logError( e.getMessage(), e ); 657 throw new UnauthorizedException( Messages.format( "GetCapabilitiesResponseValidator.INVALIDUSER", user ) ); 658 } 659 } else { 660 // get list of valid wms layers 661 List<String> list = op.getValues(); 662 FeatureTypeList ftl = capa.getFeatureTypeList(); 663 WFSFeatureType[] ft = ftl.getFeatureTypes(); 664 StringBuffer sb = new StringBuffer( 200 ); 665 for ( int i = 0; i < ft.length; i++ ) { 666 sb.delete( 0, sb.length() ); 667 sb.append( '{' ).append( ft[i].getName().getNamespace().toASCIIString() ); 668 sb.append( "}:" ).append( ft[i].getName().getLocalName() ); 669 if ( !list.contains( sb.toString() ) ) { 670 ftl.removeFeatureType( ft[i] ); 671 } 672 } 673 } 674 675 return capa; 676 } 677 }