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