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