1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package com.atlassian.seraph.util;
19
20 import java.io.Serializable;
21 import java.util.*;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class PathMapper implements Serializable
50 {
51 private Map mappings = new HashMap();
52 private List complexPaths = new ArrayList();
53 static String[] DEFAULT_KEYS = {"/", "*", "/*"};
54
55
56 public void put(String key, String pattern)
57 {
58 if (pattern == null)
59 {
60 removeMappingsForKey(key);
61 return;
62 }
63
64 mappings.put(pattern, key);
65 if (pattern.indexOf('?') > -1 || (pattern.indexOf("*") > -1 && pattern.length() > 1))
66 {
67 complexPaths.add(pattern);
68 }
69 }
70
71 private void removeMappingsForKey(String key)
72 {
73 for (Iterator it = mappings.entrySet().iterator(); it.hasNext();)
74 {
75 Map.Entry entry = (Map.Entry) it.next();
76 if (entry.getValue().equals(key))
77 {
78 complexPaths.remove(entry.getKey());
79 it.remove();
80 }
81 }
82 }
83
84
85
86 public String get(String path)
87 {
88 if (path == null) path = "/";
89 String mapped = findKey(path, mappings, complexPaths);
90 if (mapped == null) return null;
91 return (String) mappings.get(mapped);
92 }
93
94
95
96 public Collection getAll(String path)
97 {
98 if (path == null) path = "/";
99
100 List matches = new ArrayList();
101
102
103 String exactKey = findExactKey(path, mappings);
104
105 if (exactKey != null)
106 matches.add(mappings.get(exactKey));
107
108
109 for (Iterator iterator = findComplexKeys(path, complexPaths).iterator(); iterator.hasNext();)
110 {
111 String mapped = (String) iterator.next();
112 matches.add(mappings.get(mapped));
113 }
114
115
116 for (Iterator iterator = findDefaultKeys(mappings).iterator(); iterator.hasNext();)
117 {
118 String mapped = (String) iterator.next();
119 matches.add(mappings.get(mapped));
120 }
121
122 return matches;
123 }
124
125
126
127 private static String findKey(String path, Map mappings, List keys)
128 {
129 String result = findExactKey(path, mappings);
130 if (result == null) result = findComplexKey(path, keys);
131 if (result == null) result = findDefaultKey(mappings);
132 return result;
133 }
134
135
136
137 private static String findExactKey(String path, Map mappings)
138 {
139 if (mappings.containsKey(path)) return path;
140 return null;
141 }
142
143
144
145 private static String findComplexKey(String path, List complexPaths)
146 {
147 int size = complexPaths.size();
148 for (int i = 0; i < size; i++)
149 {
150 String key = (String) complexPaths.get(i);
151 if (match(key, path, false))
152 {
153 return key;
154 }
155 }
156 return null;
157 }
158
159
160 private static Collection findComplexKeys(String path, List complexPaths)
161 {
162 int size = complexPaths.size();
163 List matches = new ArrayList();
164 for (int i = 0; i < size; i++)
165 {
166 String key = (String) complexPaths.get(i);
167 if (match(key, path, false))
168 {
169 matches.add(key);
170 }
171 }
172 return matches;
173 }
174
175
176 private static String findDefaultKey(Map mappings)
177 {
178 for (int i = 0; i < DEFAULT_KEYS.length; i++)
179 {
180 if (mappings.containsKey(DEFAULT_KEYS[i])) return DEFAULT_KEYS[i];
181 }
182 return null;
183 }
184
185
186 private static Collection findDefaultKeys(Map mappings)
187 {
188 List matches = new ArrayList();
189
190 for (int i = 0; i < DEFAULT_KEYS.length; i++)
191 {
192 if (mappings.containsKey(DEFAULT_KEYS[i]))
193 matches.add(DEFAULT_KEYS[i]);
194 }
195
196 return matches;
197 }
198
199
200 private static boolean match(String pattern, String str, boolean isCaseSensitive)
201 {
202 char[] patArr = pattern.toCharArray();
203 char[] strArr = str.toCharArray();
204 int patIdxStart = 0;
205 int patIdxEnd = patArr.length - 1;
206 int strIdxStart = 0;
207 int strIdxEnd = strArr.length - 1;
208 char ch;
209
210 boolean containsStar = false;
211 for (int i = 0; i < patArr.length; i++)
212 {
213 if (patArr[i] == '*')
214 {
215 containsStar = true;
216 break;
217 }
218 }
219
220 if (!containsStar)
221 {
222
223 if (patIdxEnd != strIdxEnd)
224 {
225 return false;
226 }
227 for (int i = 0; i <= patIdxEnd; i++)
228 {
229 ch = patArr[i];
230 if (ch != '?')
231 {
232 if (isCaseSensitive && ch != strArr[i])
233 {
234 return false;
235 }
236 if (!isCaseSensitive && Character.toUpperCase(ch) !=
237 Character.toUpperCase(strArr[i]))
238 {
239 return false;
240 }
241 }
242 }
243 return true;
244 }
245
246 if (patIdxEnd == 0)
247 {
248 return true;
249 }
250
251
252 while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd)
253 {
254 if (ch != '?')
255 {
256 if (isCaseSensitive && ch != strArr[strIdxStart])
257 {
258 return false;
259 }
260 if (!isCaseSensitive && Character.toUpperCase(ch) !=
261 Character.toUpperCase(strArr[strIdxStart]))
262 {
263 return false;
264 }
265 }
266 patIdxStart++;
267 strIdxStart++;
268 }
269 if (strIdxStart > strIdxEnd)
270 {
271
272
273 for (int i = patIdxStart; i <= patIdxEnd; i++)
274 {
275 if (patArr[i] != '*')
276 {
277 return false;
278 }
279 }
280 return true;
281 }
282
283
284 while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd)
285 {
286 if (ch != '?')
287 {
288 if (isCaseSensitive && ch != strArr[strIdxEnd])
289 {
290 return false;
291 }
292 if (!isCaseSensitive && Character.toUpperCase(ch) !=
293 Character.toUpperCase(strArr[strIdxEnd]))
294 {
295 return false;
296 }
297 }
298 patIdxEnd--;
299 strIdxEnd--;
300 }
301 if (strIdxStart > strIdxEnd)
302 {
303
304
305 for (int i = patIdxStart; i <= patIdxEnd; i++)
306 {
307 if (patArr[i] != '*')
308 {
309 return false;
310 }
311 }
312 return true;
313 }
314
315
316
317 while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd)
318 {
319 int patIdxTmp = -1;
320 for (int i = patIdxStart + 1; i <= patIdxEnd; i++)
321 {
322 if (patArr[i] == '*')
323 {
324 patIdxTmp = i;
325 break;
326 }
327 }
328 if (patIdxTmp == patIdxStart + 1)
329 {
330
331 patIdxStart++;
332 continue;
333 }
334
335
336 int patLength = (patIdxTmp - patIdxStart - 1);
337 int strLength = (strIdxEnd - strIdxStart + 1);
338 int foundIdx = -1;
339 strLoop:
340 for (int i = 0; i <= strLength - patLength; i++)
341 {
342 for (int j = 0; j < patLength; j++)
343 {
344 ch = patArr[patIdxStart + j + 1];
345 if (ch != '?')
346 {
347 if (isCaseSensitive && ch != strArr[strIdxStart + i + j])
348 {
349 continue strLoop;
350 }
351 if (!isCaseSensitive && Character.toUpperCase(ch) !=
352 Character.toUpperCase(strArr[strIdxStart + i + j]))
353 {
354 continue strLoop;
355 }
356 }
357 }
358
359 foundIdx = strIdxStart + i;
360 break;
361 }
362
363 if (foundIdx == -1)
364 {
365 return false;
366 }
367
368 patIdxStart = patIdxTmp;
369 strIdxStart = foundIdx + patLength;
370 }
371
372
373
374 for (int i = patIdxStart; i <= patIdxEnd; i++)
375 {
376 if (patArr[i] != '*')
377 {
378 return false;
379 }
380 }
381 return true;
382 }
383
384 public String toString()
385 {
386 StringBuffer sb = new StringBuffer();
387 sb.append("Mappings:\n");
388 for (Iterator iterator = mappings.keySet().iterator(); iterator.hasNext();)
389 {
390 String key = (String) iterator.next();
391 sb.append(key + "=" + (String) mappings.get(key) + "\n");
392 }
393 sb.append("Complex Paths:\n");
394 for (Iterator iterator = complexPaths.iterator(); iterator.hasNext();)
395 {
396 String path = (String) iterator.next();
397 sb.append(path + "\n");
398 }
399
400 return sb.toString();
401 }
402 }