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.SimpleUrlPattern;
37 import info.magnolia.context.MgnlContext;
38 import info.magnolia.context.WebContext;
39 import info.magnolia.objectfactory.Classes;
40
41 import java.io.IOException;
42 import java.util.Collection;
43 import java.util.Enumeration;
44 import java.util.Iterator;
45 import java.util.LinkedList;
46 import java.util.Map;
47 import java.util.regex.Matcher;
48 import java.util.regex.Pattern;
49
50 import javax.servlet.FilterChain;
51 import javax.servlet.FilterConfig;
52 import javax.servlet.Servlet;
53 import javax.servlet.ServletConfig;
54 import javax.servlet.ServletContext;
55 import javax.servlet.ServletException;
56 import javax.servlet.ServletRequest;
57 import javax.servlet.http.HttpServletRequest;
58 import javax.servlet.http.HttpServletRequestWrapper;
59 import javax.servlet.http.HttpServletResponse;
60
61 import org.apache.commons.lang.StringUtils;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65
66
67
68
69
70
71
72
73
74 public class ServletDispatchingFilter extends AbstractMgnlFilter {
75
76 private static final Logger log = LoggerFactory.getLogger(ServletDispatchingFilter.class);
77
78 private static final String METACHARACTERS = "([\\^\\(\\)\\{\\}\\[\\]*$+])";
79
80 private String servletName;
81
82 private String servletClass;
83
84 private Collection mappings;
85
86 private Map parameters;
87
88 private String comment;
89
90 private Servlet servlet;
91
92 public ServletDispatchingFilter() {
93 mappings = new LinkedList();
94 }
95
96 public String getName() {
97 return "Wrapper for " + servletName + " servlet";
98 }
99
100
101
102
103 public void init(final FilterConfig filterConfig) throws ServletException {
104 super.init(filterConfig);
105
106 if (servletClass != null) {
107 try {
108 servlet = Classes.newInstance(servletClass);
109 servlet.init(new WrappedServletConfig(servletName, filterConfig, parameters));
110 }
111 catch (Throwable e) {
112 log.error("Unable to load servlet " + servletClass + " : " + e.getMessage(), e);
113 }
114 }
115 }
116
117
118
119
120 public void destroy() {
121 if (servlet != null) {
122 servlet.destroy();
123 }
124 super.destroy();
125 }
126
127
128
129
130
131 public boolean bypasses(HttpServletRequest request) {
132 return determineMatchingEnd(request) < 0 || super.bypasses(request);
133 }
134
135
136
137
138
139 protected int determineMatchingEnd(HttpServletRequest request) {
140 final Matcher matcher = findMatcher(request);
141 if (matcher == null) {
142 return -1;
143 } else {
144 if (matcher.groupCount() > 0) {
145 return matcher.end(1);
146 } else {
147 return matcher.end();
148 }
149 }
150 }
151
152 protected Matcher findMatcher(HttpServletRequest request) {
153 WebContext ctx = MgnlContext.getWebContextOrNull();
154 final String uri;
155 if (ctx != null) {
156 uri = MgnlContext.getWebContext().getAggregationState().getCurrentURI();
157 } else {
158
159 uri = StringUtils.substringAfter(request.getRequestURI(), request.getContextPath());
160 }
161 return findMatcher(uri);
162 }
163
164 protected Matcher findMatcher(String uri) {
165 for (Iterator iter = mappings.iterator(); iter.hasNext();) {
166 final Matcher matcher = ((Pattern) iter.next()).matcher(uri);
167
168 if (matcher.find()) {
169 return matcher;
170 }
171 }
172
173 return null;
174 }
175
176
177
178
179
180 public void doFilter(final HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
181 log.debug("Dispatching to servlet {}", getServletClass());
182 final Matcher matcher = findMatcher(request);
183 servlet.service(new WrappedRequest(request, matcher), response);
184 }
185
186 public String getServletName() {
187 return servletName;
188 }
189
190 public void setServletName(String servletName) {
191 this.servletName = servletName;
192 }
193
194 public String getServletClass() {
195 return servletClass;
196 }
197
198 public void setServletClass(String servletClass) {
199 this.servletClass = servletClass;
200 }
201
202 public Collection getMappings() {
203 return mappings;
204 }
205
206 public void setMappings(Collection mappings) {
207 this.mappings = mappings;
208 }
209
210
211
212
213
214
215
216
217
218 public void addMapping(final String mapping) {
219 final String pattern;
220
221
222
223 if (isDefaultMapping(mapping)) {
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259 private boolean isPathMapping(String mapping) {
260 return mapping.startsWith("/") && mapping.endsWith("/*");
261 }
262
263 private boolean isExtensionMapping(String mapping) {
264 return mapping.startsWith("*.");
265 }
266
267 private boolean isDefaultMapping(String mapping) {
268
269 return mapping.equals("/");
270 }
271
272 private boolean isRegexpMapping(String mapping) {
273 return mapping.startsWith("regex:");
274 }
275
276 public Map getParameters() {
277 return parameters;
278 }
279
280 public void setParameters(Map parameters) {
281 this.parameters = parameters;
282 }
283
284 public String getComment() {
285 return comment;
286 }
287
288 public void setComment(String comment) {
289 this.comment = comment;
290 }
291
292 private final static class WrappedServletConfig implements ServletConfig {
293
294 private final String servletName;
295
296 private final FilterConfig filterConfig;
297
298 private final Map parameters;
299
300 public WrappedServletConfig(String servletName, FilterConfig filterConfig, Map parameters) {
301 this.servletName = servletName;
302 this.filterConfig = filterConfig;
303 this.parameters = parameters;
304 }
305
306 public String getInitParameter(String name) {
307 return (String) parameters.get(name);
308 }
309
310 public Enumeration getInitParameterNames() {
311 return new Enumeration() {
312
313 private Iterator iter = parameters.keySet().iterator();
314
315 public boolean hasMoreElements() {
316 return iter.hasNext();
317 }
318
319 public Object nextElement() {
320 return iter.next();
321 }
322 };
323 }
324
325 public ServletContext getServletContext() {
326 return filterConfig.getServletContext();
327 }
328
329 public String getServletName() {
330 return servletName;
331 }
332
333 }
334
335 private class WrappedRequest extends HttpServletRequestWrapper {
336
337 private Matcher matcher;
338
339
340
341
342
343
344
345 private boolean requestReplaced = false;
346
347
348
349
350
351 public WrappedRequest(HttpServletRequest request, Matcher matcher) {
352 super(request);
353 this.matcher = matcher;
354 }
355
356 public String getPathInfo() {
357 if (requestReplaced) {
358 return super.getPathInfo();
359 }
360 if (matcher.groupCount() > 2) {
361 String pathInfo = matcher.group(3);
362 if (pathInfo.equals("")) {
363 return null;
364 }
365
366 return (pathInfo.startsWith("/") ? pathInfo : "/" + pathInfo);
367 }
368 return null;
369 }
370
371 public String getServletPath() {
372 if (requestReplaced) {
373 return super.getServletPath();
374 }
375 return matcher.group(1);
376 }
377
378 public void setRequest(ServletRequest request) {
379 requestReplaced = true;
380 super.setRequest(request);
381 }
382
383 }
384 }