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