org.geoserver.security.RESTfulPathBasedFilterInvocationDefinitionMap.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.security.RESTfulPathBasedFilterInvocationDefinitionMap.java

Source

/* Copyright (c) 2001 - 2013 OpenPlans - www.openplans.org. All rights reserved.
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.security;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.Arrays;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.util.StringUtils;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

/**
 * 
 * @author Chris Berry
 * http://opensource.atlassian.com/projects/spring/browse/SEC-531
 *
 */

public class RESTfulPathBasedFilterInvocationDefinitionMap implements FilterInvocationSecurityMetadataSource {

    static private Log log = LogFactory.getLog(RESTfulPathBasedFilterInvocationDefinitionMap.class);

    //~ Instance fields ================================================================================================

    private Collection<EntryHolder> requestMap = new Vector<EntryHolder>();
    private PathMatcher pathMatcher = new AntPathMatcher();
    private boolean convertUrlToLowercaseBeforeComparison = false;

    //~ Methods ========================================================================================================
    public boolean supports(Class clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }

    public void addSecureUrl(String antPath, String[] httpMethods, Collection<ConfigAttribute> attrs) {
        requestMap.add(new EntryHolder(antPath, httpMethods, attrs));

        if (log.isDebugEnabled()) {
            log.debug("Added Ant path: " + antPath + "; attributes: " + attrs + ", httpMethods: "
                    + Arrays.toString(httpMethods));
        }
    }

    public void addSecureUrl(String antPath, Collection<ConfigAttribute> attrs) {
        throw new IllegalArgumentException(
                "addSecureUrl(String, Collection<ConfigAttribute> ) is INVALID for RESTfulDefinitionSource");
    }

    public Collection<ConfigAttribute> getAllConfigAttributes() {
        Set<ConfigAttribute> set = new HashSet<ConfigAttribute>();

        for (EntryHolder h : requestMap) {
            set.addAll(h.getConfigAttributes());
        }

        return set;
        //return set.iterator();
    }

    public int getMapSize() {
        return this.requestMap.size();
    }

    public boolean isConvertUrlToLowercaseBeforeComparison() {
        return convertUrlToLowercaseBeforeComparison;
    }

    public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) {
        this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
    }

    public Collection<ConfigAttribute> 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 this.lookupAttributes(url, method);
    }

    public Collection<ConfigAttribute> lookupAttributes(String url) {
        throw new IllegalArgumentException("lookupAttributes(String url) is INVALID for RESTfulDefinitionSource");
    }

    public Collection<ConfigAttribute> lookupAttributes(String url, String httpMethod) {
        // Strip anything after a question mark symbol, as per SEC-161. See also SEC-321
        int firstQuestionMarkIndex = url.indexOf("?");

        if (firstQuestionMarkIndex != -1) {
            url = url.substring(0, firstQuestionMarkIndex);
        }

        if (isConvertUrlToLowercaseBeforeComparison()) {
            url = url.toLowerCase();

            if (log.isDebugEnabled()) {
                log.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'  and httpMethod= "
                        + httpMethod);
            }
        }

        Iterator iter = requestMap.iterator();
        while (iter.hasNext()) {
            EntryHolder entryHolder = (EntryHolder) iter.next();

            String antPath = entryHolder.getAntPath();
            String[] methodList = entryHolder.getHttpMethodList();
            if (log.isDebugEnabled()) {
                log.debug("~~~~~~~~~~ antPath= " + antPath + " methodList= " + Arrays.toString(methodList));
            }

            boolean matchedPath = pathMatcher.match(antPath, url);
            boolean matchedMethods = true;
            if (methodList != null) {
                matchedMethods = false;
                for (int ii = 0; ii < methodList.length; ii++) {
                    if (methodList[ii].equals(httpMethod)) {
                        matchedMethods = true;
                        break;
                    }
                }
            }
            if (log.isDebugEnabled())
                log.debug("Candidate is: '" + url + "'; antPath is " + antPath + "; matchedPath=" + matchedPath
                        + "; matchedMethods=" + matchedMethods);

            if (matchedPath && matchedMethods) {
                log.debug("returning "
                        + StringUtils.collectionToCommaDelimitedString(entryHolder.getConfigAttributes()));
                return entryHolder.getConfigAttributes();
            }
        }
        return null;
    }

    //~ Inner Classes ==================================================================================================

    protected class EntryHolder {
        private Collection<ConfigAttribute> configAttributes;
        private String antPath;
        private String[] httpMethodList;

        public EntryHolder(String antPath, String[] httpMethodList, Collection<ConfigAttribute> attrs) {
            this.antPath = antPath;
            this.configAttributes = attrs;
            this.httpMethodList = httpMethodList;
        }

        protected EntryHolder() {
            throw new IllegalArgumentException("Cannot use default constructor");
        }

        public String getAntPath() {
            return antPath;
        }

        public String[] getHttpMethodList() {
            return httpMethodList;
        }

        public Collection<ConfigAttribute> getConfigAttributes() {
            return configAttributes;
        }
    }
}