1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codehaus.mojo.wagon.shared;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 import java.util.StringTokenizer;
34 import java.util.Vector;
35
36
37
38
39 public final class SelectorUtils {
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public static boolean matchPatternStart(String pattern, String str) {
55 return matchPatternStart(pattern, str, true);
56 }
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 public static boolean matchPatternStart(String pattern, String str, boolean isCaseSensitive) {
74
75
76
77
78 if (str.startsWith("/") != pattern.startsWith("/")) {
79 return false;
80 }
81
82 Vector<?> patDirs = tokenizePath(pattern);
83 Vector<?> strDirs = tokenizePath(str);
84
85 int patIdxStart = 0;
86 int patIdxEnd = patDirs.size() - 1;
87 int strIdxStart = 0;
88 int strIdxEnd = strDirs.size() - 1;
89
90
91 while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
92 String patDir = (String) patDirs.elementAt(patIdxStart);
93 if (patDir.equals("**")) {
94 break;
95 }
96 if (!match(patDir, (String) strDirs.elementAt(strIdxStart), isCaseSensitive)) {
97 return false;
98 }
99 patIdxStart++;
100 strIdxStart++;
101 }
102
103 if (strIdxStart > strIdxEnd) {
104
105 return true;
106 } else if (patIdxStart > patIdxEnd) {
107
108 return false;
109 } else {
110
111
112 return true;
113 }
114 }
115
116
117
118
119
120
121
122
123
124
125
126 public static boolean matchPath(String pattern, String str) {
127 return matchPath(pattern, str, true);
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141
142 public static boolean matchPath(String pattern, String str, boolean isCaseSensitive) {
143
144
145
146
147 if (str.startsWith("/") != pattern.startsWith("/")) {
148 return false;
149 }
150
151 Vector<?> patDirs = tokenizePath(pattern);
152 Vector<?> strDirs = tokenizePath(str);
153
154 int patIdxStart = 0;
155 int patIdxEnd = patDirs.size() - 1;
156 int strIdxStart = 0;
157 int strIdxEnd = strDirs.size() - 1;
158
159
160 while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
161 String patDir = (String) patDirs.elementAt(patIdxStart);
162 if (patDir.equals("**")) {
163 break;
164 }
165 if (!match(patDir, (String) strDirs.elementAt(strIdxStart), isCaseSensitive)) {
166 patDirs = null;
167 strDirs = null;
168 return false;
169 }
170 patIdxStart++;
171 strIdxStart++;
172 }
173 if (strIdxStart > strIdxEnd) {
174
175 for (int i = patIdxStart; i <= patIdxEnd; i++) {
176 if (!patDirs.elementAt(i).equals("**")) {
177 patDirs = null;
178 strDirs = null;
179 return false;
180 }
181 }
182 return true;
183 } else {
184 if (patIdxStart > patIdxEnd) {
185
186 patDirs = null;
187 strDirs = null;
188 return false;
189 }
190 }
191
192
193 while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
194 String patDir = (String) patDirs.elementAt(patIdxEnd);
195 if (patDir.equals("**")) {
196 break;
197 }
198 if (!match(patDir, (String) strDirs.elementAt(strIdxEnd), isCaseSensitive)) {
199 patDirs = null;
200 strDirs = null;
201 return false;
202 }
203 patIdxEnd--;
204 strIdxEnd--;
205 }
206 if (strIdxStart > strIdxEnd) {
207
208 for (int i = patIdxStart; i <= patIdxEnd; i++) {
209 if (!patDirs.elementAt(i).equals("**")) {
210 patDirs = null;
211 strDirs = null;
212 return false;
213 }
214 }
215 return true;
216 }
217
218 while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
219 int patIdxTmp = -1;
220 for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
221 if (patDirs.elementAt(i).equals("**")) {
222 patIdxTmp = i;
223 break;
224 }
225 }
226 if (patIdxTmp == patIdxStart + 1) {
227
228 patIdxStart++;
229 continue;
230 }
231
232
233 int patLength = (patIdxTmp - patIdxStart - 1);
234 int strLength = (strIdxEnd - strIdxStart + 1);
235 int foundIdx = -1;
236 strLoop: for (int i = 0; i <= strLength - patLength; i++) {
237 for (int j = 0; j < patLength; j++) {
238 String subPat = (String) patDirs.elementAt(patIdxStart + j + 1);
239 String subStr = (String) strDirs.elementAt(strIdxStart + i + j);
240 if (!match(subPat, subStr, isCaseSensitive)) {
241 continue strLoop;
242 }
243 }
244
245 foundIdx = strIdxStart + i;
246 break;
247 }
248
249 if (foundIdx == -1) {
250 patDirs = null;
251 strDirs = null;
252 return false;
253 }
254
255 patIdxStart = patIdxTmp;
256 strIdxStart = foundIdx + patLength;
257 }
258
259 for (int i = patIdxStart; i <= patIdxEnd; i++) {
260 if (!patDirs.elementAt(i).equals("**")) {
261 patDirs = null;
262 strDirs = null;
263 return false;
264 }
265 }
266
267 return true;
268 }
269
270
271
272
273
274
275
276
277
278
279
280
281
282 public static boolean match(String pattern, String str) {
283 return match(pattern, str, true);
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 public static boolean match(String pattern, String str, boolean isCaseSensitive) {
302 char[] patArr = pattern.toCharArray();
303 char[] strArr = str.toCharArray();
304 int patIdxStart = 0;
305 int patIdxEnd = patArr.length - 1;
306 int strIdxStart = 0;
307 int strIdxEnd = strArr.length - 1;
308 char ch;
309
310 boolean containsStar = false;
311 for (int i = 0; i < patArr.length; i++) {
312 if (patArr[i] == '*') {
313 containsStar = true;
314 break;
315 }
316 }
317
318 if (!containsStar) {
319
320 if (patIdxEnd != strIdxEnd) {
321 return false;
322 }
323 for (int i = 0; i <= patIdxEnd; i++) {
324 ch = patArr[i];
325 if (ch != '?' && !equals(ch, strArr[i], isCaseSensitive)) {
326 return false;
327 }
328 }
329 return true;
330 }
331
332 if (patIdxEnd == 0) {
333 return true;
334 }
335
336
337 while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
338 if (ch != '?' && !equals(ch, strArr[strIdxStart], isCaseSensitive)) {
339 return false;
340 }
341 patIdxStart++;
342 strIdxStart++;
343 }
344 if (strIdxStart > strIdxEnd) {
345
346
347 for (int i = patIdxStart; i <= patIdxEnd; i++) {
348 if (patArr[i] != '*') {
349 return false;
350 }
351 }
352 return true;
353 }
354
355
356 while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
357 if (ch != '?' && !equals(ch, strArr[strIdxEnd], isCaseSensitive)) {
358 return false;
359 }
360 patIdxEnd--;
361 strIdxEnd--;
362 }
363 if (strIdxStart > strIdxEnd) {
364
365
366 for (int i = patIdxStart; i <= patIdxEnd; i++) {
367 if (patArr[i] != '*') {
368 return false;
369 }
370 }
371 return true;
372 }
373
374
375
376 while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
377 int patIdxTmp = -1;
378 for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
379 if (patArr[i] == '*') {
380 patIdxTmp = i;
381 break;
382 }
383 }
384 if (patIdxTmp == patIdxStart + 1) {
385
386 patIdxStart++;
387 continue;
388 }
389
390
391 int patLength = (patIdxTmp - patIdxStart - 1);
392 int strLength = (strIdxEnd - strIdxStart + 1);
393 int foundIdx = -1;
394 strLoop: for (int i = 0; i <= strLength - patLength; i++) {
395 for (int j = 0; j < patLength; j++) {
396 ch = patArr[patIdxStart + j + 1];
397 if (ch != '?' && !equals(ch, strArr[strIdxStart + i + j], isCaseSensitive)) {
398 continue strLoop;
399 }
400 }
401
402 foundIdx = strIdxStart + i;
403 break;
404 }
405
406 if (foundIdx == -1) {
407 return false;
408 }
409
410 patIdxStart = patIdxTmp;
411 strIdxStart = foundIdx + patLength;
412 }
413
414
415
416 for (int i = patIdxStart; i <= patIdxEnd; i++) {
417 if (patArr[i] != '*') {
418 return false;
419 }
420 }
421 return true;
422 }
423
424
425
426
427 private static boolean equals(char c1, char c2, boolean isCaseSensitive) {
428 if (c1 == c2) {
429 return true;
430 }
431 if (!isCaseSensitive) {
432
433 if (Character.toUpperCase(c1) == Character.toUpperCase(c2)
434 || Character.toLowerCase(c1) == Character.toLowerCase(c2)) {
435 return true;
436 }
437 }
438 return false;
439 }
440
441
442
443
444
445
446
447
448
449 public static Vector<String> tokenizePath(String path) {
450 Vector<String> ret = new Vector<String>();
451 StringTokenizer st = new StringTokenizer(path, "/");
452 while (st.hasMoreTokens()) {
453 ret.addElement(st.nextToken());
454 }
455 return ret;
456 }
457
458 }