Coverage Report - org.acegisecurity.intercept.web.FilterInvocationDefinitionSourceEditor
 
Classes in this File Line Coverage Branch Coverage Complexity
FilterInvocationDefinitionSourceEditor
90% 
100% 
28
 
 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 java.beans.PropertyEditorSupport;
 19  
 import java.io.BufferedReader;
 20  
 import java.io.IOException;
 21  
 import java.io.StringReader;
 22  
 import java.util.ArrayList;
 23  
 import java.util.List;
 24  
 
 25  
 import org.acegisecurity.util.StringSplitUtils;
 26  
 import org.apache.commons.logging.Log;
 27  
 import org.apache.commons.logging.LogFactory;
 28  
 import org.springframework.util.StringUtils;
 29  
 
 30  
 
 31  
 /**
 32  
  * Property editor to assist with the setup of a {@link FilterInvocationDefinitionSource}.<p>The class creates and
 33  
  * populates a {@link RegExpBasedFilterInvocationDefinitionMap} or {@link PathBasedFilterInvocationDefinitionMap}
 34  
  * (depending on the type of patterns presented).</p>
 35  
  *  <p>By default the class treats presented patterns as regular expressions. If the keyword
 36  
  * <code>PATTERN_TYPE_APACHE_ANT</code> is present (case sensitive), patterns will be treated as Apache Ant paths
 37  
  * rather than regular expressions.</p>
 38  
  *
 39  
  * @author Ben Alex
 40  
  * @version $Id: FilterInvocationDefinitionSourceEditor.java 1784 2007-02-24 21:00:24Z luke_t $
 41  
  */
 42  43
 public class FilterInvocationDefinitionSourceEditor extends PropertyEditorSupport {
 43  
     //~ Static fields/initializers =====================================================================================
 44  
 
 45  2
     private static final Log logger = LogFactory.getLog(FilterInvocationDefinitionSourceEditor.class);
 46  
     public static final String DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON =
 47  
             "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON";
 48  
     public static final String DIRECTIVE_PATTERN_TYPE_APACHE_ANT = "PATTERN_TYPE_APACHE_ANT";
 49  
 
 50  
     //~ Methods ========================================================================================================
 51  
 
 52  
     public void setAsText(String s) throws IllegalArgumentException {
 53  43
         FilterInvocationDefinitionDecorator source = new FilterInvocationDefinitionDecorator();
 54  
 
 55  43
         if ((s == null) || "".equals(s)) {
 56  
             // Leave target object empty
 57  2
             source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap());
 58  
         } else {
 59  
             // Check if we need to override the default definition map
 60  41
             if (s.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) {
 61  30
                 source.setDecorated(new PathBasedFilterInvocationDefinitionMap());
 62  
 
 63  30
                 if (logger.isDebugEnabled()) {
 64  0
                     logger.debug(("Detected " + DIRECTIVE_PATTERN_TYPE_APACHE_ANT
 65  
                         + " directive; using Apache Ant style path expressions"));
 66  
                 }
 67  
             } else {
 68  11
                 source.setDecorated(new RegExpBasedFilterInvocationDefinitionMap());
 69  
             }
 70  
 
 71  41
             if (s.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) {
 72  20
                 if (logger.isDebugEnabled()) {
 73  0
                     logger.debug("Detected " + DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
 74  
                         + " directive; Instructing mapper to convert URLs to lowercase before comparison");
 75  
                 }
 76  
 
 77  20
                 source.setConvertUrlToLowercaseBeforeComparison(true);
 78  
             }
 79  
 
 80  41
             BufferedReader br = new BufferedReader(new StringReader(s));
 81  41
             int counter = 0;
 82  
             String line;
 83  
 
 84  41
             List mappings = new ArrayList();
 85  
 
 86  
             while (true) {
 87  202
                 counter++;
 88  
 
 89  
                 try {
 90  202
                     line = br.readLine();
 91  0
                 } catch (IOException ioe) {
 92  0
                     throw new IllegalArgumentException(ioe.getMessage());
 93  202
                 }
 94  
 
 95  202
                 if (line == null) {
 96  36
                     break;
 97  
                 }
 98  
 
 99  166
                 line = line.trim();
 100  
 
 101  166
                 if (logger.isDebugEnabled()) {
 102  0
                     logger.debug("Line " + counter + ": " + line);
 103  
                 }
 104  
 
 105  166
                 if (line.startsWith("//")) {
 106  2
                     continue;
 107  
                 }
 108  
 
 109  
                 // Attempt to detect malformed lines (as per SEC-204)
 110  164
                 if (line.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1) {
 111  
                     // Directive found; check for second directive or name=value
 112  20
                     if ((line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) || (line.lastIndexOf("=") != -1)) {
 113  2
                         throw new IllegalArgumentException("Line appears to be malformed: " + line);
 114  
                     }
 115  
                 }
 116  
 
 117  
                 // Attempt to detect malformed lines (as per SEC-204)
 118  162
                 if (line.lastIndexOf(DIRECTIVE_PATTERN_TYPE_APACHE_ANT) != -1) {
 119  
                     // Directive found; check for second directive or name=value
 120  29
                     if ((line.lastIndexOf(DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON) != -1)
 121  
                         || (line.lastIndexOf("=") != -1)) {
 122  1
                         throw new IllegalArgumentException("Line appears to be malformed: " + line);
 123  
                     }
 124  
                 }
 125  
 
 126  
                 // Skip lines that are not directives
 127  161
                 if (line.lastIndexOf('=') == -1) {
 128  79
                     continue;
 129  
                 }
 130  
 
 131  82
                 if (line.lastIndexOf("==") != -1) {
 132  1
                     throw new IllegalArgumentException("Only single equals should be used in line " + line);
 133  
                 }
 134  
 
 135  
                 // Tokenize the line into its name/value tokens
 136  
                 // As per SEC-219, use the LAST equals as the delimiter between LHS and RHS
 137  81
                 String name = StringSplitUtils.substringBeforeLast(line, "=");
 138  81
                 String value = StringSplitUtils.substringAfterLast(line, "=");
 139  
 
 140  81
                 if (!StringUtils.hasText(name) || !StringUtils.hasText(value)) {
 141  0
                     throw new IllegalArgumentException("Failed to parse a valid name/value pair from " + line);
 142  
                 }
 143  
 
 144  
                 // Attempt to detect malformed lines (as per SEC-204)
 145  81
                 if (source.isConvertUrlToLowercaseBeforeComparison()
 146  
                     && source.getDecorated() instanceof PathBasedFilterInvocationDefinitionMap) {
 147  
                     // Should all be lowercase; check each character
 148  
                     // We only do this for Ant (regexp have control chars)
 149  595
                     for (int i = 0; i < name.length(); i++) {
 150  551
                         String character = name.substring(i, i + 1);
 151  
 
 152  551
                         if (!character.toLowerCase().equals(character)) {
 153  1
                             throw new IllegalArgumentException("You are using the "
 154  
                                 + DIRECTIVE_CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
 155  
                                 + " with Ant Paths, yet you have specified an uppercase character in line: " + line
 156  
                                 + " (character '" + character + "')");
 157  
                         }
 158  
                     }
 159  
                 }
 160  
 
 161  80
                 FilterInvocationDefinitionSourceMapping mapping = new FilterInvocationDefinitionSourceMapping();
 162  80
                 mapping.setUrl(name);
 163  
 
 164  80
                 String[] tokens = org.springframework.util.StringUtils
 165  
                         .commaDelimitedListToStringArray(value);
 166  
 
 167  183
                 for (int i = 0; i < tokens.length; i++) {
 168  103
                     mapping.addConfigAttribute(tokens[i].trim());
 169  
                 }
 170  
 
 171  80
                 mappings.add(mapping);
 172  80
             }
 173  36
             source.setMappings(mappings);
 174  
         }
 175  
 
 176  37
         setValue(source.getDecorated());
 177  37
     }
 178  
 }