1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.util;
18
19 import java.util.LinkedList;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24
25
26
27
28
29
30
31
32
33
34
35
36 class AntPathStringMatcher {
37
38 private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}");
39
40 private static final String DEFAULT_VARIABLE_PATTERN = "(.*)";
41
42 private final Pattern pattern;
43
44 private final List<String> variableNames = new LinkedList<String>();
45
46
47
48 AntPathStringMatcher(String pattern) {
49 this.pattern = createPattern(pattern);
50 }
51
52 private Pattern createPattern(String pattern) {
53 StringBuilder patternBuilder = new StringBuilder();
54 Matcher m = GLOB_PATTERN.matcher(pattern);
55 int end = 0;
56 while (m.find()) {
57 patternBuilder.append(quote(pattern, end, m.start()));
58 String match = m.group();
59 if ("?".equals(match)) {
60 patternBuilder.append('.');
61 }
62 else if ("*".equals(match)) {
63 patternBuilder.append(".*");
64 }
65 else if (match.startsWith("{") && match.endsWith("}")) {
66 int colonIdx = match.indexOf(':');
67 if (colonIdx == -1) {
68 patternBuilder.append(DEFAULT_VARIABLE_PATTERN);
69 variableNames.add(m.group(1));
70 }
71 else {
72 String variablePattern = match.substring(colonIdx + 1, match.length() - 1);
73 patternBuilder.append('(');
74 patternBuilder.append(variablePattern);
75 patternBuilder.append(')');
76 String variableName = match.substring(1, colonIdx);
77 variableNames.add(variableName);
78 }
79 }
80 end = m.end();
81 }
82 patternBuilder.append(quote(pattern, end, pattern.length()));
83 return Pattern.compile(patternBuilder.toString());
84 }
85
86 private String quote(String s, int start, int end) {
87 if (start == end) {
88 return "";
89 }
90 return Pattern.quote(s.substring(start, end));
91 }
92
93
94
95
96
97
98 public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {
99 Matcher matcher = pattern.matcher(str);
100 if (matcher.matches()) {
101 if (uriTemplateVariables != null) {
102
103 Assert.isTrue(variableNames.size() == matcher.groupCount(),
104 "The number of capturing groups in the pattern segment " + pattern +
105 " does not match the number of URI template variables it defines, which can occur if " +
106 " capturing groups are used in a URI template regex. Use non-capturing groups instead.");
107 for (int i = 1; i <= matcher.groupCount(); i++) {
108 String name = this.variableNames.get(i - 1);
109 String value = matcher.group(i);
110 uriTemplateVariables.put(name, value);
111 }
112 }
113 return true;
114 }
115 else {
116 return false;
117 }
118 }
119
120 }