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