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