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