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
27
28
29
30
31
32
33
34 package info.magnolia.cms.filters;
35
36 import info.magnolia.cms.util.ServletUtil;
37 import info.magnolia.cms.util.SimpleUrlPattern;
38 import info.magnolia.context.MgnlContext;
39 import info.magnolia.context.WebContext;
40
41 import java.util.ArrayList;
42 import java.util.Collection;
43 import java.util.Iterator;
44 import java.util.regex.Matcher;
45 import java.util.regex.Pattern;
46
47 import javax.servlet.http.HttpServletRequest;
48
49 import org.apache.commons.lang3.StringUtils;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53
54
55
56
57 public class Mapping {
58 private static final Logger log = LoggerFactory.getLogger(Mapping.class);
59
60 private static final String METACHARACTERS = "([\\^\\(\\)\\{\\}\\[\\]*$+.])";
61
62 protected static String escapeMetaCharacters(String str) {
63 return str.replaceAll(METACHARACTERS, "\\\\$1");
64 }
65
66 private Collection<Pattern> mappings = new ArrayList<Pattern>();
67
68 public MatchingResult match(HttpServletRequest request) {
69 Matcher matcher = findMatcher(request);
70 boolean matches = matcher != null;
71 int matchingEndPosition = determineMatchingEnd(matcher);
72 return new MatchingResult(matcher, matches, matchingEndPosition);
73 }
74
75
76
77
78
79 private int determineMatchingEnd(Matcher matcher) {
80 if (matcher == null) {
81 return -1;
82 }
83 if (matcher.groupCount() > 0) {
84 return matcher.end(1);
85 }
86 return matcher.end();
87 }
88
89 private Matcher findMatcher(HttpServletRequest request) {
90 String uri = null;
91 WebContext ctx = MgnlContext.getWebContextOrNull();
92 if (ctx != null) {
93 uri = ctx.getAggregationState().getCurrentURI();
94 }
95 if (uri == null) {
96
97 uri = ServletUtil.stripPathParameters(request.getRequestURI());
98 String contextPath = request.getContextPath();
99
100 if (uri.startsWith(contextPath + "/")) {
101 uri = uri.substring(contextPath.length());
102 }
103 }
104 return findMatcher(uri);
105 }
106
107 private Matcher findMatcher(String uri) {
108 for (Iterator<Pattern> iter = getMappings().iterator(); iter.hasNext(); ) {
109 final Matcher matcher = iter.next().matcher(uri);
110
111 if (matcher.find()) {
112 return matcher;
113 }
114 }
115
116 return null;
117 }
118
119 public Collection<Pattern> getMappings() {
120 return mappings;
121 }
122
123 public void setMappings(Collection<String> mappings) {
124 this.mappings.clear();
125 if (mappings != null) {
126 for (String mapping : mappings) {
127 this.addMapping(mapping);
128 }
129 }
130 }
131
132
133
134
135
136
137
138
139 public void addMapping(final String mapping) {
140 log.debug("Adding new mapping for {}", mapping);
141 final Pattern pattern = servletMappingToRegex(mapping);
142 mappings.add(pattern);
143 }
144
145 protected Pattern servletMappingToRegex(String mapping) {
146 final String pattern;
147
148
149
150 if (isDefaultMapping(mapping)) {
151
152
153 pattern = "^()(/)(" + SimpleUrlPattern.MULTIPLE_CHAR_PATTERN + ")";
154 } else if (isPathMapping(mapping)) {
155
156
157 final String mappingWithoutSuffix = StringUtils.removeEnd(mapping, "/*");
158 pattern = "^(" + escapeMetaCharacters(mappingWithoutSuffix) + ")(/)(" + SimpleUrlPattern.MULTIPLE_CHAR_PATTERN + ")";
159 } else if (isExtensionMapping(mapping)) {
160
161
162 final String regexedMapping = StringUtils.replace(mapping, "*.", SimpleUrlPattern.MULTIPLE_CHAR_PATTERN + "\\.");
163 pattern = "^(" + regexedMapping + ")$";
164 } else if (isRegexpMapping(mapping)) {
165 final String mappingWithoutPrefix = StringUtils.removeStart(mapping, "regex:");
166 pattern = "^(" + mappingWithoutPrefix + ")($|/)(" + SimpleUrlPattern.MULTIPLE_CHAR_PATTERN + ")";
167 } else {
168
169
170 pattern = "^(" + escapeMetaCharacters(mapping) + ")$";
171 }
172 return Pattern.compile(pattern);
173 }
174
175
176
177
178
179 private boolean isPathMapping(String mapping) {
180 return mapping.startsWith("/") && mapping.endsWith("/*");
181 }
182
183 private boolean isExtensionMapping(String mapping) {
184 return mapping.startsWith("*.");
185 }
186
187 private boolean isDefaultMapping(String mapping) {
188
189
190 return mapping.equals("/");
191 }
192
193 private boolean isRegexpMapping(String mapping) {
194 return mapping.startsWith("regex:");
195 }
196
197
198
199
200 public static class MatchingResult {
201 private final Matcher matcher;
202 private final boolean matches;
203 private final int matchingEndPosition;
204
205 public MatchingResult(Matcher matcher, boolean matches, int matchingEndPosition) {
206 this.matcher = matcher;
207 this.matches = matches;
208 this.matchingEndPosition = matchingEndPosition;
209 }
210
211 public Matcher getMatcher() {
212 return matcher;
213 }
214
215 public boolean isMatching() {
216 return matches;
217 }
218
219 public int getMatchingEndPosition() {
220 return matchingEndPosition;
221 }
222 }
223
224 }