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