1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server;
20
21 import java.io.IOException;
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.HashSet;
25
26 import javax.servlet.DispatcherType;
27 import javax.servlet.RequestDispatcher;
28 import javax.servlet.ServletException;
29 import javax.servlet.ServletRequest;
30 import javax.servlet.ServletResponse;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34 import org.eclipse.jetty.http.HttpFields;
35 import org.eclipse.jetty.http.HttpMethod;
36 import org.eclipse.jetty.http.HttpURI;
37 import org.eclipse.jetty.http.MetaData;
38 import org.eclipse.jetty.server.handler.ContextHandler;
39 import org.eclipse.jetty.util.Attributes;
40 import org.eclipse.jetty.util.MultiMap;
41
42 public class Dispatcher implements RequestDispatcher
43 {
44
45 public final static String __INCLUDE_PREFIX="javax.servlet.include.";
46
47
48 public final static String __FORWARD_PREFIX="javax.servlet.forward.";
49
50 private final ContextHandler _contextHandler;
51 private final HttpURI _uri;
52 private final String _pathInContext;
53 private final String _named;
54
55 public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInContext)
56 {
57 _contextHandler=contextHandler;
58 _uri=uri;
59 _pathInContext=pathInContext;
60 _named=null;
61 }
62
63 public Dispatcher(ContextHandler contextHandler, String name) throws IllegalStateException
64 {
65 _contextHandler=contextHandler;
66 _uri=null;
67 _pathInContext=null;
68 _named=name;
69 }
70
71 @Override
72 public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException
73 {
74 forward(request, response, DispatcherType.FORWARD);
75 }
76
77 public void error(ServletRequest request, ServletResponse response) throws ServletException, IOException
78 {
79 forward(request, response, DispatcherType.ERROR);
80 }
81
82 @Override
83 public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
84 {
85 Request baseRequest=Request.getBaseRequest(request);
86
87 if (!(request instanceof HttpServletRequest))
88 request = new ServletRequestHttpWrapper(request);
89 if (!(response instanceof HttpServletResponse))
90 response = new ServletResponseHttpWrapper(response);
91
92 final DispatcherType old_type = baseRequest.getDispatcherType();
93 final Attributes old_attr=baseRequest.getAttributes();
94 final MultiMap<String> old_query_params=baseRequest.getQueryParameters();
95 try
96 {
97 baseRequest.setDispatcherType(DispatcherType.INCLUDE);
98 baseRequest.getResponse().include();
99 if (_named!=null)
100 {
101 _contextHandler.handle(_named,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
102 }
103 else
104 {
105 IncludeAttributes attr = new IncludeAttributes(old_attr);
106
107 attr._requestURI=_uri.getPath();
108 attr._contextPath=_contextHandler.getContextPath();
109 attr._servletPath=null;
110 attr._pathInfo=_pathInContext;
111 attr._query=_uri.getQuery();
112
113 if (attr._query!=null)
114 baseRequest.mergeQueryParameters(baseRequest.getQueryString(),attr._query, false);
115 baseRequest.setAttributes(attr);
116
117 _contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
118 }
119 }
120 finally
121 {
122 baseRequest.setAttributes(old_attr);
123 baseRequest.getResponse().included();
124 baseRequest.setQueryParameters(old_query_params);
125 baseRequest.resetParameters();
126 baseRequest.setDispatcherType(old_type);
127 }
128 }
129
130 protected void forward(ServletRequest request, ServletResponse response, DispatcherType dispatch) throws ServletException, IOException
131 {
132 Request baseRequest=Request.getBaseRequest(request);
133 Response base_response=baseRequest.getResponse();
134 base_response.resetForForward();
135
136 if (!(request instanceof HttpServletRequest))
137 request = new ServletRequestHttpWrapper(request);
138 if (!(response instanceof HttpServletResponse))
139 response = new ServletResponseHttpWrapper(response);
140
141 final boolean old_handled=baseRequest.isHandled();
142
143 final HttpURI old_uri=baseRequest.getHttpURI();
144 final String old_context_path=baseRequest.getContextPath();
145 final String old_servlet_path=baseRequest.getServletPath();
146 final String old_path_info=baseRequest.getPathInfo();
147
148 final MultiMap<String> old_query_params=baseRequest.getQueryParameters();
149 final Attributes old_attr=baseRequest.getAttributes();
150 final DispatcherType old_type=baseRequest.getDispatcherType();
151
152 try
153 {
154 baseRequest.setHandled(false);
155 baseRequest.setDispatcherType(dispatch);
156
157 if (_named!=null)
158 {
159 _contextHandler.handle(_named, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
160 }
161 else
162 {
163 ForwardAttributes attr = new ForwardAttributes(old_attr);
164
165
166
167
168
169 if (old_attr.getAttribute(FORWARD_REQUEST_URI) != null)
170 {
171 attr._pathInfo=(String)old_attr.getAttribute(FORWARD_PATH_INFO);
172 attr._query=(String)old_attr.getAttribute(FORWARD_QUERY_STRING);
173 attr._requestURI=(String)old_attr.getAttribute(FORWARD_REQUEST_URI);
174 attr._contextPath=(String)old_attr.getAttribute(FORWARD_CONTEXT_PATH);
175 attr._servletPath=(String)old_attr.getAttribute(FORWARD_SERVLET_PATH);
176 }
177 else
178 {
179 attr._pathInfo=old_path_info;
180 attr._query=old_uri.getQuery();
181 attr._requestURI=old_uri.getPath();
182 attr._contextPath=old_context_path;
183 attr._servletPath=old_servlet_path;
184 }
185
186 HttpURI uri = new HttpURI(old_uri.getScheme(),old_uri.getHost(),old_uri.getPort(),
187 _uri.getPath(),_uri.getParam(),_uri.getQuery(),_uri.getFragment());
188
189 baseRequest.setHttpURI(uri);
190
191 baseRequest.setContextPath(_contextHandler.getContextPath());
192 baseRequest.setServletPath(null);
193 baseRequest.setPathInfo(_pathInContext);
194 if (_uri.getQuery()!=null || old_uri.getQuery()!=null)
195 baseRequest.mergeQueryParameters(old_uri.getQuery(),_uri.getQuery(), true);
196
197 baseRequest.setAttributes(attr);
198
199 _contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
200
201 if (!baseRequest.getHttpChannelState().isAsync())
202 commitResponse(response,baseRequest);
203 }
204 }
205 finally
206 {
207 baseRequest.setHandled(old_handled);
208 baseRequest.setHttpURI(old_uri);
209 baseRequest.setContextPath(old_context_path);
210 baseRequest.setServletPath(old_servlet_path);
211 baseRequest.setPathInfo(old_path_info);
212 baseRequest.setQueryParameters(old_query_params);
213 baseRequest.resetParameters();
214 baseRequest.setAttributes(old_attr);
215 baseRequest.setDispatcherType(old_type);
216 }
217 }
218
219
220
221
222
223
224
225 @Deprecated
226 public void push(ServletRequest request)
227 {
228 Request baseRequest = Request.getBaseRequest(request);
229 HttpFields fields = new HttpFields(baseRequest.getHttpFields());
230
231 String query=baseRequest.getQueryString();
232 if (_uri.hasQuery())
233 {
234 if (query==null)
235 query=_uri.getQuery();
236 else
237 query=query+"&"+_uri.getQuery();
238 }
239
240 HttpURI uri = HttpURI.createHttpURI(request.getScheme(),request.getServerName(),request.getServerPort(),_uri.getPath(),baseRequest.getHttpURI().getParam(),query,null);
241
242 MetaData.Request push = new MetaData.Request(HttpMethod.GET.asString(),uri,baseRequest.getHttpVersion(),fields);
243
244 baseRequest.getHttpChannel().getHttpTransport().push(push);
245 }
246
247 @Override
248 public String toString()
249 {
250 return String.format("Dispatcher@0x%x{%s,%s}",hashCode(),_named,_uri);
251 }
252
253 private void commitResponse(ServletResponse response, Request baseRequest) throws IOException
254 {
255 if (baseRequest.getResponse().isWriting())
256 {
257 try
258 {
259 response.getWriter().close();
260 }
261 catch (IllegalStateException e)
262 {
263 response.getOutputStream().close();
264 }
265 }
266 else
267 {
268 try
269 {
270 response.getOutputStream().close();
271 }
272 catch (IllegalStateException e)
273 {
274 response.getWriter().close();
275 }
276 }
277 }
278
279 private class ForwardAttributes implements Attributes
280 {
281 final Attributes _attr;
282
283 String _requestURI;
284 String _contextPath;
285 String _servletPath;
286 String _pathInfo;
287 String _query;
288
289 ForwardAttributes(Attributes attributes)
290 {
291 _attr=attributes;
292 }
293
294
295 @Override
296 public Object getAttribute(String key)
297 {
298 if (Dispatcher.this._named==null)
299 {
300 if (key.equals(FORWARD_PATH_INFO))
301 return _pathInfo;
302 if (key.equals(FORWARD_REQUEST_URI))
303 return _requestURI;
304 if (key.equals(FORWARD_SERVLET_PATH))
305 return _servletPath;
306 if (key.equals(FORWARD_CONTEXT_PATH))
307 return _contextPath;
308 if (key.equals(FORWARD_QUERY_STRING))
309 return _query;
310 }
311
312 if (key.startsWith(__INCLUDE_PREFIX))
313 return null;
314
315 return _attr.getAttribute(key);
316 }
317
318 @Override
319 public Enumeration<String> getAttributeNames()
320 {
321 HashSet<String> set=new HashSet<>();
322 Enumeration<String> e=_attr.getAttributeNames();
323 while(e.hasMoreElements())
324 {
325 String name=e.nextElement();
326 if (!name.startsWith(__INCLUDE_PREFIX) &&
327 !name.startsWith(__FORWARD_PREFIX))
328 set.add(name);
329 }
330
331 if (_named==null)
332 {
333 if (_pathInfo!=null)
334 set.add(FORWARD_PATH_INFO);
335 else
336 set.remove(FORWARD_PATH_INFO);
337 set.add(FORWARD_REQUEST_URI);
338 set.add(FORWARD_SERVLET_PATH);
339 set.add(FORWARD_CONTEXT_PATH);
340 if (_query!=null)
341 set.add(FORWARD_QUERY_STRING);
342 else
343 set.remove(FORWARD_QUERY_STRING);
344 }
345
346 return Collections.enumeration(set);
347 }
348
349 @Override
350 public void setAttribute(String key, Object value)
351 {
352 if (_named==null && key.startsWith("javax.servlet."))
353 {
354 if (key.equals(FORWARD_PATH_INFO))
355 _pathInfo=(String)value;
356 else if (key.equals(FORWARD_REQUEST_URI))
357 _requestURI=(String)value;
358 else if (key.equals(FORWARD_SERVLET_PATH))
359 _servletPath=(String)value;
360 else if (key.equals(FORWARD_CONTEXT_PATH))
361 _contextPath=(String)value;
362 else if (key.equals(FORWARD_QUERY_STRING))
363 _query=(String)value;
364
365 else if (value==null)
366 _attr.removeAttribute(key);
367 else
368 _attr.setAttribute(key,value);
369 }
370 else if (value==null)
371 _attr.removeAttribute(key);
372 else
373 _attr.setAttribute(key,value);
374 }
375
376 @Override
377 public String toString()
378 {
379 return "FORWARD+"+_attr.toString();
380 }
381
382 @Override
383 public void clearAttributes()
384 {
385 throw new IllegalStateException();
386 }
387
388 @Override
389 public void removeAttribute(String name)
390 {
391 setAttribute(name,null);
392 }
393 }
394
395 private class IncludeAttributes implements Attributes
396 {
397 final Attributes _attr;
398
399 String _requestURI;
400 String _contextPath;
401 String _servletPath;
402 String _pathInfo;
403 String _query;
404
405 IncludeAttributes(Attributes attributes)
406 {
407 _attr=attributes;
408 }
409
410 @Override
411 public Object getAttribute(String key)
412 {
413 if (Dispatcher.this._named==null)
414 {
415 if (key.equals(INCLUDE_PATH_INFO)) return _pathInfo;
416 if (key.equals(INCLUDE_SERVLET_PATH)) return _servletPath;
417 if (key.equals(INCLUDE_CONTEXT_PATH)) return _contextPath;
418 if (key.equals(INCLUDE_QUERY_STRING)) return _query;
419 if (key.equals(INCLUDE_REQUEST_URI)) return _requestURI;
420 }
421 else if (key.startsWith(__INCLUDE_PREFIX))
422 return null;
423
424
425 return _attr.getAttribute(key);
426 }
427
428 @Override
429 public Enumeration<String> getAttributeNames()
430 {
431 HashSet<String> set=new HashSet<>();
432 Enumeration<String> e=_attr.getAttributeNames();
433 while(e.hasMoreElements())
434 {
435 String name=e.nextElement();
436 if (!name.startsWith(__INCLUDE_PREFIX))
437 set.add(name);
438 }
439
440 if (_named==null)
441 {
442 if (_pathInfo!=null)
443 set.add(INCLUDE_PATH_INFO);
444 else
445 set.remove(INCLUDE_PATH_INFO);
446 set.add(INCLUDE_REQUEST_URI);
447 set.add(INCLUDE_SERVLET_PATH);
448 set.add(INCLUDE_CONTEXT_PATH);
449 if (_query!=null)
450 set.add(INCLUDE_QUERY_STRING);
451 else
452 set.remove(INCLUDE_QUERY_STRING);
453 }
454
455 return Collections.enumeration(set);
456 }
457
458 @Override
459 public void setAttribute(String key, Object value)
460 {
461 if (_named==null && key.startsWith("javax.servlet."))
462 {
463 if (key.equals(INCLUDE_PATH_INFO)) _pathInfo=(String)value;
464 else if (key.equals(INCLUDE_REQUEST_URI)) _requestURI=(String)value;
465 else if (key.equals(INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
466 else if (key.equals(INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
467 else if (key.equals(INCLUDE_QUERY_STRING)) _query=(String)value;
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 @Override
480 public String toString()
481 {
482 return "INCLUDE+"+_attr.toString();
483 }
484
485 @Override
486 public void clearAttributes()
487 {
488 throw new IllegalStateException();
489 }
490
491 @Override
492 public void removeAttribute(String name)
493 {
494 setAttribute(name,null);
495 }
496 }
497 }