]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/server/Dispatcher.java
updating jetty to jetty-9.2.16.v2016040
[gigi.git] / lib / jetty / org / eclipse / jetty / server / Dispatcher.java
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 //  ------------------------------------------------------------------------
5 //  All rights reserved. This program and the accompanying materials
6 //  are made available under the terms of the Eclipse Public License v1.0
7 //  and Apache License v2.0 which accompanies this distribution.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
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 import javax.servlet.DispatcherType;
26 import javax.servlet.RequestDispatcher;
27 import javax.servlet.ServletException;
28 import javax.servlet.ServletRequest;
29 import javax.servlet.ServletResponse;
30 import javax.servlet.http.HttpServletRequest;
31 import javax.servlet.http.HttpServletResponse;
32
33 import org.eclipse.jetty.server.handler.ContextHandler;
34 import org.eclipse.jetty.util.Attributes;
35 import org.eclipse.jetty.util.MultiMap;
36
37 public class Dispatcher implements RequestDispatcher
38 {
39     /** Dispatch include attribute names */
40     public final static String __INCLUDE_PREFIX="javax.servlet.include.";
41
42     /** Dispatch include attribute names */
43     public final static String __FORWARD_PREFIX="javax.servlet.forward.";
44
45     private final ContextHandler _contextHandler;
46     private final String _uri;
47     private final String _path;
48     private final String _query;
49     private final String _named;
50
51     public Dispatcher(ContextHandler contextHandler, String uri, String pathInContext, String query)
52     {
53         _contextHandler=contextHandler;
54         _uri=uri;
55         _path=pathInContext;
56         _query=query;
57         _named=null;
58     }
59
60     public Dispatcher(ContextHandler contextHandler, String name) throws IllegalStateException
61     {
62         _contextHandler=contextHandler;
63         _named=name;
64         _uri=null;
65         _path=null;
66         _query=null;
67     }
68
69     @Override
70     public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException
71     {
72         forward(request, response, DispatcherType.FORWARD);
73     }
74
75     public void error(ServletRequest request, ServletResponse response) throws ServletException, IOException
76     {
77         forward(request, response, DispatcherType.ERROR);
78     }
79
80     @Override
81     public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
82     {
83         Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
84
85         if (!(request instanceof HttpServletRequest))
86             request = new ServletRequestHttpWrapper(request);
87         if (!(response instanceof HttpServletResponse))
88             response = new ServletResponseHttpWrapper(response);
89
90         final DispatcherType old_type = baseRequest.getDispatcherType();
91         final Attributes old_attr=baseRequest.getAttributes();
92         final MultiMap<String> old_query_params=baseRequest.getQueryParameters();
93         try
94         {
95             baseRequest.setDispatcherType(DispatcherType.INCLUDE);
96             baseRequest.getResponse().include();
97             if (_named!=null)
98             {
99                 _contextHandler.handle(_named,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
100             }
101             else
102             {
103                 IncludeAttributes attr = new IncludeAttributes(old_attr);
104
105                 attr._requestURI=_uri;
106                 attr._contextPath=_contextHandler.getContextPath();
107                 attr._servletPath=null; // set by ServletHandler
108                 attr._pathInfo=_path;
109                 attr._query=_query;
110
111                 if (_query!=null)
112                     baseRequest.mergeQueryParameters(_query, false);
113                 baseRequest.setAttributes(attr);
114
115                 _contextHandler.handle(_path, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
116             }
117         }
118         finally
119         {
120             baseRequest.setAttributes(old_attr);
121             baseRequest.getResponse().included();
122             baseRequest.setQueryParameters(old_query_params);
123             baseRequest.resetParameters();
124             baseRequest.setDispatcherType(old_type);
125         }
126     }
127
128     protected void forward(ServletRequest request, ServletResponse response, DispatcherType dispatch) throws ServletException, IOException
129     {
130         Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
131         Response base_response=baseRequest.getResponse();
132         base_response.resetForForward();
133
134         if (!(request instanceof HttpServletRequest))
135             request = new ServletRequestHttpWrapper(request);
136         if (!(response instanceof HttpServletResponse))
137             response = new ServletResponseHttpWrapper(response);
138
139         final boolean old_handled=baseRequest.isHandled();
140         final String old_uri=baseRequest.getRequestURI();
141         final String old_context_path=baseRequest.getContextPath();
142         final String old_servlet_path=baseRequest.getServletPath();
143         final String old_path_info=baseRequest.getPathInfo();
144         final String old_query=baseRequest.getQueryString();
145         final MultiMap<String> old_query_params=baseRequest.getQueryParameters();
146         final Attributes old_attr=baseRequest.getAttributes();
147         final DispatcherType old_type=baseRequest.getDispatcherType();
148
149         try
150         {
151             baseRequest.setHandled(false);
152             baseRequest.setDispatcherType(dispatch);
153
154             if (_named!=null)
155             {
156                 _contextHandler.handle(_named, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
157             }
158             else
159             {
160                 ForwardAttributes attr = new ForwardAttributes(old_attr);
161
162                 //If we have already been forwarded previously, then keep using the established
163                 //original value. Otherwise, this is the first forward and we need to establish the values.
164                 //Note: the established value on the original request for pathInfo and
165                 //for queryString is allowed to be null, but cannot be null for the other values.
166                 if (old_attr.getAttribute(FORWARD_REQUEST_URI) != null)
167                 {
168                     attr._pathInfo=(String)old_attr.getAttribute(FORWARD_PATH_INFO);
169                     attr._query=(String)old_attr.getAttribute(FORWARD_QUERY_STRING);
170                     attr._requestURI=(String)old_attr.getAttribute(FORWARD_REQUEST_URI);
171                     attr._contextPath=(String)old_attr.getAttribute(FORWARD_CONTEXT_PATH);
172                     attr._servletPath=(String)old_attr.getAttribute(FORWARD_SERVLET_PATH);
173                 }
174                 else
175                 {
176                     attr._pathInfo=old_path_info;
177                     attr._query=old_query;
178                     attr._requestURI=old_uri;
179                     attr._contextPath=old_context_path;
180                     attr._servletPath=old_servlet_path;
181                 }
182
183                 baseRequest.setRequestURI(_uri);
184                 baseRequest.setContextPath(_contextHandler.getContextPath());
185                 baseRequest.setServletPath(null);
186                 baseRequest.setPathInfo(_uri);
187                 if (_query!=null)
188                     baseRequest.mergeQueryParameters(_query, true);
189                 baseRequest.setAttributes(attr);
190
191                 _contextHandler.handle(_path, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
192
193                 if (!baseRequest.getHttpChannelState().isAsync())
194                     commitResponse(response,baseRequest);
195             }
196         }
197         finally
198         {
199             baseRequest.setHandled(old_handled);
200             baseRequest.setRequestURI(old_uri);
201             baseRequest.setContextPath(old_context_path);
202             baseRequest.setServletPath(old_servlet_path);
203             baseRequest.setPathInfo(old_path_info);
204             baseRequest.setQueryString(old_query);
205             baseRequest.setQueryParameters(old_query_params);
206             baseRequest.resetParameters();
207             baseRequest.setAttributes(old_attr);
208             baseRequest.setDispatcherType(old_type);
209         }
210     }
211
212     private void commitResponse(ServletResponse response, Request baseRequest) throws IOException
213     {
214         if (baseRequest.getResponse().isWriting())
215         {
216             try
217             {
218                 response.getWriter().close();
219             }
220             catch (IllegalStateException e)
221             {
222                 response.getOutputStream().close();
223             }
224         }
225         else
226         {
227             try
228             {
229                 response.getOutputStream().close();
230             }
231             catch (IllegalStateException e)
232             {
233                 response.getWriter().close();
234             }
235         }
236     }
237
238     private class ForwardAttributes implements Attributes
239     {
240         final Attributes _attr;
241
242         String _requestURI;
243         String _contextPath;
244         String _servletPath;
245         String _pathInfo;
246         String _query;
247
248         ForwardAttributes(Attributes attributes)
249         {
250             _attr=attributes;
251         }
252
253         /* ------------------------------------------------------------ */
254         @Override
255         public Object getAttribute(String key)
256         {
257             if (Dispatcher.this._named==null)
258             {
259                 if (key.equals(FORWARD_PATH_INFO))
260                     return _pathInfo;
261                 if (key.equals(FORWARD_REQUEST_URI))
262                     return _requestURI;
263                 if (key.equals(FORWARD_SERVLET_PATH))
264                     return _servletPath;
265                 if (key.equals(FORWARD_CONTEXT_PATH))
266                     return _contextPath;
267                 if (key.equals(FORWARD_QUERY_STRING))
268                     return _query;
269             }
270
271             if (key.startsWith(__INCLUDE_PREFIX))
272                 return null;
273
274             return _attr.getAttribute(key);
275         }
276
277         @Override
278         public Enumeration<String> getAttributeNames()
279         {
280             HashSet<String> set=new HashSet<>();
281             Enumeration<String> e=_attr.getAttributeNames();
282             while(e.hasMoreElements())
283             {
284                 String name=e.nextElement();
285                 if (!name.startsWith(__INCLUDE_PREFIX) &&
286                     !name.startsWith(__FORWARD_PREFIX))
287                     set.add(name);
288             }
289
290             if (_named==null)
291             {
292                 if (_pathInfo!=null)
293                     set.add(FORWARD_PATH_INFO);
294                 else
295                     set.remove(FORWARD_PATH_INFO);
296                 set.add(FORWARD_REQUEST_URI);
297                 set.add(FORWARD_SERVLET_PATH);
298                 set.add(FORWARD_CONTEXT_PATH);
299                 if (_query!=null)
300                     set.add(FORWARD_QUERY_STRING);
301                 else
302                     set.remove(FORWARD_QUERY_STRING);
303             }
304
305             return Collections.enumeration(set);
306         }
307
308         @Override
309         public void setAttribute(String key, Object value)
310         {
311             if (_named==null && key.startsWith("javax.servlet."))
312             {
313                 if (key.equals(FORWARD_PATH_INFO))
314                     _pathInfo=(String)value;
315                 else if (key.equals(FORWARD_REQUEST_URI))
316                     _requestURI=(String)value;
317                 else if (key.equals(FORWARD_SERVLET_PATH))
318                     _servletPath=(String)value;
319                 else if (key.equals(FORWARD_CONTEXT_PATH))
320                     _contextPath=(String)value;
321                 else if (key.equals(FORWARD_QUERY_STRING))
322                     _query=(String)value;
323
324                 else if (value==null)
325                     _attr.removeAttribute(key);
326                 else
327                     _attr.setAttribute(key,value);
328             }
329             else if (value==null)
330                 _attr.removeAttribute(key);
331             else
332                 _attr.setAttribute(key,value);
333         }
334
335         @Override
336         public String toString()
337         {
338             return "FORWARD+"+_attr.toString();
339         }
340
341         @Override
342         public void clearAttributes()
343         {
344             throw new IllegalStateException();
345         }
346
347         @Override
348         public void removeAttribute(String name)
349         {
350             setAttribute(name,null);
351         }
352     }
353
354     private class IncludeAttributes implements Attributes
355     {
356         final Attributes _attr;
357
358         String _requestURI;
359         String _contextPath;
360         String _servletPath;
361         String _pathInfo;
362         String _query;
363
364         IncludeAttributes(Attributes attributes)
365         {
366             _attr=attributes;
367         }
368
369         @Override
370         public Object getAttribute(String key)
371         {
372             if (Dispatcher.this._named==null)
373             {
374                 if (key.equals(INCLUDE_PATH_INFO))    return _pathInfo;
375                 if (key.equals(INCLUDE_SERVLET_PATH)) return _servletPath;
376                 if (key.equals(INCLUDE_CONTEXT_PATH)) return _contextPath;
377                 if (key.equals(INCLUDE_QUERY_STRING)) return _query;
378                 if (key.equals(INCLUDE_REQUEST_URI))  return _requestURI;
379             }
380             else if (key.startsWith(__INCLUDE_PREFIX))
381                     return null;
382
383
384             return _attr.getAttribute(key);
385         }
386
387         @Override
388         public Enumeration<String> getAttributeNames()
389         {
390             HashSet<String> set=new HashSet<>();
391             Enumeration<String> e=_attr.getAttributeNames();
392             while(e.hasMoreElements())
393             {
394                 String name=e.nextElement();
395                 if (!name.startsWith(__INCLUDE_PREFIX))
396                     set.add(name);
397             }
398
399             if (_named==null)
400             {
401                 if (_pathInfo!=null)
402                     set.add(INCLUDE_PATH_INFO);
403                 else
404                     set.remove(INCLUDE_PATH_INFO);
405                 set.add(INCLUDE_REQUEST_URI);
406                 set.add(INCLUDE_SERVLET_PATH);
407                 set.add(INCLUDE_CONTEXT_PATH);
408                 if (_query!=null)
409                     set.add(INCLUDE_QUERY_STRING);
410                 else
411                     set.remove(INCLUDE_QUERY_STRING);
412             }
413
414             return Collections.enumeration(set);
415         }
416
417         @Override
418         public void setAttribute(String key, Object value)
419         {
420             if (_named==null && key.startsWith("javax.servlet."))
421             {
422                 if (key.equals(INCLUDE_PATH_INFO))         _pathInfo=(String)value;
423                 else if (key.equals(INCLUDE_REQUEST_URI))  _requestURI=(String)value;
424                 else if (key.equals(INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
425                 else if (key.equals(INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
426                 else if (key.equals(INCLUDE_QUERY_STRING)) _query=(String)value;
427                 else if (value==null)
428                     _attr.removeAttribute(key);
429                 else
430                     _attr.setAttribute(key,value);
431             }
432             else if (value==null)
433                 _attr.removeAttribute(key);
434             else
435                 _attr.setAttribute(key,value);
436         }
437
438         @Override
439         public String toString()
440         {
441             return "INCLUDE+"+_attr.toString();
442         }
443
444         @Override
445         public void clearAttributes()
446         {
447             throw new IllegalStateException();
448         }
449
450         @Override
451         public void removeAttribute(String name)
452         {
453             setAttribute(name,null);
454         }
455     }
456 }