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