Package org.geoserver.security

Source Code of org.geoserver.security.RESTfulDefinitionSource$RESTfulDefinitionSourceMapping

package org.geoserver.security;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.SecurityConfig;
import org.acegisecurity.intercept.web.FilterInvocation;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionDecorator;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionSourceMapping;
import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource;

import org.acegisecurity.util.StringSplitUtils;
import org.springframework.util.StringUtils;





/**
*
* @author Chris Berry
* http://opensource.atlassian.com/projects/spring/browse/SEC-531
*
*/
public class RESTfulDefinitionSource implements FilterInvocationDefinitionSource {
      
    static private Log log = LogFactory.getLog(RESTfulDefinitionSource.class);

    static private final String[] validMethodNames = { "GET", "PUT", "DELETE", "POST" };

    /**
     * Underlying objectDefinitionSource object
     */
    private RESTfulPathBasedFilterInvocationDefinitionMap delegate = null;  
    /**
     * rest access rules dao
     */
    private RESTAccessRuleDAO dao;
   
    /**
     * Override the method in AbstractFilterInvocationDefinitionSource
     */
    public ConfigAttributeDefinition getAttributes( Object object )
        throws IllegalArgumentException {
       
        if ((object == null) || !this.supports(object.getClass())) {
            throw new IllegalArgumentException("Object must be a FilterInvocation");
        }

        String url = ((FilterInvocation) object).getRequestUrl();
        String method = ((FilterInvocation) object).getHttpRequest().getMethod();

        return delegate().lookupAttributes( cleanURL(url), method );
    }

    /**
     * this form is invalid for this implementation
     */
    public ConfigAttributeDefinition lookupAttributes( String url ) {
        throw new IllegalArgumentException( "lookupAttributes(String url) is INVALID for RESTfulDefinitionSource" );
    }

    public ConfigAttributeDefinition lookupAttributes( String url, String method ) {
        return delegate().lookupAttributes(cleanURL(url), method );
    }

    public Iterator getConfigAttributeDefinitions() {
        return delegate().getConfigAttributeDefinitions();       
    }

    /**
     * Duplicated from AbstractFilterInvocationDefinitionSource
     */
    public boolean supports(Class clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
   
    /**
     * Creates a proxy to a PathBasedFilterInvocationDefinitionMap to delegate calls.
     * Initializations of the delegate is done here.
     *
     * @deprecated This is not longer used (JD)
     */
    public RESTfulDefinitionSource( String pathToRoleList ) throws IllegalArgumentException {   
        delegate = new RESTfulPathBasedFilterInvocationDefinitionMap();
        processPathList( pathToRoleList );
    }

    public RESTfulDefinitionSource(RESTAccessRuleDAO dao) {
        this.dao = dao;
       
        //force a read of the property file at startup
        dao.reload();
    }
   
    RESTfulPathBasedFilterInvocationDefinitionMap delegate() {
        if (delegate == null || dao.isModified()) {
            synchronized(this) {
                delegate = new RESTfulPathBasedFilterInvocationDefinitionMap();
                for (String rule : dao.getRules()) {
                    processPathList(rule);
                }   
            }
        }
        return delegate;
    }
   
    /**
     * this is completely bogus. I am duplicating code in FilterInvocationDefinitionSourceEditor
     */
    private void processPathList( String pathToRoleList ) throws IllegalArgumentException {

        /*
        FilterInvocationDefinitionDecorator source = new FilterInvocationDefinitionDecorator();
        source.setDecorated( delegate );
        source.setConvertUrlToLowercaseBeforeComparison( true );
        */
        delegate.setConvertUrlToLowercaseBeforeComparison( true );

        BufferedReader br = new BufferedReader( new StringReader( pathToRoleList ) );
        int counter = 0;
        String line;
       
        List mappings = new ArrayList();
       
        while (true) {
            counter++;          
            try {
                line = br.readLine();
            } catch (IOException ioe) {
                throw new IllegalArgumentException(ioe.getMessage());
            }
           
            if (line == null) {
                break;
            }
           
            line = line.trim();
           
            if (log.isDebugEnabled()) {
                log.debug("Line " + counter + ": " + line);
            }
           
            if (line.startsWith("//")) {
                continue;
            }
           
            // Skip lines that are not directives
            if (line.lastIndexOf('=') == -1) {
                continue;
            }
           
            if (line.lastIndexOf("==") != -1) {
                throw new IllegalArgumentException("Only single equals should be used in line " + line);
            }
           
            // Tokenize the line into its name/value tokens
            // As per SEC-219, use the LAST equals as the delimiter between LHS and RHS
            String name = StringSplitUtils.substringBeforeLast(line, "=");
            String value = StringSplitUtils.substringAfterLast(line, "=");
           
            if (!StringUtils.hasText(name) || !StringUtils.hasText(value)) {
                throw new IllegalArgumentException("Failed to parse a valid name/value pair from " + line);
            }

            String antPath = name;
            String methods = null;

            int firstColonIndex = name.indexOf( ":" );
            if (log.isDebugEnabled())
                log.debug( "~~~~~~~~~~ name= " + name + " firstColonIndex= " + firstColonIndex );

            if (firstColonIndex != -1) {
                antPath = name.substring( 0, firstColonIndex );
                methods = name.substring( (firstColonIndex+1), name.length() );
            }
            if (log.isDebugEnabled())
                log.debug( "~~~~~~~~~~ name= " + name + " antPath= " + antPath + " methods= " + methods );

            String[] methodList = null;
            if ( methods != null ) {
                methodList = methods.split( "," );

                // Verify methodList is valid
                for( int ii=0; ii < methodList.length; ii++ ) {
                    boolean matched = false;
                    for ( int jj=0; jj < validMethodNames.length; jj++ ) {
                        if ( methodList[ii].equals( validMethodNames[jj] ) ) {
                            matched = true;
                            break;
                        }
                    }
                    if ( !matched ) {
                        throw new IllegalArgumentException( "The HTTP Method Name (" + methodList[ii] +
                                                            " does NOT equal a valid name (GET,PUT,POST,DELETE)" );
                    }
                }
            }
            if (log.isDebugEnabled()) {
                log.debug("methodList = " + methodList );
                if ( methodList != null ) {
                    for( int ii=0; ii <  methodList.length; ii++ )
                        log.debug("method[" + ii + "]: " +  methodList[ii] );  
                }
            }

            // Should all be lowercase; check each character
            // We only do this for Ant (regexp have control chars)
            for (int i = 0; i < antPath.length(); i++) {
                String character = antPath.substring(i, i + 1);            
                if (!character.toLowerCase().equals(character)) {
                    throw new IllegalArgumentException("You are using Ant Paths, yet you have specified an uppercase character in line: "
                                                       + line + " (character '" + character + "')");
                }
            }

            RESTfulDefinitionSourceMapping mapping = new RESTfulDefinitionSourceMapping();
            mapping.setUrl( antPath );
            mapping.setHttpMethods( methodList );
           
            String[] tokens = StringUtils.commaDelimitedListToStringArray(value);

            for (int i = 0; i < tokens.length; i++) {
                mapping.addConfigAttribute( tokens[i].trim() );
            }
            mappings.add(mapping);
        }  

        // This will call the addSecureUrl in RESTfulPathBasedFilterInvocationDefinitionMap
        //   which is how this whole convoluted beast gets wired together
        //source.setMappings(mappings);
        setMappings( mappings );
    }

    public void setMappings( List mappings ) {
        Iterator it = mappings.iterator();
        while (it.hasNext()) {
            RESTfulDefinitionSourceMapping mapping = (RESTfulDefinitionSourceMapping)it.next();
            ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition();

            Iterator configAttributesIt = mapping.getConfigAttributes().iterator();
            while (configAttributesIt.hasNext()) {
                String s = (String) configAttributesIt.next();
                configDefinition.addConfigAttribute( new SecurityConfig(s) );
            }
            delegate.addSecureUrl(mapping.getUrl(), mapping.getHttpMethods(), configDefinition);
        }
    }

    /**
     * Hacks an incoming url to help with matching.
     */
    String cleanURL(String url) {
        //remove any trailing slashes
        url = url.replaceAll("/+$", "");
        return url;
    }
   
    //++++++++++++++++++++++++
    static public class RESTfulDefinitionSourceMapping {       
        private String url = null;     
        private List configAttributes = new ArrayList();
        private String[] httpMethods = null;

        public void setHttpMethods( String[] httpMethods )
        { this.httpMethods = httpMethods; }    
        /**
         * A null httpMethods implies that ALL methods are accepted
         */
        public String[] getHttpMethods()
        { return httpMethods; }
       
        public void setUrl( String url )
        { this.url = url; }    
        public String getUrl()
        { return url; }
       
        public void setConfigAttributes( List roles )
        { this.configAttributes = roles; }

        public List getConfigAttributes()
        { return configAttributes; }

        public void addConfigAttribute( String configAttribute )
        { configAttributes.add(configAttribute); }      
    }


}
TOP

Related Classes of org.geoserver.security.RESTfulDefinitionSource$RESTfulDefinitionSourceMapping

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.