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