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 String old_uri=baseRequest.getRequestURI();
226 final String old_context_path=baseRequest.getContextPath();
227 final String old_servlet_path=baseRequest.getServletPath();
228 final String old_path_info=baseRequest.getPathInfo();
229 final String old_query=baseRequest.getQueryString();
230 final Attributes old_attr=baseRequest.getAttributes();
231 final DispatcherType old_type=baseRequest.getDispatcherType();
232 MultiMap<String> old_params=baseRequest.getParameters();
233
234 try
235 {
236 baseRequest.setDispatcherType(dispatch);
237
238 if (_named!=null)
239 _contextHandler.handle(_named,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
240 else
241 {
242
243
244 String query=_dQuery;
245 if (query!=null)
246 {
247
248 if (old_params==null)
249 {
250 baseRequest.extractParameters();
251 old_params=baseRequest.getParameters();
252 }
253
254 baseRequest.mergeQueryString(query);
255 }
256
257 ForwardAttributes attr = new ForwardAttributes(old_attr);
258
259
260
261
262
263 if (old_attr.getAttribute(FORWARD_REQUEST_URI) != null)
264 {
265 attr._pathInfo=(String)old_attr.getAttribute(FORWARD_PATH_INFO);
266 attr._query=(String)old_attr.getAttribute(FORWARD_QUERY_STRING);
267 attr._requestURI=(String)old_attr.getAttribute(FORWARD_REQUEST_URI);
268 attr._contextPath=(String)old_attr.getAttribute(FORWARD_CONTEXT_PATH);
269 attr._servletPath=(String)old_attr.getAttribute(FORWARD_SERVLET_PATH);
270 }
271 else
272 {
273 attr._pathInfo=old_path_info;
274 attr._query=old_query;
275 attr._requestURI=old_uri;
276 attr._contextPath=old_context_path;
277 attr._servletPath=old_servlet_path;
278 }
279
280 baseRequest.setRequestURI(_uri);
281 baseRequest.setContextPath(_contextHandler.getContextPath());
282 baseRequest.setAttributes(attr);
283
284 _contextHandler.handle(_path,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
285
286 if (baseRequest.getResponse().isWriting())
287 {
288 try {response.getWriter().close();}
289 catch(IllegalStateException e)
290 {
291 response.getOutputStream().close();
292 }
293 }
294 else
295 {
296 try {response.getOutputStream().close();}
297 catch(IllegalStateException e)
298 {
299 response.getWriter().close();
300 }
301 }
302 }
303 }
304 finally
305 {
306 baseRequest.setRequestURI(old_uri);
307 baseRequest.setContextPath(old_context_path);
308 baseRequest.setServletPath(old_servlet_path);
309 baseRequest.setPathInfo(old_path_info);
310 baseRequest.setAttributes(old_attr);
311 baseRequest.setParameters(old_params);
312 baseRequest.setQueryString(old_query);
313 baseRequest.setDispatcherType(old_type);
314 }
315 }
316
317
318
319
320
321 private class ForwardAttributes implements Attributes
322 {
323 final Attributes _attr;
324
325 String _requestURI;
326 String _contextPath;
327 String _servletPath;
328 String _pathInfo;
329 String _query;
330
331 ForwardAttributes(Attributes attributes)
332 {
333 _attr=attributes;
334 }
335
336
337 public Object getAttribute(String key)
338 {
339 if (Dispatcher.this._named==null)
340 {
341 if (key.equals(FORWARD_PATH_INFO))
342 return _pathInfo;
343 if (key.equals(FORWARD_REQUEST_URI))
344 return _requestURI;
345 if (key.equals(FORWARD_SERVLET_PATH))
346 return _servletPath;
347 if (key.equals(FORWARD_CONTEXT_PATH))
348 return _contextPath;
349 if (key.equals(FORWARD_QUERY_STRING))
350 return _query;
351 }
352
353 if (key.startsWith(__INCLUDE_PREFIX))
354 return null;
355
356 return _attr.getAttribute(key);
357 }
358
359
360 public Enumeration getAttributeNames()
361 {
362 HashSet set=new HashSet();
363 Enumeration e=_attr.getAttributeNames();
364 while(e.hasMoreElements())
365 {
366 String name=(String)e.nextElement();
367 if (!name.startsWith(__INCLUDE_PREFIX) &&
368 !name.startsWith(__FORWARD_PREFIX))
369 set.add(name);
370 }
371
372 if (_named==null)
373 {
374 if (_pathInfo!=null)
375 set.add(FORWARD_PATH_INFO);
376 else
377 set.remove(FORWARD_PATH_INFO);
378 set.add(FORWARD_REQUEST_URI);
379 set.add(FORWARD_SERVLET_PATH);
380 set.add(FORWARD_CONTEXT_PATH);
381 if (_query!=null)
382 set.add(FORWARD_QUERY_STRING);
383 else
384 set.remove(FORWARD_QUERY_STRING);
385 }
386
387 return Collections.enumeration(set);
388 }
389
390
391 public void setAttribute(String key, Object value)
392 {
393 if (_named==null && key.startsWith("javax.servlet."))
394 {
395 if (key.equals(FORWARD_PATH_INFO))
396 _pathInfo=(String)value;
397 else if (key.equals(FORWARD_REQUEST_URI))
398 _requestURI=(String)value;
399 else if (key.equals(FORWARD_SERVLET_PATH))
400 _servletPath=(String)value;
401 else if (key.equals(FORWARD_CONTEXT_PATH))
402 _contextPath=(String)value;
403 else if (key.equals(FORWARD_QUERY_STRING))
404 _query=(String)value;
405
406 else if (value==null)
407 _attr.removeAttribute(key);
408 else
409 _attr.setAttribute(key,value);
410 }
411 else if (value==null)
412 _attr.removeAttribute(key);
413 else
414 _attr.setAttribute(key,value);
415 }
416
417
418 @Override
419 public String toString()
420 {
421 return "FORWARD+"+_attr.toString();
422 }
423
424
425 public void clearAttributes()
426 {
427 throw new IllegalStateException();
428 }
429
430
431 public void removeAttribute(String name)
432 {
433 setAttribute(name,null);
434 }
435 }
436
437
438 private class IncludeAttributes implements Attributes
439 {
440 final Attributes _attr;
441
442 String _requestURI;
443 String _contextPath;
444 String _servletPath;
445 String _pathInfo;
446 String _query;
447
448 IncludeAttributes(Attributes attributes)
449 {
450 _attr=attributes;
451 }
452
453
454
455
456 public Object getAttribute(String key)
457 {
458 if (Dispatcher.this._named==null)
459 {
460 if (key.equals(INCLUDE_PATH_INFO)) return _pathInfo;
461 if (key.equals(INCLUDE_SERVLET_PATH)) return _servletPath;
462 if (key.equals(INCLUDE_CONTEXT_PATH)) return _contextPath;
463 if (key.equals(INCLUDE_QUERY_STRING)) return _query;
464 if (key.equals(INCLUDE_REQUEST_URI)) return _requestURI;
465 }
466 else if (key.startsWith(__INCLUDE_PREFIX))
467 return null;
468
469
470 return _attr.getAttribute(key);
471 }
472
473
474 public Enumeration getAttributeNames()
475 {
476 HashSet set=new HashSet();
477 Enumeration e=_attr.getAttributeNames();
478 while(e.hasMoreElements())
479 {
480 String name=(String)e.nextElement();
481 if (!name.startsWith(__INCLUDE_PREFIX))
482 set.add(name);
483 }
484
485 if (_named==null)
486 {
487 if (_pathInfo!=null)
488 set.add(INCLUDE_PATH_INFO);
489 else
490 set.remove(INCLUDE_PATH_INFO);
491 set.add(INCLUDE_REQUEST_URI);
492 set.add(INCLUDE_SERVLET_PATH);
493 set.add(INCLUDE_CONTEXT_PATH);
494 if (_query!=null)
495 set.add(INCLUDE_QUERY_STRING);
496 else
497 set.remove(INCLUDE_QUERY_STRING);
498 }
499
500 return Collections.enumeration(set);
501 }
502
503
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 public void clearAttributes()
533 {
534 throw new IllegalStateException();
535 }
536
537
538 public void removeAttribute(String name)
539 {
540 setAttribute(name,null);
541 }
542 }
543 }