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