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