1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.HashSet;
25 import javax.servlet.DispatcherType;
26 import javax.servlet.RequestDispatcher;
27 import javax.servlet.ServletException;
28 import javax.servlet.ServletRequest;
29 import javax.servlet.ServletResponse;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32
33 import org.eclipse.jetty.server.handler.ContextHandler;
34 import org.eclipse.jetty.util.Attributes;
35 import org.eclipse.jetty.util.MultiMap;
36
37 public class Dispatcher implements RequestDispatcher
38 {
39
40 public final static String __INCLUDE_PREFIX="javax.servlet.include.";
41
42
43 public final static String __FORWARD_PREFIX="javax.servlet.forward.";
44
45 private final ContextHandler _contextHandler;
46 private final String _uri;
47 private final String _path;
48 private final String _query;
49 private final String _named;
50
51 public Dispatcher(ContextHandler contextHandler, String uri, String pathInContext, String query)
52 {
53 _contextHandler=contextHandler;
54 _uri=uri;
55 _path=pathInContext;
56 _query=query;
57 _named=null;
58 }
59
60 public Dispatcher(ContextHandler contextHandler, String name) throws IllegalStateException
61 {
62 _contextHandler=contextHandler;
63 _named=name;
64 _uri=null;
65 _path=null;
66 _query=null;
67 }
68
69 @Override
70 public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException
71 {
72 forward(request, response, DispatcherType.FORWARD);
73 }
74
75 public void error(ServletRequest request, ServletResponse response) throws ServletException, IOException
76 {
77 forward(request, response, DispatcherType.ERROR);
78 }
79
80 @Override
81 public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
82 {
83 Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
84
85 if (!(request instanceof HttpServletRequest))
86 request = new ServletRequestHttpWrapper(request);
87 if (!(response instanceof HttpServletResponse))
88 response = new ServletResponseHttpWrapper(response);
89
90 final DispatcherType old_type = baseRequest.getDispatcherType();
91 final Attributes old_attr=baseRequest.getAttributes();
92 final MultiMap<String> old_query_params=baseRequest.getQueryParameters();
93 try
94 {
95 baseRequest.setDispatcherType(DispatcherType.INCLUDE);
96 baseRequest.getResponse().include();
97 if (_named!=null)
98 {
99 _contextHandler.handle(_named,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
100 }
101 else
102 {
103 IncludeAttributes attr = new IncludeAttributes(old_attr);
104
105 attr._requestURI=_uri;
106 attr._contextPath=_contextHandler.getContextPath();
107 attr._servletPath=null;
108 attr._pathInfo=_path;
109 attr._query=_query;
110
111 if (_query!=null)
112 baseRequest.mergeQueryParameters(_query, false);
113 baseRequest.setAttributes(attr);
114
115 _contextHandler.handle(_path, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
116 }
117 }
118 finally
119 {
120 baseRequest.setAttributes(old_attr);
121 baseRequest.getResponse().included();
122 baseRequest.setQueryParameters(old_query_params);
123 baseRequest.resetParameters();
124 baseRequest.setDispatcherType(old_type);
125 }
126 }
127
128 protected void forward(ServletRequest request, ServletResponse response, DispatcherType dispatch) throws ServletException, IOException
129 {
130 Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
131 Response base_response=baseRequest.getResponse();
132 base_response.resetForForward();
133
134 if (!(request instanceof HttpServletRequest))
135 request = new ServletRequestHttpWrapper(request);
136 if (!(response instanceof HttpServletResponse))
137 response = new ServletResponseHttpWrapper(response);
138
139 final boolean old_handled=baseRequest.isHandled();
140 final String old_uri=baseRequest.getRequestURI();
141 final String old_context_path=baseRequest.getContextPath();
142 final String old_servlet_path=baseRequest.getServletPath();
143 final String old_path_info=baseRequest.getPathInfo();
144 final String old_query=baseRequest.getQueryString();
145 final MultiMap<String> old_query_params=baseRequest.getQueryParameters();
146 final Attributes old_attr=baseRequest.getAttributes();
147 final DispatcherType old_type=baseRequest.getDispatcherType();
148
149 try
150 {
151 baseRequest.setHandled(false);
152 baseRequest.setDispatcherType(dispatch);
153
154 if (_named!=null)
155 {
156 _contextHandler.handle(_named, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
157 }
158 else
159 {
160 ForwardAttributes attr = new ForwardAttributes(old_attr);
161
162
163
164
165
166 if (old_attr.getAttribute(FORWARD_REQUEST_URI) != null)
167 {
168 attr._pathInfo=(String)old_attr.getAttribute(FORWARD_PATH_INFO);
169 attr._query=(String)old_attr.getAttribute(FORWARD_QUERY_STRING);
170 attr._requestURI=(String)old_attr.getAttribute(FORWARD_REQUEST_URI);
171 attr._contextPath=(String)old_attr.getAttribute(FORWARD_CONTEXT_PATH);
172 attr._servletPath=(String)old_attr.getAttribute(FORWARD_SERVLET_PATH);
173 }
174 else
175 {
176 attr._pathInfo=old_path_info;
177 attr._query=old_query;
178 attr._requestURI=old_uri;
179 attr._contextPath=old_context_path;
180 attr._servletPath=old_servlet_path;
181 }
182
183 baseRequest.setRequestURI(_uri);
184 baseRequest.setContextPath(_contextHandler.getContextPath());
185 baseRequest.setServletPath(null);
186 baseRequest.setPathInfo(_uri);
187 if (_query!=null)
188 baseRequest.mergeQueryParameters(_query, true);
189 baseRequest.setAttributes(attr);
190
191 _contextHandler.handle(_path, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
192
193 if (!baseRequest.getHttpChannelState().isAsync())
194 commitResponse(response,baseRequest);
195 }
196 }
197 finally
198 {
199 baseRequest.setHandled(old_handled);
200 baseRequest.setRequestURI(old_uri);
201 baseRequest.setContextPath(old_context_path);
202 baseRequest.setServletPath(old_servlet_path);
203 baseRequest.setPathInfo(old_path_info);
204 baseRequest.setQueryString(old_query);
205 baseRequest.setQueryParameters(old_query_params);
206 baseRequest.resetParameters();
207 baseRequest.setAttributes(old_attr);
208 baseRequest.setDispatcherType(old_type);
209 }
210 }
211
212 private void commitResponse(ServletResponse response, Request baseRequest) throws IOException
213 {
214 if (baseRequest.getResponse().isWriting())
215 {
216 try
217 {
218 response.getWriter().close();
219 }
220 catch (IllegalStateException e)
221 {
222 response.getOutputStream().close();
223 }
224 }
225 else
226 {
227 try
228 {
229 response.getOutputStream().close();
230 }
231 catch (IllegalStateException e)
232 {
233 response.getWriter().close();
234 }
235 }
236 }
237
238 private class ForwardAttributes implements Attributes
239 {
240 final Attributes _attr;
241
242 String _requestURI;
243 String _contextPath;
244 String _servletPath;
245 String _pathInfo;
246 String _query;
247
248 ForwardAttributes(Attributes attributes)
249 {
250 _attr=attributes;
251 }
252
253
254 @Override
255 public Object getAttribute(String key)
256 {
257 if (Dispatcher.this._named==null)
258 {
259 if (key.equals(FORWARD_PATH_INFO))
260 return _pathInfo;
261 if (key.equals(FORWARD_REQUEST_URI))
262 return _requestURI;
263 if (key.equals(FORWARD_SERVLET_PATH))
264 return _servletPath;
265 if (key.equals(FORWARD_CONTEXT_PATH))
266 return _contextPath;
267 if (key.equals(FORWARD_QUERY_STRING))
268 return _query;
269 }
270
271 if (key.startsWith(__INCLUDE_PREFIX))
272 return null;
273
274 return _attr.getAttribute(key);
275 }
276
277 @Override
278 public Enumeration<String> getAttributeNames()
279 {
280 HashSet<String> set=new HashSet<>();
281 Enumeration<String> e=_attr.getAttributeNames();
282 while(e.hasMoreElements())
283 {
284 String name=e.nextElement();
285 if (!name.startsWith(__INCLUDE_PREFIX) &&
286 !name.startsWith(__FORWARD_PREFIX))
287 set.add(name);
288 }
289
290 if (_named==null)
291 {
292 if (_pathInfo!=null)
293 set.add(FORWARD_PATH_INFO);
294 else
295 set.remove(FORWARD_PATH_INFO);
296 set.add(FORWARD_REQUEST_URI);
297 set.add(FORWARD_SERVLET_PATH);
298 set.add(FORWARD_CONTEXT_PATH);
299 if (_query!=null)
300 set.add(FORWARD_QUERY_STRING);
301 else
302 set.remove(FORWARD_QUERY_STRING);
303 }
304
305 return Collections.enumeration(set);
306 }
307
308 @Override
309 public void setAttribute(String key, Object value)
310 {
311 if (_named==null && key.startsWith("javax.servlet."))
312 {
313 if (key.equals(FORWARD_PATH_INFO))
314 _pathInfo=(String)value;
315 else if (key.equals(FORWARD_REQUEST_URI))
316 _requestURI=(String)value;
317 else if (key.equals(FORWARD_SERVLET_PATH))
318 _servletPath=(String)value;
319 else if (key.equals(FORWARD_CONTEXT_PATH))
320 _contextPath=(String)value;
321 else if (key.equals(FORWARD_QUERY_STRING))
322 _query=(String)value;
323
324 else if (value==null)
325 _attr.removeAttribute(key);
326 else
327 _attr.setAttribute(key,value);
328 }
329 else if (value==null)
330 _attr.removeAttribute(key);
331 else
332 _attr.setAttribute(key,value);
333 }
334
335 @Override
336 public String toString()
337 {
338 return "FORWARD+"+_attr.toString();
339 }
340
341 @Override
342 public void clearAttributes()
343 {
344 throw new IllegalStateException();
345 }
346
347 @Override
348 public void removeAttribute(String name)
349 {
350 setAttribute(name,null);
351 }
352 }
353
354 private class IncludeAttributes implements Attributes
355 {
356 final Attributes _attr;
357
358 String _requestURI;
359 String _contextPath;
360 String _servletPath;
361 String _pathInfo;
362 String _query;
363
364 IncludeAttributes(Attributes attributes)
365 {
366 _attr=attributes;
367 }
368
369 @Override
370 public Object getAttribute(String key)
371 {
372 if (Dispatcher.this._named==null)
373 {
374 if (key.equals(INCLUDE_PATH_INFO)) return _pathInfo;
375 if (key.equals(INCLUDE_SERVLET_PATH)) return _servletPath;
376 if (key.equals(INCLUDE_CONTEXT_PATH)) return _contextPath;
377 if (key.equals(INCLUDE_QUERY_STRING)) return _query;
378 if (key.equals(INCLUDE_REQUEST_URI)) return _requestURI;
379 }
380 else if (key.startsWith(__INCLUDE_PREFIX))
381 return null;
382
383
384 return _attr.getAttribute(key);
385 }
386
387 @Override
388 public Enumeration<String> getAttributeNames()
389 {
390 HashSet<String> set=new HashSet<>();
391 Enumeration<String> e=_attr.getAttributeNames();
392 while(e.hasMoreElements())
393 {
394 String name=e.nextElement();
395 if (!name.startsWith(__INCLUDE_PREFIX))
396 set.add(name);
397 }
398
399 if (_named==null)
400 {
401 if (_pathInfo!=null)
402 set.add(INCLUDE_PATH_INFO);
403 else
404 set.remove(INCLUDE_PATH_INFO);
405 set.add(INCLUDE_REQUEST_URI);
406 set.add(INCLUDE_SERVLET_PATH);
407 set.add(INCLUDE_CONTEXT_PATH);
408 if (_query!=null)
409 set.add(INCLUDE_QUERY_STRING);
410 else
411 set.remove(INCLUDE_QUERY_STRING);
412 }
413
414 return Collections.enumeration(set);
415 }
416
417 @Override
418 public void setAttribute(String key, Object value)
419 {
420 if (_named==null && key.startsWith("javax.servlet."))
421 {
422 if (key.equals(INCLUDE_PATH_INFO)) _pathInfo=(String)value;
423 else if (key.equals(INCLUDE_REQUEST_URI)) _requestURI=(String)value;
424 else if (key.equals(INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
425 else if (key.equals(INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
426 else if (key.equals(INCLUDE_QUERY_STRING)) _query=(String)value;
427 else if (value==null)
428 _attr.removeAttribute(key);
429 else
430 _attr.setAttribute(key,value);
431 }
432 else if (value==null)
433 _attr.removeAttribute(key);
434 else
435 _attr.setAttribute(key,value);
436 }
437
438 @Override
439 public String toString()
440 {
441 return "INCLUDE+"+_attr.toString();
442 }
443
444 @Override
445 public void clearAttributes()
446 {
447 throw new IllegalStateException();
448 }
449
450 @Override
451 public void removeAttribute(String name)
452 {
453 setAttribute(name,null);
454 }
455 }
456 }