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 {
253 rewrite_old_query = true;
254 }
255 else
256 {
257 Object values=entry.getValue();
258 for (int i=0;i<LazyList.size(values);i++)
259 {
260 parameters.add(name, LazyList.get(values, i));
261 }
262 }
263 }
264 }
265
266 if (old_query != null && old_query.length()>0)
267 {
268 if ( rewrite_old_query )
269 {
270 StringBuffer overridden_query_string = new StringBuffer();
271 MultiMap overridden_old_query = new MultiMap();
272 UrlEncoded.decodeTo(old_query,overridden_old_query,request.getCharacterEncoding());
273
274 MultiMap overridden_new_query = new MultiMap();
275 UrlEncoded.decodeTo(query,overridden_new_query,request.getCharacterEncoding());
276
277 Iterator iter = overridden_old_query.entrySet().iterator();
278 while (iter.hasNext())
279 {
280 Map.Entry entry = (Map.Entry)iter.next();
281 String name=(String)entry.getKey();
282 if(!overridden_new_query.containsKey(name))
283 {
284 Object values=entry.getValue();
285 for (int i=0;i<LazyList.size(values);i++)
286 {
287 overridden_query_string.append("&"+name+"="+LazyList.get(values, i));
288 }
289 }
290 }
291
292 query = query + overridden_query_string;
293 }
294 else
295 {
296 query=query+"&"+old_query;
297 }
298 }
299
300 base_request.setParameters(parameters);
301 base_request.setQueryString(query);
302 }
303
304 ForwardAttributes attr = new ForwardAttributes(old_attr);
305
306
307
308
309
310 if ((String)old_attr.getAttribute(__FORWARD_REQUEST_URI) != null)
311 {
312 attr._pathInfo=(String)old_attr.getAttribute(__FORWARD_PATH_INFO);
313 attr._query=(String)old_attr.getAttribute(__FORWARD_QUERY_STRING);
314 attr._requestURI=(String)old_attr.getAttribute(__FORWARD_REQUEST_URI);
315 attr._contextPath=(String)old_attr.getAttribute(__FORWARD_CONTEXT_PATH);
316 attr._servletPath=(String)old_attr.getAttribute(__FORWARD_SERVLET_PATH);
317 }
318 else
319 {
320 attr._pathInfo=old_path_info;
321 attr._query=old_query;
322 attr._requestURI=old_uri;
323 attr._contextPath=old_context_path;
324 attr._servletPath=old_servlet_path;
325 }
326
327
328
329 base_request.setRequestURI(_uri);
330 base_request.setContextPath(_contextHandler.getContextPath());
331 base_request.setAttributes(attr);
332 base_request.setQueryString(query);
333
334 _contextHandler.handle(_path, (HttpServletRequest)request, (HttpServletResponse)response, dispatch);
335
336 if (base_request.getConnection().getResponse().isWriting())
337 {
338 try {response.getWriter().close();}
339 catch(IllegalStateException e) { response.getOutputStream().close(); }
340 }
341 else
342 {
343 try {response.getOutputStream().close();}
344 catch(IllegalStateException e) { response.getWriter().close(); }
345 }
346 }
347 }
348 finally
349 {
350 base_request.setRequestURI(old_uri);
351 base_request.setContextPath(old_context_path);
352 base_request.setServletPath(old_servlet_path);
353 base_request.setPathInfo(old_path_info);
354 base_request.setAttributes(old_attr);
355 base_request.setParameters(old_params);
356 base_request.setQueryString(old_query);
357 }
358 }
359
360
361
362
363
364 private class ForwardAttributes implements Attributes
365 {
366 Attributes _attr;
367
368 String _requestURI;
369 String _contextPath;
370 String _servletPath;
371 String _pathInfo;
372 String _query;
373
374 ForwardAttributes(Attributes attributes)
375 {
376 _attr=attributes;
377 }
378
379
380 public Object getAttribute(String key)
381 {
382 if (Dispatcher.this._named==null)
383 {
384 if (key.equals(__FORWARD_PATH_INFO)) return _pathInfo;
385 if (key.equals(__FORWARD_REQUEST_URI)) return _requestURI;
386 if (key.equals(__FORWARD_SERVLET_PATH)) return _servletPath;
387 if (key.equals(__FORWARD_CONTEXT_PATH)) return _contextPath;
388 if (key.equals(__FORWARD_QUERY_STRING)) return _query;
389 }
390
391 if (key.startsWith(__INCLUDE_PREFIX) || key.equals(__INCLUDE_JETTY) )
392 return null;
393
394 if (key.equals(__FORWARD_JETTY))
395 return Boolean.TRUE;
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)) _pathInfo=(String)value;
437 else if (key.equals(__FORWARD_REQUEST_URI)) _requestURI=(String)value;
438 else if (key.equals(__FORWARD_SERVLET_PATH)) _servletPath=(String)value;
439 else if (key.equals(__FORWARD_CONTEXT_PATH)) _contextPath=(String)value;
440 else if (key.equals(__FORWARD_QUERY_STRING)) _query=(String)value;
441
442 else if (value==null)
443 _attr.removeAttribute(key);
444 else
445 _attr.setAttribute(key,value);
446 }
447 else if (value==null)
448 _attr.removeAttribute(key);
449 else
450 _attr.setAttribute(key,value);
451 }
452
453
454 public String toString()
455 {
456 return "FORWARD+"+_attr.toString();
457 }
458
459
460 public void clearAttributes()
461 {
462 throw new IllegalStateException();
463 }
464
465
466 public void removeAttribute(String name)
467 {
468 setAttribute(name,null);
469 }
470 }
471
472
473 private class IncludeAttributes implements Attributes
474 {
475 Attributes _attr;
476
477 String _requestURI;
478 String _contextPath;
479 String _servletPath;
480 String _pathInfo;
481 String _query;
482
483 IncludeAttributes(Attributes attributes)
484 {
485 _attr=attributes;
486 }
487
488
489
490
491 public Object getAttribute(String key)
492 {
493 if (Dispatcher.this._named==null)
494 {
495 if (key.equals(__INCLUDE_PATH_INFO)) return _pathInfo;
496 if (key.equals(__INCLUDE_SERVLET_PATH)) return _servletPath;
497 if (key.equals(__INCLUDE_CONTEXT_PATH)) return _contextPath;
498 if (key.equals(__INCLUDE_QUERY_STRING)) return _query;
499 if (key.equals(__INCLUDE_REQUEST_URI)) return _requestURI;
500 }
501 else if (key.startsWith(__INCLUDE_PREFIX))
502 return null;
503
504 if (key.equals(__INCLUDE_JETTY))
505 return Boolean.TRUE;
506
507 return _attr.getAttribute(key);
508 }
509
510
511 public Enumeration getAttributeNames()
512 {
513 HashSet set=new HashSet();
514 Enumeration e=_attr.getAttributeNames();
515 while(e.hasMoreElements())
516 {
517 String name=(String)e.nextElement();
518 if (!name.startsWith(__INCLUDE_PREFIX))
519 set.add(name);
520 }
521
522 if (_named==null)
523 {
524 if (_pathInfo!=null)
525 set.add(__INCLUDE_PATH_INFO);
526 else
527 set.remove(__INCLUDE_PATH_INFO);
528 set.add(__INCLUDE_REQUEST_URI);
529 set.add(__INCLUDE_SERVLET_PATH);
530 set.add(__INCLUDE_CONTEXT_PATH);
531 if (_query!=null)
532 set.add(__INCLUDE_QUERY_STRING);
533 else
534 set.remove(__INCLUDE_QUERY_STRING);
535 }
536
537 return Collections.enumeration(set);
538 }
539
540
541 public void setAttribute(String key, Object value)
542 {
543 if (_named==null && key.startsWith("javax.servlet."))
544 {
545 if (key.equals(__INCLUDE_PATH_INFO)) _pathInfo=(String)value;
546 else if (key.equals(__INCLUDE_REQUEST_URI)) _requestURI=(String)value;
547 else if (key.equals(__INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
548 else if (key.equals(__INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
549 else if (key.equals(__INCLUDE_QUERY_STRING)) _query=(String)value;
550 else if (value==null)
551 _attr.removeAttribute(key);
552 else
553 _attr.setAttribute(key,value);
554 }
555 else if (value==null)
556 _attr.removeAttribute(key);
557 else
558 _attr.setAttribute(key,value);
559 }
560
561
562 public String toString()
563 {
564 return "INCLUDE+"+_attr.toString();
565 }
566
567
568 public void clearAttributes()
569 {
570 throw new IllegalStateException();
571 }
572
573
574 public void removeAttribute(String name)
575 {
576 setAttribute(name,null);
577 }
578 }
579 };