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