1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package javax.security.jacc;
27
28 import java.util.Iterator;
29 import java.util.LinkedList;
30
31 import javax.servlet.http.HttpServletRequest;
32
33
34
35
36 final class URLPatternSpec {
37
38 private final String pattern;
39 private final URLPattern first;
40 private final LinkedList qualifiers = new LinkedList();
41
42 public URLPatternSpec(String name) {
43 if (name == null) throw new java.lang.IllegalArgumentException("URLPatternSpec cannot be null");
44 if (name.length() == 0) name = "/";
45
46 pattern = name;
47
48 String[] tokens = pattern.split(":", -1);
49 first = new URLPattern(tokens[0]);
50
51 URLPattern candidate;
52 for (int i = 1; i < tokens.length; i++) {
53 candidate = new URLPattern(tokens[i]);
54
55
56 if (candidate.matches(first)) {
57 throw new java.lang.IllegalArgumentException("Qualifier patterns in the URLPatternSpec cannot match the first URLPattern");
58 }
59
60 if (first.type == URLPattern.PATH_PREFIX) {
61
62
63
64
65
66 if (candidate.type == URLPattern.EXACT && !first.matches(candidate)) {
67 throw new java.lang.IllegalArgumentException("Exact qualifier patterns in the URLPatternSpec must be matched by the first URLPattern");
68 } else if (candidate.type == URLPattern.PATH_PREFIX
69 && !(first.matches(candidate)
70 && first.pattern.length() < candidate.pattern.length())) {
71 throw new java.lang.IllegalArgumentException("path-prefix qualifier patterns in the URLPatternSpec must be matched by, but different from, the first URLPattern");
72 } else if (candidate.type == URLPattern.EXTENSION) {
73 throw new java.lang.IllegalArgumentException("extension qualifier patterns in the URLPatternSpec are not allowed when the first URLPattern is path-prefix");
74 }
75 } else if (first.type == URLPattern.EXTENSION) {
76
77
78
79
80
81 if (candidate.type == URLPattern.EXACT) {
82 if (!first.matches(candidate)) {
83 throw new java.lang.IllegalArgumentException("Exact qualifier patterns in the URLPatternSpec must be matched when first URLPattern is an extension pattern");
84 }
85 } else if (candidate.type != URLPattern.PATH_PREFIX) {
86 throw new java.lang.IllegalArgumentException("Only exact and path-prefix qualifiers in the URLPatternSpec are allowed when first URLPattern is an extension pattern");
87 }
88 } else if (first.type == URLPattern.DEFAULT) {
89
90
91
92
93 if (candidate.type == URLPattern.DEFAULT) {
94
95 throw new java.lang.IllegalArgumentException("Qualifier patterns must not be default when first URLPattern is a default pattern");
96 }
97 } else if (first.type == URLPattern.EXACT) {
98
99
100
101
102 throw new java.lang.IllegalArgumentException("Qualifier patterns must not be present when first URLPattern is an exact pattern");
103 }
104
105 qualifiers.add(candidate);
106 }
107 }
108
109 public boolean equals(URLPatternSpec o) {
110 return implies(o) && o.implies(this);
111 }
112
113 public int hashCode() {
114 return pattern.hashCode();
115 }
116
117 public String getPatternSpec() {
118 return pattern;
119 }
120
121 public String toString() {
122 return pattern;
123 }
124
125 public boolean implies(URLPatternSpec p) {
126
127
128
129 if (!first.matches(p.first)) return false;
130
131
132
133
134 Iterator iter1 = qualifiers.iterator();
135 while (iter1.hasNext()) {
136 if (((URLPattern) iter1.next()).matches(p.first)) return false;
137 }
138
139
140
141
142
143
144 if (p.first.matches(first)) {
145 Iterator iter2 = p.qualifiers.iterator();
146
147 while (iter2.hasNext()) {
148 Iterator iter3 = qualifiers.iterator();
149 URLPattern test = (URLPattern) iter2.next();
150 boolean found = false;
151
152 while (iter3.hasNext()) {
153 if (test.matches((URLPattern) iter3.next())) {
154 found = true;
155 break;
156 }
157 }
158 if (!found) return false;
159 }
160 }
161
162 return true;
163 }
164
165 static String encodeColons(HttpServletRequest request) {
166 String result = request.getServletPath() + (request.getPathInfo() == null ? "" : request.getPathInfo());
167
168 if (result.indexOf(":") > -1) result = result.replaceAll(":", "%3A");
169
170 return result;
171 }
172
173 private class URLPattern {
174
175 public final static int EXACT = 0x0;
176 public final static int PATH_PREFIX = 0x1;
177 public final static int EXTENSION = 0x2;
178 public final static int DEFAULT = 0x4;
179
180 public int type;
181 public String pattern;
182
183 public URLPattern(String pat) {
184 if (pat == null) throw new java.lang.IllegalArgumentException("URLPattern cannot be null");
185 if (pat.length() == 0) throw new java.lang.IllegalArgumentException("URLPattern cannot be empty");
186
187 if (pat.equals("/") || pat.equals("/*")) {
188 type = DEFAULT;
189 } else if (pat.charAt(0) == '/' && pat.endsWith("/*")) {
190 type = PATH_PREFIX;
191 } else if (pat.charAt(0) == '*') {
192 type = EXTENSION;
193 } else {
194 type = EXACT;
195 }
196 pattern = pat;
197 }
198
199 public boolean matches(URLPattern p) {
200
201 String test = p.pattern;
202
203
204 if (pattern.equals(test)) return true;
205
206 switch (type) {
207
208
209
210
211
212
213 case PATH_PREFIX: {
214 int length = pattern.length() - 2;
215 if (length > test.length()) return false;
216
217 for (int i = 0; i < length; i++) {
218 if (pattern.charAt(i) != test.charAt(i)) return false;
219 }
220
221 if (test.length() == length) return true;
222 else if (test.charAt(length) != '/') return false;
223
224 return true;
225 }
226
227
228
229 case EXTENSION: {
230 return test.endsWith(pattern.substring(1));
231 }
232
233
234
235
236 case DEFAULT: {
237 return true;
238 }
239 }
240 return false;
241 }
242 }
243 }