001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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.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.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: 25547 $, $Date: 2010-07-27 17:11:57 +0200 (Di, 27 Jul 2010) $
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        private String proxiedURL;
110    
111        /**
112         * @param policy
113         * @param proxyURL
114         */
115        public GetCapabilitiesResponseValidator( Policy policy, String proxyURL ) {
116            super( policy );
117            this.proxyURL = proxyURL;
118            this.proxiedURL = this.getPolicy().getSecurityConfig().getProxiedUrl();
119        }
120    
121        /**
122         * validates the passed object as a response to a OWS request. The validity of the response may is assigned to
123         * specific user rights. If the passed user is <>null this will be evaluated. <br>
124         * the reponse may contain three valid kinds of objects:
125         * <ul>
126         * <li>a serialized image
127         * <li>a xml encoded exception
128         * <li>a svg-encoded vector image
129         * </ul>
130         * Each of these types can be identified by the mime-type of the response that is also passed to the method. <br>
131         * If something basic went wrong it is possible that not further specified kind of object is passed as response. In
132         * this case the method will throw an <tt>InvalidParameterValueException</tt> to avoid sending bad responses to the
133         * client.
134         * 
135         * @param service
136         *            service which produced the response (WMS, WFS ...)
137         * @param response
138         * @param mime
139         *            mime-type of the response
140         * @param user
141         * @return the new response array
142         * @throws InvalidParameterValueException
143         * @throws UnauthorizedException
144         * @see GetMapRequestValidator#validateRequest(OGCWebServiceRequest, User)
145         */
146        @Override
147        public byte[] validateResponse( String service, byte[] response, String mime, User user )
148                                throws InvalidParameterValueException, UnauthorizedException {
149    
150            Request req = policy.getRequest( service, "GetCapabilities" );
151            if ( req == null ) {
152                throw new InvalidParameterValueException( INVALIDSERVICE + service );
153            }
154            // request is valid because no restrictions are made
155            if ( req.isAny() || req.getPostConditions().isAny() ) {
156                return response;
157            }
158    
159            if ( MimeTypeMapper.isKnownOGCType( mime ) ) {
160                // if the mime-type is a known OGC mime-type it must be an XML
161                // document. probably it is a capabilities document but it also
162                // could be an
163                response = validateXML( service, response, user );
164            } else if ( mime.equals( "text/xml" ) ) {
165                // if the mime-type isn't an image type but 'text/xml'
166                // it could be an exception
167                response = validateXML( service, response, user );
168            } else {
169                throw new InvalidParameterValueException( UNKNOWNMIMETYPE + mime );
170            }
171    
172            return response;
173        }
174    
175        /**
176         * splits document string into 'core' capabilities document and xml header
177         * 
178         * @param xml
179         * @return the splitted document
180         * @throws InvalidParameterValueException
181         */
182        private String[] clearCapabilities( byte[] xml )
183                                throws InvalidParameterValueException {
184            InputStreamReader isr = new InputStreamReader( new ByteArrayInputStream( xml ) );
185            StringBuffer sb = new StringBuffer( 50000 );
186            int c = 0;
187            try {
188                while ( ( c = isr.read() ) > -1 ) {
189                    sb.append( (char) c );
190                }
191                isr.close();
192            } catch ( IOException e ) {
193                String s = Messages.format( "GetCapabilitiesResponseValidator.CAPAREAD", e.getMessage() );
194                throw new InvalidParameterValueException( s );
195            }
196            // WMS <= 1.1.1
197            int pos = sb.indexOf( "<WMT_MS_Capabilities" );
198            // WMS 1.3
199            if ( pos < 0 ) {
200                pos = sb.indexOf( "WMS_Capabilities" );
201            }
202            // WFS 1.1.0
203            if ( pos < 0 ) {
204                pos = sb.indexOf( "WFS_Capabilities" );
205            }
206            // CSW 2.0.0
207            if ( pos < 0 ) {
208                pos = sb.indexOf( "Capabilities" );
209            }
210            // WCS 1.0.0
211            if ( pos < 0 ) {
212                pos = sb.indexOf( "WCS_Capabilities" );
213            }
214    
215            // just if pos is > -1 it makes sense to find the starting
216            // index of the root element
217            if ( pos > -1 ) {
218                pos = pos + 4;
219                char ch = '$';
220                // find starting index of the root element
221                while ( ch != '<' && pos > 0 ) {
222                    pos--;
223                    ch = sb.charAt( pos );
224                }
225                // if the least char read does not equal '<' the parsed document
226                // is not an XML document
227                if ( ch != '<' ) {
228                    pos = -1;
229                }
230            }
231            String[] o = new String[2];
232            if ( pos > 0 ) {
233                // XML header / doctype
234                o[0] = sb.substring( 0, pos );
235            } else {
236                o[0] = "";
237            }
238            if ( pos > -1 ) {
239                // xml document starting at the root element
240                o[1] = sb.substring( pos );
241            } else {
242                // no XML document
243                o[0] = "ERROR";
244                o[1] = sb.toString();
245            }
246    
247            return o;
248        }
249    
250        /**
251         * validates the passed xml to be valid against the policy
252         * 
253         * @param service
254         *            service which produced the response (WMS, WFS ...)
255         * @param xml
256         * @param user
257         * @throws InvalidParameterValueException
258         */
259        private byte[] validateXML( String service, byte[] xml, User user )
260                                throws InvalidParameterValueException, UnauthorizedException {
261    
262            String[] st = clearCapabilities( xml );
263            if ( st[0].equals( "ERROR" ) ) {
264                LOG.logError( st[1] );
265                String s = Messages.format( "GetCapabilitiesResponseValidator.NOCAPADOC", st[1] );
266                throw new InvalidParameterValueException( s );
267            }
268            Document doc = null;
269            try {
270                XMLFragment frag = new XMLFragment();
271                frag.load( new StringReader( st[1] ), XMLFragment.DEFAULT_URL );
272                doc = frag.getRootElement().getOwnerDocument();
273            } catch ( Exception e ) {
274                LOG.logError( e.getMessage(), e );
275                String s = Messages.getString( "GetCapabilitiesResponseValidator.ALLCAPAPARSE" );
276                throw new InvalidParameterValueException( s );
277            }
278            String root = doc.getDocumentElement().getNodeName();
279            if ( root.equalsIgnoreCase( "Exception" ) ) {
280                // if the xml contains a exception the reponse is valid!
281            } else if ( "WMS".equals( service ) ) {
282                try {
283                    xml = validateWMSCapabilities( doc, user );
284                } catch ( XMLParsingException e ) {
285                    LOG.logError( e.getMessage(), e );
286                    throw new InvalidParameterValueException( "invalid WMS capabilities" );
287                }
288            } else if ( "WFS".equals( service ) ) {
289                xml = validateWFSCapabilities( doc, user );
290            } else if ( "WCS".equals( service ) ) {
291                xml = validateWCSCapabilities( doc, user );
292            } else if ( "CSW".equals( service ) ) {
293                xml = validateCSWCapabilities( doc );
294            }
295    
296            StringBuffer sb = new StringBuffer( xml.length + st[0].length() );
297            sb.append( st[0] );
298            String s = new String( xml );
299            int p = s.indexOf( "?>" );
300            if ( p > -1 ) {
301                sb.append( s.substring( p + 2, s.length() ) );
302            } else {
303                sb.append( s );
304            }
305            s = sb.toString();
306            if ( s.indexOf( "<?xml version" ) > 1 ) {
307                s = StringTools.replace( s, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>", "", false );
308                s = StringTools.replace( s, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "", false );
309            }
310    
311            // TODO
312            // regular expression
313            // s = sb.toString().replaceAll( "<?...?>", "" );
314    
315            return s.getBytes();
316        }
317    
318        /**
319         * 
320         * @param doc
321         * @param user
322         * @return nothing, an exception is thrown
323         */
324        private byte[] validateWCSCapabilities( Document doc, User user ) {
325            // TODO
326            // implement support for WCS
327            throw new UnsupportedOperationException();
328        }
329    
330        /**
331         * validates the passed xml to be valid against the policy
332         * 
333         * @param user
334         * @throws InvalidParameterValueException
335         * @throws XMLParsingException
336         */
337        private byte[] validateWMSCapabilities( Document doc, User user )
338                                throws InvalidParameterValueException, UnauthorizedException, XMLParsingException {
339    
340            WMSCapabilitiesDocument cdoc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getDocumentElement() );
341            WMSCapabilities capa = null;
342            try {
343                capa = (WMSCapabilities) cdoc.parseCapabilities();
344            } catch ( InvalidCapabilitiesException e ) {
345                LOG.logError( e.getMessage(), e );
346                String s = Messages.format( "GetCapabilitiesResponseValidator.WMSCAPAPARSE", e.getMessage() );
347                throw new InvalidParameterValueException( s );
348            }
349            capa = filterWMSLayers( capa, user );
350    
351            List<Operation> ops = capa.getOperationMetadata().getOperations();
352            for ( Operation operation : ops ) {
353                setNewOnlineResource( operation );
354            }
355    
356            ByteArrayOutputStream bos = new ByteArrayOutputStream( 50000 );
357            byte[] b;
358            try {
359                cdoc = XMLFactory.export( capa );
360                Properties properties = new Properties();
361                // setting this to system charset is no problem, as later on it will be converted to a different encoding
362                // again anyway
363                // not using byte arrays might solve the problems here...
364                properties.setProperty( OutputKeys.ENCODING, getSystemCharset() );
365                cdoc.write( bos, properties );
366                b = bos.toByteArray();
367                bos.close();
368            } catch ( Exception e ) {
369                LOG.logError( e.getMessage(), e );
370                String s = Messages.format( "GetCapabilitiesResponseValidator.WMSCAPAEXPORT", e.getMessage() );
371                throw new InvalidParameterValueException( s );
372            }
373    
374            return b;
375    
376        }
377    
378        /**
379         * 
380         * @param op
381         */
382        private void setNewOnlineResource( Operation op ) {
383            if ( op.getDCP() != null ) {
384                List<DCP> dcps = op.getDCP();
385                for ( DCP dcp : dcps ) {
386                    HTTP http = (HTTP) dcp;
387                    List<OnlineResource> links = http.getLinks();
388                    try {
389                        int size = links.size();
390                        links.clear();
391                        OnlineResource proxy = new OnlineResource( new Linkage( new URL( proxyURL ) ) );
392                        for ( int i = 0; i < size; ++i )
393                            links.add( proxy );
394                    } catch ( MalformedURLException e1 ) {
395                        LOG.logError( e1.getLocalizedMessage(), e1 );
396                    }
397                }
398            }
399        }
400    
401        /**
402         * Sets the proxy online resource in the old owscommon Operation class. To be removed soon!
403         * 
404         * @param op
405         */
406        private void setNewOnlineResourceInOldOperation( org.deegree.ogcwebservices.getcapabilities.Operation op ) {
407            if ( op.getDCPs() != null ) {
408                for ( int i = 0; i < op.getDCPs().length; i++ ) {
409                    org.deegree.ogcwebservices.getcapabilities.HTTP http = (org.deegree.ogcwebservices.getcapabilities.HTTP) op.getDCPs()[i].getProtocol();
410                    try {
411                        if ( http.getGetOnlineResources().length > 0 ) {
412                            URL urls[] = new URL[http.getGetOnlineResources().length];
413                            for ( int k = 0; k < http.getGetOnlineResources().length; ++k )
414                                urls[k] = new URL( proxyURL );
415                            http.setGetOnlineResources( urls );
416                        }
417                        if ( http.getPostOnlineResources().length > 0 ) {
418                            URL urls[] = new URL[http.getPostOnlineResources().length];
419                            for ( int k = 0; k < http.getPostOnlineResources().length; ++k )
420                                urls[k] = new URL( proxyURL );
421                            http.setPostOnlineResources( urls );
422                        }
423                    } catch ( MalformedURLException e1 ) {
424                        e1.printStackTrace();
425                    }
426                }
427            }
428        }
429    
430        /**
431         * validates the passed xml to be valid against the policy
432         * 
433         * @param user
434         * @throws InvalidParameterValueException
435         * @throws UnauthorizedException
436         */
437        private byte[] validateWFSCapabilities( Document doc, User user )
438                                throws InvalidParameterValueException, UnauthorizedException {
439    
440            WFSCapabilities capa = null;
441            try {
442                WFSCapabilitiesDocument capaDoc = new WFSCapabilitiesDocument();
443                capaDoc.setRootElement( doc.getDocumentElement() );
444                capa = (WFSCapabilities) capaDoc.parseCapabilities();
445            } catch ( Exception e ) {
446                LOG.logError( e.getMessage(), e );
447                String s = Messages.format( "GetCapabilitiesResponseValidator.INVALIDWFSCAPA", e.getMessage() );
448                throw new InvalidParameterValueException( s );
449            }
450    
451            capa = filterWFSFeatureType( capa, user );
452    
453            org.deegree.ogcwebservices.getcapabilities.Operation[] ops = capa.getOperationsMetadata().getOperations();
454            for ( int i = 0; i < ops.length; i++ ) {
455                setNewOnlineResourceInOldOperation( ops[i] );
456            }
457    
458            WFSCapabilitiesDocument capaDoc = null;
459            try {
460                capaDoc = org.deegree.ogcwebservices.wfs.XMLFactory.export( capa );
461            } catch ( Exception e ) {
462                throw new InvalidParameterValueException( e );
463            }
464            ByteArrayOutputStream bos = new ByteArrayOutputStream( 20000 );
465            PrintWriter pr = new PrintWriter( bos );
466            capaDoc.write( pr );
467            return bos.toByteArray();
468    
469        }
470    
471        /**
472         * validates the passed xml to be valid against the policy
473         * 
474         * @param doc
475         * @return the new response
476         * @throws InvalidParameterValueException
477         */
478        private byte[] validateCSWCapabilities( Document doc )
479                                throws InvalidParameterValueException {
480            CatalogueCapabilities capa = null;
481            try {
482                CatalogueCapabilitiesDocument capaDoc = new CatalogueCapabilitiesDocument();
483                capaDoc.setRootElement( doc.getDocumentElement() );
484                capa = (CatalogueCapabilities) capaDoc.parseCapabilities();
485            } catch ( Exception e ) {
486                LOG.logError( e.getMessage(), e );
487                throw new InvalidParameterValueException(
488                                                          Messages.format(
489                                                                           "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                    if ( secObj == null || user.getRights( access, secObj ).getRight( secObj, GETMAP ) == null ) {
629                        // remove the layer from the capabilities if it's not known
630                        // by the DRM registry or if the user doesn't have a GetMap
631                        // right on it
632                        layer.removeLayer( layers[i].getName() );
633                    }
634                } else {
635                    removeWMSLayer( layers[i], user, access );
636                    if ( layers[i].getLayer().length == 0 && layers[i].getName() == null ) {
637                        layer.removeLayerByTitle( layers[i].getTitle() );
638                    }
639                }
640            }
641            return layer;
642        }
643    
644        /**
645         * @param capa
646         * @param user
647         * @return the new capabilities
648         * @throws UnauthorizedException
649         */
650        private WFSCapabilities filterWFSFeatureType( WFSCapabilities capa, User user )
651                                throws UnauthorizedException {
652    
653            Request req = policy.getRequest( "WFS", "GetCapabilities" );
654            Condition con = req.getPostConditions();
655            OperationParameter op = con.getOperationParameter( "featureTypes" );
656            if ( op.isAny() )
657                return capa;
658    
659            if ( op.isUserCoupled() && user != null ) {
660                try {
661                    SecurityAccessManager sam = SecurityAccessManager.getInstance();
662                    SecurityAccess access = sam.acquireAccess( user );
663                    FeatureTypeList ftl = capa.getFeatureTypeList();
664                    WFSFeatureType[] ft = ftl.getFeatureTypes();
665                    StringBuffer sb = new StringBuffer( 200 );
666                    for ( int i = 0; i < ft.length; i++ ) {
667                        SecuredObject secObj = null;
668                        try {
669                            // must be in try-catch block because an exception will be thrown
670                            // if no SecuredObject with the passed layer exists
671                            sb.delete( 0, sb.length() );
672                            sb.append( '{' ).append( ft[i].getName().getNamespace().toASCIIString() );
673                            sb.append( "}:" ).append( ft[i].getName().getLocalName() );
674                            if ( policy.getSecurityConfig().getProxiedUrl() == null ) {
675                                secObj = access.getSecuredObjectByName( sb.toString(), "Featuretype" );
676                            } else {
677                                secObj = access.getSecuredObjectByName( "[" + policy.getSecurityConfig().getProxiedUrl()
678                                                                        + "]:" + sb, "Featuretype" );
679                            }
680                        } catch ( Exception e ) {
681                            LOG.logDebug( "Lookup failed? ", e.getLocalizedMessage() );
682                        }
683                        if ( secObj == null || user.getRights( access, secObj ).getRight( secObj, GETFEATURE ) == null ) {
684                            ftl.removeFeatureType( ft[i] );
685                        }
686                    }
687                } catch ( Exception e ) {
688                    LOG.logError( e.getMessage(), e );
689                    throw new UnauthorizedException( Messages.format( "GetCapabilitiesResponseValidator.INVALIDUSER", user ) );
690                }
691            } else {
692                // get list of valid wms layers
693                List<String> list = op.getValues();
694                FeatureTypeList ftl = capa.getFeatureTypeList();
695                WFSFeatureType[] ft = ftl.getFeatureTypes();
696                StringBuffer sb = new StringBuffer( 200 );
697                for ( int i = 0; i < ft.length; i++ ) {
698                    sb.delete( 0, sb.length() );
699                    sb.append( '{' ).append( ft[i].getName().getNamespace().toASCIIString() );
700                    sb.append( "}:" ).append( ft[i].getName().getLocalName() );
701                    if ( !list.contains( sb.toString() ) ) {
702                        ftl.removeFeatureType( ft[i] );
703                    }
704                }
705            }
706    
707            return capa;
708        }
709    }