Coverage Report - org.acegisecurity.intercept.web.PathBasedFilterInvocationDefinitionMap
 
Classes in this File Line Coverage Branch Coverage Complexity
PathBasedFilterInvocationDefinitionMap
90% 
100% 
2.1
 
 1  
 /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 2  
  *
 3  
  * Licensed under the Apache License, Version 2.0 (the "License");
 4  
  * you may not use this file except in compliance with the License.
 5  
  * You may obtain a copy of the License at
 6  
  *
 7  
  *     http://www.apache.org/licenses/LICENSE-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing, software
 10  
  * distributed under the License is distributed on an "AS IS" BASIS,
 11  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
  * See the License for the specific language governing permissions and
 13  
  * limitations under the License.
 14  
  */
 15  
 
 16  
 package org.acegisecurity.intercept.web;
 17  
 
 18  
 import org.acegisecurity.ConfigAttributeDefinition;
 19  
 
 20  
 import org.apache.commons.logging.Log;
 21  
 import org.apache.commons.logging.LogFactory;
 22  
 
 23  
 import org.springframework.util.AntPathMatcher;
 24  
 import org.springframework.util.PathMatcher;
 25  
 
 26  
 import java.util.HashSet;
 27  
 import java.util.Iterator;
 28  
 import java.util.List;
 29  
 import java.util.Set;
 30  
 import java.util.Vector;
 31  
 
 32  
 
 33  
 /**
 34  
  * Maintains a <code>List</code> of <code>ConfigAttributeDefinition</code>s associated with different HTTP request
 35  
  * URL Apache Ant path-based patterns.<p>Apache Ant path expressions are used to match a HTTP request URL against a
 36  
  * <code>ConfigAttributeDefinition</code>.</p>
 37  
  * <p>The order of registering the Ant paths using the {@link #addSecureUrl(String,ConfigAttributeDefinition)} is
 38  
  * very important. The system will identify the <b>first</b>  matching path for a given HTTP URL. It will not proceed
 39  
  * to evaluate later paths if a match has already been found. Accordingly, the most specific paths should be
 40  
  * registered first, with the most general paths registered last.</p>
 41  
  * <p>If no registered paths match the HTTP URL, <code>null</code> is returned.</p>
 42  
  *
 43  
  * @author Ben Alex
 44  
  * @version $Id: PathBasedFilterInvocationDefinitionMap.java 1970 2007-08-28 16:53:05Z luke_t $
 45  
  */
 46  40
 public class PathBasedFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource
 47  
         implements FilterInvocationDefinition {
 48  
     //~ Static fields/initializers =====================================================================================
 49  
 
 50  2
     private static final Log logger = LogFactory.getLog(PathBasedFilterInvocationDefinitionMap.class);
 51  
 
 52  
     //~ Instance fields ================================================================================================
 53  
 
 54  40
     private List requestMap = new Vector();
 55  40
     private PathMatcher pathMatcher = new AntPathMatcher();
 56  40
     private boolean convertUrlToLowercaseBeforeComparison = false;
 57  
 
 58  
     //~ Methods ========================================================================================================
 59  
 
 60  
     public void addSecureUrl(String antPath, ConfigAttributeDefinition attr) {
 61  
         // SEC-501: If using lower case comparison, we should convert the paths to lower case
 62  
         // as any upper case characters included by mistake will prevent the URL from ever being matched.
 63  69
         if (convertUrlToLowercaseBeforeComparison) {
 64  47
             antPath = antPath.toLowerCase();
 65  
         }
 66  
 
 67  69
         requestMap.add(new EntryHolder(antPath, attr));
 68  
 
 69  69
         if (logger.isDebugEnabled()) {
 70  0
             logger.debug("Added Ant path: " + antPath + "; attributes: " + attr);
 71  
         }
 72  69
     }
 73  
 
 74  
     public Iterator getConfigAttributeDefinitions() {
 75  19
         Set set = new HashSet();
 76  19
         Iterator iter = requestMap.iterator();
 77  
 
 78  71
         while (iter.hasNext()) {
 79  52
             EntryHolder entryHolder = (EntryHolder) iter.next();
 80  52
             set.add(entryHolder.getConfigAttributeDefinition());
 81  52
         }
 82  
 
 83  19
         return set.iterator();
 84  
     }
 85  
 
 86  
     public int getMapSize() {
 87  2
         return this.requestMap.size();
 88  
     }
 89  
 
 90  
     public boolean isConvertUrlToLowercaseBeforeComparison() {
 91  85
         return convertUrlToLowercaseBeforeComparison;
 92  
     }
 93  
 
 94  
     public ConfigAttributeDefinition lookupAttributes(String url) {
 95  
         // Strip anything after a question mark symbol, as per SEC-161. See also SEC-321
 96  19
         int firstQuestionMarkIndex = url.indexOf("?");
 97  
 
 98  19
         if (firstQuestionMarkIndex != -1) {
 99  3
             url = url.substring(0, firstQuestionMarkIndex);
 100  
         }
 101  
 
 102  19
         if (isConvertUrlToLowercaseBeforeComparison()) {
 103  9
             url = url.toLowerCase();
 104  
 
 105  9
             if (logger.isDebugEnabled()) {
 106  0
                 logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'");
 107  
             }
 108  
         }
 109  
 
 110  19
         Iterator iter = requestMap.iterator();
 111  
 
 112  32
         while (iter.hasNext()) {
 113  27
             EntryHolder entryHolder = (EntryHolder) iter.next();
 114  
 
 115  27
             boolean matched = pathMatcher.match(entryHolder.getAntPath(), url);
 116  
 
 117  27
             if (logger.isDebugEnabled()) {
 118  0
                 logger.debug("Candidate is: '" + url + "'; pattern is " + entryHolder.getAntPath() + "; matched="
 119  
                         + matched);
 120  
             }
 121  
 
 122  27
             if (matched) {
 123  14
                 return entryHolder.getConfigAttributeDefinition();
 124  
             }
 125  13
         }
 126  
 
 127  5
         return null;
 128  
     }
 129  
 
 130  
     public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) {
 131  23
         this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
 132  23
     }
 133  
 
 134  
     //~ Inner Classes ==================================================================================================
 135  
 
 136  40
     protected class EntryHolder {
 137  
         private ConfigAttributeDefinition configAttributeDefinition;
 138  
         private String antPath;
 139  
 
 140  69
         public EntryHolder(String antPath, ConfigAttributeDefinition attr) {
 141  69
             this.antPath = antPath;
 142  69
             this.configAttributeDefinition = attr;
 143  69
         }
 144  
 
 145  0
         protected EntryHolder() {
 146  0
             throw new IllegalArgumentException("Cannot use default constructor");
 147  
         }
 148  
 
 149  
         public String getAntPath() {
 150  27
             return antPath;
 151  
         }
 152  
 
 153  
         public ConfigAttributeDefinition getConfigAttributeDefinition() {
 154  66
             return configAttributeDefinition;
 155  
         }
 156  
     }
 157  
 }