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