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):HttpConnection.getCurrentConnection().getRequest();
134 request.removeAttribute(__JSP_FILE);
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):HttpConnection.getCurrentConnection().getRequest();
215 Response base_response=baseRequest.getResponse();
216 response.resetBuffer();
217 base_response.fwdReset();
218 request.removeAttribute(__JSP_FILE);
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.getResponse().isWriting())
291 {
292 try {response.getWriter().close();}
293 catch(IllegalStateException e)
294 {
295 response.getOutputStream().close();
296 }
297 }
298 else
299 {
300 try {response.getOutputStream().close();}
301 catch(IllegalStateException e)
302 {
303 response.getWriter().close();
304 }
305 }
306 }
307 }
308 finally
309 {
310 baseRequest.setHandled(old_handled);
311 baseRequest.setRequestURI(old_uri);
312 baseRequest.setContextPath(old_context_path);
313 baseRequest.setServletPath(old_servlet_path);
314 baseRequest.setPathInfo(old_path_info);
315 baseRequest.setAttributes(old_attr);
316 baseRequest.setParameters(old_params);
317 baseRequest.setQueryString(old_query);
318 baseRequest.setDispatcherType(old_type);
319 }
320 }
321
322
323
324
325
326 private class ForwardAttributes implements Attributes
327 {
328 final Attributes _attr;
329
330 String _requestURI;
331 String _contextPath;
332 String _servletPath;
333 String _pathInfo;
334 String _query;
335
336 ForwardAttributes(Attributes attributes)
337 {
338 _attr=attributes;
339 }
340
341
342 public Object getAttribute(String key)
343 {
344 if (Dispatcher.this._named==null)
345 {
346 if (key.equals(FORWARD_PATH_INFO))
347 return _pathInfo;
348 if (key.equals(FORWARD_REQUEST_URI))
349 return _requestURI;
350 if (key.equals(FORWARD_SERVLET_PATH))
351 return _servletPath;
352 if (key.equals(FORWARD_CONTEXT_PATH))
353 return _contextPath;
354 if (key.equals(FORWARD_QUERY_STRING))
355 return _query;
356 }
357
358 if (key.startsWith(__INCLUDE_PREFIX))
359 return null;
360
361 return _attr.getAttribute(key);
362 }
363
364
365 public Enumeration getAttributeNames()
366 {
367 HashSet set=new HashSet();
368 Enumeration e=_attr.getAttributeNames();
369 while(e.hasMoreElements())
370 {
371 String name=(String)e.nextElement();
372 if (!name.startsWith(__INCLUDE_PREFIX) &&
373 !name.startsWith(__FORWARD_PREFIX))
374 set.add(name);
375 }
376
377 if (_named==null)
378 {
379 if (_pathInfo!=null)
380 set.add(FORWARD_PATH_INFO);
381 else
382 set.remove(FORWARD_PATH_INFO);
383 set.add(FORWARD_REQUEST_URI);
384 set.add(FORWARD_SERVLET_PATH);
385 set.add(FORWARD_CONTEXT_PATH);
386 if (_query!=null)
387 set.add(FORWARD_QUERY_STRING);
388 else
389 set.remove(FORWARD_QUERY_STRING);
390 }
391
392 return Collections.enumeration(set);
393 }
394
395
396 public void setAttribute(String key, Object value)
397 {
398 if (_named==null && key.startsWith("javax.servlet."))
399 {
400 if (key.equals(FORWARD_PATH_INFO))
401 _pathInfo=(String)value;
402 else if (key.equals(FORWARD_REQUEST_URI))
403 _requestURI=(String)value;
404 else if (key.equals(FORWARD_SERVLET_PATH))
405 _servletPath=(String)value;
406 else if (key.equals(FORWARD_CONTEXT_PATH))
407 _contextPath=(String)value;
408 else if (key.equals(FORWARD_QUERY_STRING))
409 _query=(String)value;
410
411 else if (value==null)
412 _attr.removeAttribute(key);
413 else
414 _attr.setAttribute(key,value);
415 }
416 else if (value==null)
417 _attr.removeAttribute(key);
418 else
419 _attr.setAttribute(key,value);
420 }
421
422
423 @Override
424 public String toString()
425 {
426 return "FORWARD+"+_attr.toString();
427 }
428
429
430 public void clearAttributes()
431 {
432 throw new IllegalStateException();
433 }
434
435
436 public void removeAttribute(String name)
437 {
438 setAttribute(name,null);
439 }
440 }
441
442
443 private class IncludeAttributes implements Attributes
444 {
445 final Attributes _attr;
446
447 String _requestURI;
448 String _contextPath;
449 String _servletPath;
450 String _pathInfo;
451 String _query;
452
453 IncludeAttributes(Attributes attributes)
454 {
455 _attr=attributes;
456 }
457
458
459
460
461 public Object getAttribute(String key)
462 {
463 if (Dispatcher.this._named==null)
464 {
465 if (key.equals(INCLUDE_PATH_INFO)) return _pathInfo;
466 if (key.equals(INCLUDE_SERVLET_PATH)) return _servletPath;
467 if (key.equals(INCLUDE_CONTEXT_PATH)) return _contextPath;
468 if (key.equals(INCLUDE_QUERY_STRING)) return _query;
469 if (key.equals(INCLUDE_REQUEST_URI)) return _requestURI;
470 }
471 else if (key.startsWith(__INCLUDE_PREFIX))
472 return null;
473
474
475 return _attr.getAttribute(key);
476 }
477
478
479 public Enumeration getAttributeNames()
480 {
481 HashSet set=new HashSet();
482 Enumeration e=_attr.getAttributeNames();
483 while(e.hasMoreElements())
484 {
485 String name=(String)e.nextElement();
486 if (!name.startsWith(__INCLUDE_PREFIX))
487 set.add(name);
488 }
489
490 if (_named==null)
491 {
492 if (_pathInfo!=null)
493 set.add(INCLUDE_PATH_INFO);
494 else
495 set.remove(INCLUDE_PATH_INFO);
496 set.add(INCLUDE_REQUEST_URI);
497 set.add(INCLUDE_SERVLET_PATH);
498 set.add(INCLUDE_CONTEXT_PATH);
499 if (_query!=null)
500 set.add(INCLUDE_QUERY_STRING);
501 else
502 set.remove(INCLUDE_QUERY_STRING);
503 }
504
505 return Collections.enumeration(set);
506 }
507
508
509 public void setAttribute(String key, Object value)
510 {
511 if (_named==null && key.startsWith("javax.servlet."))
512 {
513 if (key.equals(INCLUDE_PATH_INFO)) _pathInfo=(String)value;
514 else if (key.equals(INCLUDE_REQUEST_URI)) _requestURI=(String)value;
515 else if (key.equals(INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
516 else if (key.equals(INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
517 else if (key.equals(INCLUDE_QUERY_STRING)) _query=(String)value;
518 else if (value==null)
519 _attr.removeAttribute(key);
520 else
521 _attr.setAttribute(key,value);
522 }
523 else if (value==null)
524 _attr.removeAttribute(key);
525 else
526 _attr.setAttribute(key,value);
527 }
528
529
530 @Override
531 public String toString()
532 {
533 return "INCLUDE+"+_attr.toString();
534 }
535
536
537 public void clearAttributes()
538 {
539 throw new IllegalStateException();
540 }
541
542
543 public void removeAttribute(String name)
544 {
545 setAttribute(name,null);
546 }
547 }
548 }