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.CustomServletConfig;
37 import info.magnolia.objectfactory.ComponentProvider;
38
39 import java.io.IOException;
40 import java.util.Collection;
41 import java.util.Map;
42 import java.util.regex.Matcher;
43 import java.util.regex.Pattern;
44
45 import javax.inject.Inject;
46 import javax.servlet.FilterChain;
47 import javax.servlet.FilterConfig;
48 import javax.servlet.Servlet;
49 import javax.servlet.ServletException;
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletRequestWrapper;
52 import javax.servlet.http.HttpServletResponse;
53
54 import org.apache.commons.lang3.StringUtils;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
57
58 import com.google.common.collect.ImmutableList;
59
60
61
62
63
64
65 public class ServletDispatchingFilter extends AbstractMgnlFilter {
66
67 private static final Logger log = LoggerFactory.getLogger(ServletDispatchingFilter.class);
68
69 private final ComponentProvider componentProvider;
70
71 private final Mapping servletMapping;
72
73 private String servletName;
74
75 private Class<? extends Servlet> servletClass;
76
77 private Map parameters;
78
79 private String comment;
80
81 private Servlet servlet;
82
83 @Inject
84 public ServletDispatchingFilter(ComponentProvider componentProvider) {
85 this.componentProvider = componentProvider;
86 this.servletMapping = new ServletMapping();
87 }
88
89 @Override
90 public String getName() {
91 return "Wrapper for " + servletName + " servlet";
92 }
93
94
95
96
97 @Override
98 public void init(final FilterConfig filterConfig) throws ServletException {
99 super.init(filterConfig);
100
101 if (getServletClass() != null) {
102 try {
103 initializeServlet(filterConfig);
104 } catch (Throwable e) {
105 log.error("Unable to load servlet {} : {}", getServletClass(), e.getMessage(), e);
106 }
107 }
108 }
109
110 protected void initializeServlet(FilterConfig filterConfig) throws ClassNotFoundException, ServletException {
111 servlet = newServletInstance();
112 servlet.init(new CustomServletConfig(servletName, filterConfig.getServletContext(), parameters));
113 }
114
115 protected Servlet newServletInstance() throws ClassNotFoundException {
116 return componentProvider.newInstance(getServletClass());
117 }
118
119 protected Servlet getServlet() {
120 return servlet;
121 }
122
123 @Override
124 protected Mapping getMapping() {
125 return servletMapping;
126 }
127
128
129
130
131 @Override
132 public void destroy() {
133 if (servlet != null) {
134 servlet.destroy();
135 }
136 super.destroy();
137 }
138
139
140
141
142
143 @Override
144 public void doFilter(final HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
145 if (!getMapping().getMappings().isEmpty()) {
146 log.debug("Dispatching to servlet {}", getServletClass());
147 final Matcher matcher = getMapping().match(request).getMatcher();
148 servlet.service(new WrappedRequest(request, matcher), response);
149 } else {
150 log.debug("No mappings found to {}", getServletClass());
151 setEnabled(false);
152 }
153 }
154
155 public String getServletName() {
156 return servletName;
157 }
158
159 public void setServletName(String servletName) {
160 this.servletName = servletName;
161 }
162
163 public Class<? extends Servlet> getServletClass() {
164 return servletClass;
165 }
166
167 public void setServletClass(Class<? extends Servlet> servletClass) {
168 this.servletClass = servletClass;
169 }
170
171 public Map getParameters() {
172 return parameters;
173 }
174
175 public void setParameters(Map parameters) {
176 this.parameters = parameters;
177 }
178
179 public String getComment() {
180 return comment;
181 }
182
183 public void setComment(String comment) {
184 this.comment = comment;
185 }
186
187
188
189
190
191
192 private static class WrappedRequest extends HttpServletRequestWrapper {
193
194 private String originalRequestUri;
195 private String originalServletPath;
196 private String originalPathInfo;
197 private String originalQueryString;
198
199 private String newServletPath;
200 private String newPathInfo;
201
202
203
204
205
206 public WrappedRequest(HttpServletRequest request, Matcher matcher) {
207 super(request);
208
209 this.originalRequestUri = request.getRequestURI();
210 this.originalServletPath = request.getServletPath();
211 this.originalPathInfo = request.getPathInfo();
212 this.originalQueryString = request.getQueryString();
213
214 this.newServletPath = matcher.group(1);
215 if (matcher.groupCount() > 2) {
216 String pathInfo = matcher.group(3);
217
218 if (!pathInfo.equals("")) {
219
220 this.newPathInfo = (pathInfo.startsWith("/") ? pathInfo : "/" + pathInfo);
221 }
222 }
223 }
224
225 @Override
226 public String getPathInfo() {
227 String current = super.getPathInfo();
228 if (!StringUtils.equals(super.getRequestURI(), originalRequestUri)) {
229 return current;
230 }
231 if (!StringUtils.equals(super.getServletPath(), originalServletPath)) {
232 return current;
233 }
234 if (!StringUtils.equals(current, originalPathInfo)) {
235 return current;
236 }
237 if (!StringUtils.equals(super.getQueryString(), originalQueryString)) {
238 return current;
239 }
240 return newPathInfo;
241 }
242
243 @Override
244 public String getServletPath() {
245 String current = super.getServletPath();
246 if (!StringUtils.equals(super.getRequestURI(), originalRequestUri)) {
247 return current;
248 }
249 if (!StringUtils.equals(current, originalServletPath)) {
250 return current;
251 }
252 if (!StringUtils.equals(super.getPathInfo(), originalPathInfo)) {
253 return current;
254 }
255 if (!StringUtils.equals(super.getQueryString(), originalQueryString)) {
256 return current;
257 }
258 return newServletPath;
259 }
260 }
261
262
263
264
265
266 private class ServletMapping extends Mapping {
267 private Collection<Pattern> mergedMappings;
268 private String lastUsedSelfMapping;
269
270
271
272
273
274
275
276 @Override
277 public Collection<Pattern> getMappings() {
278 final Collection<Pattern> configuredMappings = super.getMappings();
279 if (!(getServlet() instanceof SelfMappingServlet)) {
280 return configuredMappings;
281 }
282
283 final String selfMapping = ((SelfMappingServlet) getServlet()).getSelfMappingPath();
284 if (selfMapping == null) {
285 return configuredMappings;
286 }
287
288 if (lastUsedSelfMapping == null || !lastUsedSelfMapping.equals(selfMapping)) {
289 final Pattern selfMappingPattern = servletMappingToRegex(selfMapping);
290
291 mergedMappings = ImmutableList.<Pattern>builder().add(selfMappingPattern).addAll(configuredMappings).build();
292 lastUsedSelfMapping = selfMapping;
293 }
294 return mergedMappings;
295 }
296
297
298 }
299 }