1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty.servlet;
16
17 import java.io.IOException;
18 import java.util.Collections;
19 import java.util.Enumeration;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.Map;
23
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.mortbay.jetty.Handler;
32 import org.mortbay.jetty.HttpConnection;
33 import org.mortbay.jetty.Request;
34 import org.mortbay.jetty.handler.ContextHandler;
35 import org.mortbay.util.Attributes;
36 import org.mortbay.util.LazyList;
37 import org.mortbay.util.MultiMap;
38 import org.mortbay.util.UrlEncoded;
39
40
41
42
43
44
45 public class Dispatcher implements RequestDispatcher
46 {
47
48 public final static String __INCLUDE_JETTY="org.mortbay.jetty.included";
49 public final static String __INCLUDE_PREFIX="javax.servlet.include.";
50 public final static String __INCLUDE_REQUEST_URI= "javax.servlet.include.request_uri";
51 public final static String __INCLUDE_CONTEXT_PATH= "javax.servlet.include.context_path";
52 public final static String __INCLUDE_SERVLET_PATH= "javax.servlet.include.servlet_path";
53 public final static String __INCLUDE_PATH_INFO= "javax.servlet.include.path_info";
54 public final static String __INCLUDE_QUERY_STRING= "javax.servlet.include.query_string";
55
56
57 public final static String __FORWARD_JETTY="org.mortbay.jetty.forwarded";
58 public final static String __FORWARD_PREFIX="javax.servlet.forward.";
59 public final static String __FORWARD_REQUEST_URI= "javax.servlet.forward.request_uri";
60 public final static String __FORWARD_CONTEXT_PATH= "javax.servlet.forward.context_path";
61 public final static String __FORWARD_SERVLET_PATH= "javax.servlet.forward.servlet_path";
62 public final static String __FORWARD_PATH_INFO= "javax.servlet.forward.path_info";
63 public final static String __FORWARD_QUERY_STRING= "javax.servlet.forward.query_string";
64
65
66 public final static String __JSP_FILE="org.apache.catalina.jsp_file";
67
68
69
70
71 public static int type(String type)
72 {
73 if ("request".equalsIgnoreCase(type))
74 return Handler.REQUEST;
75 if ("forward".equalsIgnoreCase(type))
76 return Handler.FORWARD;
77 if ("include".equalsIgnoreCase(type))
78 return Handler.INCLUDE;
79 if ("error".equalsIgnoreCase(type))
80 return Handler.ERROR;
81 throw new IllegalArgumentException(type);
82 }
83
84
85
86 private ContextHandler _contextHandler;
87 private String _uri;
88 private String _path;
89 private String _dQuery;
90 private String _named;
91
92
93
94
95
96
97
98
99 public Dispatcher(ContextHandler contextHandler, String uri, String pathInContext, String query)
100 {
101 _contextHandler=contextHandler;
102 _uri=uri;
103 _path=pathInContext;
104 _dQuery=query;
105 }
106
107
108
109
110
111
112
113 public Dispatcher(ContextHandler contextHandler,String name)
114 throws IllegalStateException
115 {
116 _contextHandler=contextHandler;
117 _named=name;
118 }
119
120
121
122
123
124 public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException
125 {
126 forward(request, response, Handler.FORWARD);
127 }
128
129
130
131
132
133 public void error(ServletRequest request, ServletResponse response) throws ServletException, IOException
134 {
135 forward(request, response, Handler.ERROR);
136 }
137
138
139
140
141
142 public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
143 {
144 Request base_request=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
145 request.removeAttribute(__JSP_FILE);
146
147
148
149 Attributes old_attr=base_request.getAttributes();
150 MultiMap old_params=base_request.getParameters();
151 try
152 {
153 base_request.getConnection().include();
154 if (_named!=null)
155 _contextHandler.handle(_named, (HttpServletRequest)request, (HttpServletResponse)response, Handler.INCLUDE);
156 else
157 {
158 String query=_dQuery;
159
160 if (query!=null)
161 {
162 MultiMap parameters=new MultiMap();
163 UrlEncoded.decodeTo(query,parameters,request.getCharacterEncoding());
164
165 if (old_params!=null && old_params.size()>0)
166 {
167
168 Iterator iter = old_params.entrySet().iterator();
169 while (iter.hasNext())
170 {
171 Map.Entry entry = (Map.Entry)iter.next();
172 String name=(String)entry.getKey();
173 Object values=entry.getValue();
174 for (int i=0;i<LazyList.size(values);i++)
175 parameters.add(name, LazyList.get(values, i));
176 }
177
178 }
179 base_request.setParameters(parameters);
180 }
181
182 IncludeAttributes attr = new IncludeAttributes(old_attr);
183
184 attr._requestURI=_uri;
185 attr._contextPath=_contextHandler.getContextPath();
186 attr._servletPath=null;
187 attr._pathInfo=_path;
188 attr._query=query;
189
190 base_request.setAttributes(attr);
191
192 _contextHandler.handle(_named==null?_path:_named, (HttpServletRequest)request, (HttpServletResponse)response, Handler.INCLUDE);
193 }
194 }
195 finally
196 {
197 base_request.setAttributes(old_attr);
198 base_request.getConnection().included();
199 base_request.setParameters(old_params);
200 }
201 }
202
203
204
205
206
207
208 protected void forward(ServletRequest request, ServletResponse response, int dispatch) throws ServletException, IOException
209 {
210 Request base_request=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
211 response.resetBuffer();
212 request.removeAttribute(__JSP_FILE);
213
214 String old_uri=base_request.getRequestURI();
215 String old_context_path=base_request.getContextPath();
216 String old_servlet_path=base_request.getServletPath();
217 String old_path_info=base_request.getPathInfo();
218 String old_query=base_request.getQueryString();
219 Attributes old_attr=base_request.getAttributes();
220 MultiMap old_params=base_request.getParameters();
221 try
222 {
223 if (_named!=null)
224 _contextHandler.handle(_named, (HttpServletRequest)request, (HttpServletResponse)response, dispatch);
225 else
226 {
227 String query=_dQuery;
228
229 if (query!=null)
230 {
231 MultiMap parameters=new MultiMap();
232 UrlEncoded.decodeTo(query,parameters,request.getCharacterEncoding());
233
234 boolean rewrite_old_query = false;
235
236 if( old_params == null )
237 {
238 base_request.getParameterNames();
239 old_params = base_request.getParameters();
240 }
241
242 if (old_params!=null && old_params.size()>0)
243 {
244
245 Iterator iter = old_params.entrySet().iterator();
246 while (iter.hasNext())
247 {
248 Map.Entry entry = (Map.Entry)iter.next();
249 String name=(String)entry.getKey();
250
251 if (parameters.containsKey(name))
252 rewrite_old_query = true;
253 Object values=entry.getValue();
254 for (int i=0;i<LazyList.size(values);i++)
255 parameters.add(name, LazyList.get(values, i));
256 }
257 }
258
259 if (old_query != null && old_query.length()>0)
260 {
261 if ( rewrite_old_query )
262 {
263 StringBuffer overridden_query_string = new StringBuffer();
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 base_request.setParameters(parameters);
294 base_request.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 base_request.setRequestURI(_uri);
323 base_request.setContextPath(_contextHandler.getContextPath());
324 base_request.setAttributes(attr);
325 base_request.setQueryString(query);
326
327 _contextHandler.handle(_path, (HttpServletRequest)request, (HttpServletResponse)response, dispatch);
328
329 if (base_request.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 base_request.setRequestURI(old_uri);
344 base_request.setContextPath(old_context_path);
345 base_request.setServletPath(old_servlet_path);
346 base_request.setPathInfo(old_path_info);
347 base_request.setAttributes(old_attr);
348 base_request.setParameters(old_params);
349 base_request.setQueryString(old_query);
350 }
351 }
352
353
354
355
356
357 private class ForwardAttributes implements Attributes
358 {
359 Attributes _attr;
360
361 String _requestURI;
362 String _contextPath;
363 String _servletPath;
364 String _pathInfo;
365 String _query;
366
367 ForwardAttributes(Attributes attributes)
368 {
369 _attr=attributes;
370 }
371
372
373 public Object getAttribute(String key)
374 {
375 if (Dispatcher.this._named==null)
376 {
377 if (key.equals(__FORWARD_PATH_INFO)) return _pathInfo;
378 if (key.equals(__FORWARD_REQUEST_URI)) return _requestURI;
379 if (key.equals(__FORWARD_SERVLET_PATH)) return _servletPath;
380 if (key.equals(__FORWARD_CONTEXT_PATH)) return _contextPath;
381 if (key.equals(__FORWARD_QUERY_STRING)) return _query;
382 }
383
384 if (key.startsWith(__INCLUDE_PREFIX) || key.equals(__INCLUDE_JETTY) )
385 return null;
386
387 if (key.equals(__FORWARD_JETTY))
388 return Boolean.TRUE;
389
390 return _attr.getAttribute(key);
391 }
392
393
394 public Enumeration getAttributeNames()
395 {
396 HashSet set=new HashSet();
397 Enumeration e=_attr.getAttributeNames();
398 while(e.hasMoreElements())
399 {
400 String name=(String)e.nextElement();
401 if (!name.startsWith(__INCLUDE_PREFIX) &&
402 !name.startsWith(__FORWARD_PREFIX))
403 set.add(name);
404 }
405
406 if (_named==null)
407 {
408 if (_pathInfo!=null)
409 set.add(__FORWARD_PATH_INFO);
410 else
411 set.remove(__FORWARD_PATH_INFO);
412 set.add(__FORWARD_REQUEST_URI);
413 set.add(__FORWARD_SERVLET_PATH);
414 set.add(__FORWARD_CONTEXT_PATH);
415 if (_query!=null)
416 set.add(__FORWARD_QUERY_STRING);
417 else
418 set.remove(__FORWARD_QUERY_STRING);
419 }
420
421 return Collections.enumeration(set);
422 }
423
424
425 public void setAttribute(String key, Object value)
426 {
427 if (_named==null && key.startsWith("javax.servlet."))
428 {
429 if (key.equals(__FORWARD_PATH_INFO)) _pathInfo=(String)value;
430 else if (key.equals(__FORWARD_REQUEST_URI)) _requestURI=(String)value;
431 else if (key.equals(__FORWARD_SERVLET_PATH)) _servletPath=(String)value;
432 else if (key.equals(__FORWARD_CONTEXT_PATH)) _contextPath=(String)value;
433 else if (key.equals(__FORWARD_QUERY_STRING)) _query=(String)value;
434
435 else if (value==null)
436 _attr.removeAttribute(key);
437 else
438 _attr.setAttribute(key,value);
439 }
440 else if (value==null)
441 _attr.removeAttribute(key);
442 else
443 _attr.setAttribute(key,value);
444 }
445
446
447 public String toString()
448 {
449 return "FORWARD+"+_attr.toString();
450 }
451
452
453 public void clearAttributes()
454 {
455 throw new IllegalStateException();
456 }
457
458
459 public void removeAttribute(String name)
460 {
461 setAttribute(name,null);
462 }
463 }
464
465
466 private class IncludeAttributes implements Attributes
467 {
468 Attributes _attr;
469
470 String _requestURI;
471 String _contextPath;
472 String _servletPath;
473 String _pathInfo;
474 String _query;
475
476 IncludeAttributes(Attributes attributes)
477 {
478 _attr=attributes;
479 }
480
481
482
483
484 public Object getAttribute(String key)
485 {
486 if (Dispatcher.this._named==null)
487 {
488 if (key.equals(__INCLUDE_PATH_INFO)) return _pathInfo;
489 if (key.equals(__INCLUDE_SERVLET_PATH)) return _servletPath;
490 if (key.equals(__INCLUDE_CONTEXT_PATH)) return _contextPath;
491 if (key.equals(__INCLUDE_QUERY_STRING)) return _query;
492 if (key.equals(__INCLUDE_REQUEST_URI)) return _requestURI;
493 }
494 else if (key.startsWith(__INCLUDE_PREFIX))
495 return null;
496
497 if (key.equals(__INCLUDE_JETTY))
498 return Boolean.TRUE;
499
500 return _attr.getAttribute(key);
501 }
502
503
504 public Enumeration getAttributeNames()
505 {
506 HashSet set=new HashSet();
507 Enumeration e=_attr.getAttributeNames();
508 while(e.hasMoreElements())
509 {
510 String name=(String)e.nextElement();
511 if (!name.startsWith(__INCLUDE_PREFIX))
512 set.add(name);
513 }
514
515 if (_named==null)
516 {
517 if (_pathInfo!=null)
518 set.add(__INCLUDE_PATH_INFO);
519 else
520 set.remove(__INCLUDE_PATH_INFO);
521 set.add(__INCLUDE_REQUEST_URI);
522 set.add(__INCLUDE_SERVLET_PATH);
523 set.add(__INCLUDE_CONTEXT_PATH);
524 if (_query!=null)
525 set.add(__INCLUDE_QUERY_STRING);
526 else
527 set.remove(__INCLUDE_QUERY_STRING);
528 }
529
530 return Collections.enumeration(set);
531 }
532
533
534 public void setAttribute(String key, Object value)
535 {
536 if (_named==null && key.startsWith("javax.servlet."))
537 {
538 if (key.equals(__INCLUDE_PATH_INFO)) _pathInfo=(String)value;
539 else if (key.equals(__INCLUDE_REQUEST_URI)) _requestURI=(String)value;
540 else if (key.equals(__INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
541 else if (key.equals(__INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
542 else if (key.equals(__INCLUDE_QUERY_STRING)) _query=(String)value;
543 else if (value==null)
544 _attr.removeAttribute(key);
545 else
546 _attr.setAttribute(key,value);
547 }
548 else if (value==null)
549 _attr.removeAttribute(key);
550 else
551 _attr.setAttribute(key,value);
552 }
553
554
555 public String toString()
556 {
557 return "INCLUDE+"+_attr.toString();
558 }
559
560
561 public void clearAttributes()
562 {
563 throw new IllegalStateException();
564 }
565
566
567 public void removeAttribute(String name)
568 {
569 setAttribute(name,null);
570 }
571 }
572 };