1
2
3
4
5
6
7
8
9
10
11
12
13
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.PathMatcher;
24 import org.springframework.util.AntPathMatcher;
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
35 * associated with different HTTP request URL Apache Ant path-based patterns.
36 *
37 * <P>
38 * Apache Ant path expressions are used to match a HTTP request URL against a
39 * <code>ConfigAttributeDefinition</code>.
40 * </p>
41 *
42 * <p>
43 * The order of registering the Ant paths using the {@link
44 * #addSecureUrl(String, ConfigAttributeDefinition)} is very important. The
45 * system will identify the <b>first</b> matching path for a given HTTP URL.
46 * It will not proceed to evaluate later paths if a match has already been
47 * found. Accordingly, the most specific paths should be registered first,
48 * with the most general paths registered last.
49 * </p>
50 *
51 * <P>
52 * If no registered paths match the HTTP URL, <code>null</code> is returned.
53 * </p>
54 */
55 public class PathBasedFilterInvocationDefinitionMap
56 extends AbstractFilterInvocationDefinitionSource
57 implements FilterInvocationDefinitionMap {
58
59
60 private static final Log logger = LogFactory.getLog(PathBasedFilterInvocationDefinitionMap.class);
61
62
63
64 private List requestMap = new Vector();
65 private boolean convertUrlToLowercaseBeforeComparison = false;
66 private PathMatcher pathMatcher = new AntPathMatcher();
67
68
69
70 public Iterator getConfigAttributeDefinitions() {
71 Set set = new HashSet();
72 Iterator iter = requestMap.iterator();
73
74 while (iter.hasNext()) {
75 EntryHolder entryHolder = (EntryHolder) iter.next();
76 set.add(entryHolder.getConfigAttributeDefinition());
77 }
78
79 return set.iterator();
80 }
81
82 public void setConvertUrlToLowercaseBeforeComparison(
83 boolean convertUrlToLowercaseBeforeComparison) {
84 this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;
85 }
86
87 public boolean isConvertUrlToLowercaseBeforeComparison() {
88 return convertUrlToLowercaseBeforeComparison;
89 }
90
91 public int getMapSize() {
92 return this.requestMap.size();
93 }
94
95 public void addSecureUrl(String antPath, ConfigAttributeDefinition attr) {
96 requestMap.add(new EntryHolder(antPath, attr));
97
98 if (logger.isDebugEnabled()) {
99 logger.debug("Added Ant path: " + antPath + "; attributes: " + attr);
100 }
101 }
102
103 public ConfigAttributeDefinition lookupAttributes(String url) {
104 Iterator iter = requestMap.iterator();
105
106 if (convertUrlToLowercaseBeforeComparison) {
107 url = url.toLowerCase();
108
109 if (logger.isDebugEnabled()) {
110 logger.debug("Converted URL to lowercase, from: '" + url
111 + "'; to: '" + url + "'");
112 }
113 }
114
115 while (iter.hasNext()) {
116 EntryHolder entryHolder = (EntryHolder) iter.next();
117
118 boolean matched = pathMatcher.match(entryHolder.getAntPath(), url);
119
120 if (logger.isDebugEnabled()) {
121 logger.debug("Candidate is: '" + url + "'; pattern is "
122 + entryHolder.getAntPath() + "; matched=" + matched);
123 }
124
125 if (matched) {
126 return entryHolder.getConfigAttributeDefinition();
127 }
128 }
129
130 return null;
131 }
132
133
134
135 protected class EntryHolder {
136 private ConfigAttributeDefinition configAttributeDefinition;
137 private String antPath;
138
139 public EntryHolder(String antPath, ConfigAttributeDefinition attr) {
140 this.antPath = antPath;
141 this.configAttributeDefinition = attr;
142 }
143
144 protected EntryHolder() {
145 throw new IllegalArgumentException("Cannot use default constructor");
146 }
147
148 public String getAntPath() {
149 return antPath;
150 }
151
152 public ConfigAttributeDefinition getConfigAttributeDefinition() {
153 return configAttributeDefinition;
154 }
155 }
156 }