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