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 @Deprecated
220 public void push(ServletRequest request)
221 {
222 Request baseRequest = Request.getBaseRequest(request);
223 HttpFields fields = new HttpFields(baseRequest.getHttpFields());
224
225 String query=baseRequest.getQueryString();
226 if (_uri.hasQuery())
227 {
228 if (query==null)
229 query=_uri.getQuery();
230 else
231 query=query+"&"+_uri.getQuery();
232 }
233
234 HttpURI uri = HttpURI.createHttpURI(request.getScheme(),request.getServerName(),request.getServerPort(),_uri.getPath(),baseRequest.getHttpURI().getParam(),query,null);
235
236 MetaData.Request push = new MetaData.Request(HttpMethod.GET.asString(),uri,baseRequest.getHttpVersion(),fields);
237
238 baseRequest.getHttpChannel().getHttpTransport().push(push);
239 }
240
241 @Override
242 public String toString()
243 {
244 return String.format("Dispatcher@0x%x{%s,%s}",hashCode(),_named,_uri);
245 }
246
247 private void commitResponse(ServletResponse response, Request baseRequest) throws IOException
248 {
249 if (baseRequest.getResponse().isWriting())
250 {
251 try
252 {
253 response.getWriter().close();
254 }
255 catch (IllegalStateException e)
256 {
257 response.getOutputStream().close();
258 }
259 }
260 else
261 {
262 try
263 {
264 response.getOutputStream().close();
265 }
266 catch (IllegalStateException e)
267 {
268 response.getWriter().close();
269 }
270 }
271 }
272
273 private class ForwardAttributes implements Attributes
274 {
275 final Attributes _attr;
276
277 String _requestURI;
278 String _contextPath;
279 String _servletPath;
280 String _pathInfo;
281 String _query;
282
283 ForwardAttributes(Attributes attributes)
284 {
285 _attr=attributes;
286 }
287
288
289 @Override
290 public Object getAttribute(String key)
291 {
292 if (Dispatcher.this._named==null)
293 {
294 if (key.equals(FORWARD_PATH_INFO))
295 return _pathInfo;
296 if (key.equals(FORWARD_REQUEST_URI))
297 return _requestURI;
298 if (key.equals(FORWARD_SERVLET_PATH))
299 return _servletPath;
300 if (key.equals(FORWARD_CONTEXT_PATH))
301 return _contextPath;
302 if (key.equals(FORWARD_QUERY_STRING))
303 return _query;
304 }
305
306 if (key.startsWith(__INCLUDE_PREFIX))
307 return null;
308
309 return _attr.getAttribute(key);
310 }
311
312 @Override
313 public Enumeration<String> getAttributeNames()
314 {
315 HashSet<String> set=new HashSet<>();
316 Enumeration<String> e=_attr.getAttributeNames();
317 while(e.hasMoreElements())
318 {
319 String name=e.nextElement();
320 if (!name.startsWith(__INCLUDE_PREFIX) &&
321 !name.startsWith(__FORWARD_PREFIX))
322 set.add(name);
323 }
324
325 if (_named==null)
326 {
327 if (_pathInfo!=null)
328 set.add(FORWARD_PATH_INFO);
329 else
330 set.remove(FORWARD_PATH_INFO);
331 set.add(FORWARD_REQUEST_URI);
332 set.add(FORWARD_SERVLET_PATH);
333 set.add(FORWARD_CONTEXT_PATH);
334 if (_query!=null)
335 set.add(FORWARD_QUERY_STRING);
336 else
337 set.remove(FORWARD_QUERY_STRING);
338 }
339
340 return Collections.enumeration(set);
341 }
342
343 @Override
344 public void setAttribute(String key, Object value)
345 {
346 if (_named==null && key.startsWith("javax.servlet."))
347 {
348 if (key.equals(FORWARD_PATH_INFO))
349 _pathInfo=(String)value;
350 else if (key.equals(FORWARD_REQUEST_URI))
351 _requestURI=(String)value;
352 else if (key.equals(FORWARD_SERVLET_PATH))
353 _servletPath=(String)value;
354 else if (key.equals(FORWARD_CONTEXT_PATH))
355 _contextPath=(String)value;
356 else if (key.equals(FORWARD_QUERY_STRING))
357 _query=(String)value;
358
359 else if (value==null)
360 _attr.removeAttribute(key);
361 else
362 _attr.setAttribute(key,value);
363 }
364 else if (value==null)
365 _attr.removeAttribute(key);
366 else
367 _attr.setAttribute(key,value);
368 }
369
370 @Override
371 public String toString()
372 {
373 return "FORWARD+"+_attr.toString();
374 }
375
376 @Override
377 public void clearAttributes()
378 {
379 throw new IllegalStateException();
380 }
381
382 @Override
383 public void removeAttribute(String name)
384 {
385 setAttribute(name,null);
386 }
387 }
388
389 private class IncludeAttributes implements Attributes
390 {
391 final Attributes _attr;
392
393 String _requestURI;
394 String _contextPath;
395 String _servletPath;
396 String _pathInfo;
397 String _query;
398
399 IncludeAttributes(Attributes attributes)
400 {
401 _attr=attributes;
402 }
403
404 @Override
405 public Object getAttribute(String key)
406 {
407 if (Dispatcher.this._named==null)
408 {
409 if (key.equals(INCLUDE_PATH_INFO)) return _pathInfo;
410 if (key.equals(INCLUDE_SERVLET_PATH)) return _servletPath;
411 if (key.equals(INCLUDE_CONTEXT_PATH)) return _contextPath;
412 if (key.equals(INCLUDE_QUERY_STRING)) return _query;
413 if (key.equals(INCLUDE_REQUEST_URI)) return _requestURI;
414 }
415 else if (key.startsWith(__INCLUDE_PREFIX))
416 return null;
417
418
419 return _attr.getAttribute(key);
420 }
421
422 @Override
423 public Enumeration<String> getAttributeNames()
424 {
425 HashSet<String> set=new HashSet<>();
426 Enumeration<String> e=_attr.getAttributeNames();
427 while(e.hasMoreElements())
428 {
429 String name=e.nextElement();
430 if (!name.startsWith(__INCLUDE_PREFIX))
431 set.add(name);
432 }
433
434 if (_named==null)
435 {
436 if (_pathInfo!=null)
437 set.add(INCLUDE_PATH_INFO);
438 else
439 set.remove(INCLUDE_PATH_INFO);
440 set.add(INCLUDE_REQUEST_URI);
441 set.add(INCLUDE_SERVLET_PATH);
442 set.add(INCLUDE_CONTEXT_PATH);
443 if (_query!=null)
444 set.add(INCLUDE_QUERY_STRING);
445 else
446 set.remove(INCLUDE_QUERY_STRING);
447 }
448
449 return Collections.enumeration(set);
450 }
451
452 @Override
453 public void setAttribute(String key, Object value)
454 {
455 if (_named==null && key.startsWith("javax.servlet."))
456 {
457 if (key.equals(INCLUDE_PATH_INFO)) _pathInfo=(String)value;
458 else if (key.equals(INCLUDE_REQUEST_URI)) _requestURI=(String)value;
459 else if (key.equals(INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
460 else if (key.equals(INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
461 else if (key.equals(INCLUDE_QUERY_STRING)) _query=(String)value;
462 else if (value==null)
463 _attr.removeAttribute(key);
464 else
465 _attr.setAttribute(key,value);
466 }
467 else if (value==null)
468 _attr.removeAttribute(key);
469 else
470 _attr.setAttribute(key,value);
471 }
472
473 @Override
474 public String toString()
475 {
476 return "INCLUDE+"+_attr.toString();
477 }
478
479 @Override
480 public void clearAttributes()
481 {
482 throw new IllegalStateException();
483 }
484
485 @Override
486 public void removeAttribute(String name)
487 {
488 setAttribute(name,null);
489 }
490 }
491 }