View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses.
12  // ========================================================================
13  
14  package org.eclipse.jetty.server;
15  
16  import java.io.BufferedReader;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.io.InputStreamReader;
20  import java.io.UnsupportedEncodingException;
21  import java.net.InetAddress;
22  import java.nio.ByteBuffer;
23  import java.security.Principal;
24  import java.util.Collection;
25  import java.util.Collections;
26  import java.util.Enumeration;
27  import java.util.EventListener;
28  import java.util.HashMap;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Locale;
32  import java.util.Map;
33  import java.util.Map.Entry;
34  
35  import javax.servlet.RequestDispatcher;
36  import javax.servlet.ServletContext;
37  import javax.servlet.ServletInputStream;
38  import javax.servlet.ServletRequest;
39  import javax.servlet.ServletRequestAttributeEvent;
40  import javax.servlet.ServletRequestAttributeListener;
41  import javax.servlet.ServletResponse;
42  import javax.servlet.http.Cookie;
43  import javax.servlet.http.HttpServletRequest;
44  import javax.servlet.http.HttpSession;
45  
46  import org.eclipse.jetty.continuation.Continuation;
47  import org.eclipse.jetty.continuation.ContinuationListener;
48  import org.eclipse.jetty.http.HttpCookie;
49  import org.eclipse.jetty.http.HttpFields;
50  import org.eclipse.jetty.http.HttpHeaders;
51  import org.eclipse.jetty.http.HttpMethods;
52  import org.eclipse.jetty.http.HttpParser;
53  import org.eclipse.jetty.http.HttpStatus;
54  import org.eclipse.jetty.http.HttpURI;
55  import org.eclipse.jetty.http.HttpVersions;
56  import org.eclipse.jetty.http.MimeTypes;
57  import org.eclipse.jetty.io.Buffer;
58  import org.eclipse.jetty.io.BufferUtil;
59  import org.eclipse.jetty.io.EndPoint;
60  import org.eclipse.jetty.io.nio.DirectNIOBuffer;
61  import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
62  import org.eclipse.jetty.io.nio.NIOBuffer;
63  import org.eclipse.jetty.server.handler.ContextHandler;
64  import org.eclipse.jetty.server.handler.ContextHandler.Context;
65  import org.eclipse.jetty.util.Attributes;
66  import org.eclipse.jetty.util.AttributesMap;
67  import org.eclipse.jetty.util.LazyList;
68  import org.eclipse.jetty.util.MultiMap;
69  import org.eclipse.jetty.util.StringUtil;
70  import org.eclipse.jetty.util.URIUtil;
71  import org.eclipse.jetty.util.UrlEncoded;
72  import org.eclipse.jetty.util.log.Log;
73  import org.eclipse.jetty.util.log.Logger;
74  
75  /* ------------------------------------------------------------ */
76  /**
77   * Jetty Request.
78   * <p>
79   * Implements {@link javax.servlet.http.HttpServletRequest} from the <code>javax.servlet.http</code> package.
80   * </p>
81   * <p>
82   * The standard interface of mostly getters, is extended with setters so that the request is mutable by the handlers that it is passed to. This allows the
83   * request object to be as lightweight as possible and not actually implement any significant behavior. For example
84   * <ul>
85   *
86   * <li>The {@link Request#getContextPath()} method will return null, until the request has been passed to a {@link ContextHandler} which matches the
87   * {@link Request#getPathInfo()} with a context path and calls {@link Request#setContextPath(String)} as a result.</li>
88   *
89   * <li>the HTTP session methods will all return null sessions until such time as a request has been passed to a
90   * {@link org.eclipse.jetty.server.session.SessionHandler} which checks for session cookies and enables the ability to create new sessions.</li>
91   *
92   * <li>The {@link Request#getServletPath()} method will return null until the request has been passed to a <code>org.eclipse.jetty.servlet.ServletHandler</code>
93   * and the pathInfo matched against the servlet URL patterns and {@link Request#setServletPath(String)} called as a result.</li>
94   * </ul>
95   *
96   * A request instance is created for each {@link AbstractHttpConnection} accepted by the server and recycled for each HTTP request received via that connection.
97   * An effort is made to avoid reparsing headers and cookies that are likely to be the same for requests from the same connection.
98   *
99   * <p>
100  * The form content that a request can process is limited to protect from Denial of Service attacks. The size in bytes is limited by
101  * {@link ContextHandler#getMaxFormContentSize()} or if there is no context then the "org.eclipse.jetty.server.Request.maxFormContentSize" {@link Server}
102  * attribute. The number of parameters keys is limited by {@link ContextHandler#getMaxFormKeys()} or if there is no context then the
103  * "org.eclipse.jetty.server.Request.maxFormKeys" {@link Server} attribute.
104  *
105  *
106  */
107 public class Request implements HttpServletRequest
108 {
109     private static final Logger LOG = Log.getLogger(Request.class);
110 
111     private static final String __ASYNC_FWD = "org.eclipse.asyncfwd";
112     private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault());
113     private static final int __NONE = 0, _STREAM = 1, __READER = 2;
114 
115     /* ------------------------------------------------------------ */
116     public static Request getRequest(HttpServletRequest request)
117     {
118         if (request instanceof Request)
119             return (Request)request;
120 
121         return AbstractHttpConnection.getCurrentConnection().getRequest();
122     }
123     protected final AsyncContinuation _async = new AsyncContinuation();
124     private boolean _asyncSupported = true;
125     private volatile Attributes _attributes;
126     private Authentication _authentication;
127     private MultiMap<String> _baseParameters;
128     private String _characterEncoding;
129     protected AbstractHttpConnection _connection;
130     private ContextHandler.Context _context;
131     private boolean _newContext;
132     private String _contextPath;
133     private CookieCutter _cookies;
134     private boolean _cookiesExtracted = false;
135     private DispatcherType _dispatcherType;
136     private boolean _dns = false;
137     private EndPoint _endp;
138     private boolean _handled = false;
139     private int _inputState = __NONE;
140     private String _method;
141     private MultiMap<String> _parameters;
142     private boolean _paramsExtracted;
143     private String _pathInfo;
144     private int _port;
145     private String _protocol = HttpVersions.HTTP_1_1;
146     private String _queryEncoding;
147     private String _queryString;
148     private BufferedReader _reader;
149     private String _readerEncoding;
150     private String _remoteAddr;
151     private String _remoteHost;
152     private Object _requestAttributeListeners;
153     private String _requestedSessionId;
154     private boolean _requestedSessionIdFromCookie = false;
155     private String _requestURI;
156     private Map<Object, HttpSession> _savedNewSessions;
157     private String _scheme = URIUtil.HTTP;
158     private UserIdentity.Scope _scope;
159     private String _serverName;
160     private String _servletPath;
161     private HttpSession _session;
162     private SessionManager _sessionManager;
163     private long _timeStamp;
164     private long _dispatchTime;
165 
166     private Buffer _timeStampBuffer;
167     private HttpURI _uri;
168 
169     /* ------------------------------------------------------------ */
170     public Request()
171     {
172     }
173 
174     /* ------------------------------------------------------------ */
175     public Request(AbstractHttpConnection connection)
176     {
177         setConnection(connection);
178     }
179 
180     /* ------------------------------------------------------------ */
181     public void addEventListener(final EventListener listener)
182     {
183         if (listener instanceof ServletRequestAttributeListener)
184             _requestAttributeListeners = LazyList.add(_requestAttributeListeners,listener);
185         if (listener instanceof ContinuationListener)
186             throw new IllegalArgumentException();
187     }
188 
189     /* ------------------------------------------------------------ */
190     /**
191      * Extract Parameters from query string and/or form _content.
192      */
193     public void extractParameters()
194     {
195         if (_baseParameters == null)
196             _baseParameters = new MultiMap(16);
197 
198         if (_paramsExtracted)
199         {
200             if (_parameters == null)
201                 _parameters = _baseParameters;
202             return;
203         }
204 
205         _paramsExtracted = true;
206 
207         try
208         {
209             // Handle query string
210             if (_uri != null && _uri.hasQuery())
211             {
212                 if (_queryEncoding == null)
213                     _uri.decodeQueryTo(_baseParameters);
214                 else
215                 {
216                     try
217                     {
218                         _uri.decodeQueryTo(_baseParameters,_queryEncoding);
219                     }
220                     catch (UnsupportedEncodingException e)
221                     {
222                         if (LOG.isDebugEnabled())
223                             LOG.warn(e);
224                         else
225                             LOG.warn(e.toString());
226                     }
227                 }
228             }
229 
230             // handle any _content.
231             String encoding = getCharacterEncoding();
232             String content_type = getContentType();
233             if (content_type != null && content_type.length() > 0)
234             {
235                 content_type = HttpFields.valueParameters(content_type,null);
236 
237                 if (MimeTypes.FORM_ENCODED.equalsIgnoreCase(content_type) && _inputState == __NONE
238                         && (HttpMethods.POST.equals(getMethod()) || HttpMethods.PUT.equals(getMethod())))
239                 {
240                     int content_length = getContentLength();
241                     if (content_length != 0)
242                     {
243                         try
244                         {
245                             int maxFormContentSize = -1;
246                             int maxFormKeys = -1;
247 
248                             if (_context != null)
249                             {
250                                 maxFormContentSize = _context.getContextHandler().getMaxFormContentSize();
251                                 maxFormKeys = _context.getContextHandler().getMaxFormKeys();
252                             }
253                             else
254                             {
255                                 Number size = (Number)_connection.getConnector().getServer()
256                                         .getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize");
257                                 maxFormContentSize = size == null?200000:size.intValue();
258                                 Number keys = (Number)_connection.getConnector().getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys");
259                                 maxFormKeys = keys == null?1000:keys.intValue();
260                             }
261 
262                             if (content_length > maxFormContentSize && maxFormContentSize > 0)
263                             {
264                                 throw new IllegalStateException("Form too large" + content_length + ">" + maxFormContentSize);
265                             }
266                             InputStream in = getInputStream();
267 
268                             // Add form params to query params
269                             UrlEncoded.decodeTo(in,_baseParameters,encoding,content_length < 0?maxFormContentSize:-1,maxFormKeys);
270                         }
271                         catch (IOException e)
272                         {
273                             if (LOG.isDebugEnabled())
274                                 LOG.warn(e);
275                             else
276                                 LOG.warn(e.toString());
277                         }
278                     }
279                 }
280             }
281 
282             if (_parameters == null)
283                 _parameters = _baseParameters;
284             else if (_parameters != _baseParameters)
285             {
286                 // Merge parameters (needed if parameters extracted after a forward).
287                 Iterator iter = _baseParameters.entrySet().iterator();
288                 while (iter.hasNext())
289                 {
290                     Map.Entry entry = (Map.Entry)iter.next();
291                     String name = (String)entry.getKey();
292                     Object values = entry.getValue();
293                     for (int i = 0; i < LazyList.size(values); i++)
294                         _parameters.add(name,LazyList.get(values,i));
295                 }
296             }
297         }
298         finally
299         {
300             // ensure params always set (even if empty) after extraction
301             if (_parameters == null)
302                 _parameters = _baseParameters;
303         }
304     }
305 
306     /* ------------------------------------------------------------ */
307     public AsyncContext getAsyncContext()
308     {
309         if (_async.isInitial() && !_async.isAsyncStarted())
310             throw new IllegalStateException(_async.getStatusString());
311         return _async;
312     }
313 
314     /* ------------------------------------------------------------ */
315     public AsyncContinuation getAsyncContinuation()
316     {
317         return _async;
318     }
319 
320     /* ------------------------------------------------------------ */
321     /*
322      * @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
323      */
324     public Object getAttribute(String name)
325     {
326         if ("org.eclipse.jetty.io.EndPoint.maxIdleTime".equalsIgnoreCase(name))
327             return new Long(getConnection().getEndPoint().getMaxIdleTime());
328 
329         Object attr = (_attributes == null)?null:_attributes.getAttribute(name);
330         if (attr == null && Continuation.ATTRIBUTE.equals(name))
331             return _async;
332         return attr;
333     }
334 
335     /* ------------------------------------------------------------ */
336     /*
337      * @see javax.servlet.ServletRequest#getAttributeNames()
338      */
339     public Enumeration getAttributeNames()
340     {
341         if (_attributes == null)
342             return Collections.enumeration(Collections.EMPTY_LIST);
343 
344         return AttributesMap.getAttributeNamesCopy(_attributes);
345     }
346 
347     /* ------------------------------------------------------------ */
348     /*
349      */
350     public Attributes getAttributes()
351     {
352         if (_attributes == null)
353             _attributes = new AttributesMap();
354         return _attributes;
355     }
356 
357     /* ------------------------------------------------------------ */
358     /**
359      * Get the authentication.
360      *
361      * @return the authentication
362      */
363     public Authentication getAuthentication()
364     {
365         return _authentication;
366     }
367 
368     /* ------------------------------------------------------------ */
369     /*
370      * @see javax.servlet.http.HttpServletRequest#getAuthType()
371      */
372     public String getAuthType()
373     {
374         if (_authentication instanceof Authentication.Deferred)
375             _authentication = ((Authentication.Deferred)_authentication).authenticate(this);
376 
377         if (_authentication instanceof Authentication.User)
378             return ((Authentication.User)_authentication).getAuthMethod();
379         return null;
380     }
381 
382     /* ------------------------------------------------------------ */
383     /*
384      * @see javax.servlet.ServletRequest#getCharacterEncoding()
385      */
386     public String getCharacterEncoding()
387     {
388         return _characterEncoding;
389     }
390 
391     /* ------------------------------------------------------------ */
392     /**
393      * @return Returns the connection.
394      */
395     public AbstractHttpConnection getConnection()
396     {
397         return _connection;
398     }
399 
400     /* ------------------------------------------------------------ */
401     /*
402      * @see javax.servlet.ServletRequest#getContentLength()
403      */
404     public int getContentLength()
405     {
406         return (int)_connection.getRequestFields().getLongField(HttpHeaders.CONTENT_LENGTH_BUFFER);
407     }
408 
409     public long getContentRead()
410     {
411         if (_connection == null || _connection.getParser() == null)
412             return -1;
413 
414         return ((HttpParser)_connection.getParser()).getContentRead();
415     }
416 
417     /* ------------------------------------------------------------ */
418     /*
419      * @see javax.servlet.ServletRequest#getContentType()
420      */
421     public String getContentType()
422     {
423         return _connection.getRequestFields().getStringField(HttpHeaders.CONTENT_TYPE_BUFFER);
424     }
425 
426     /* ------------------------------------------------------------ */
427     /**
428      * @return The current {@link Context context} used for this request, or <code>null</code> if {@link #setContext} has not yet been called.
429      */
430     public Context getContext()
431     {
432         return _context;
433     }
434 
435     /* ------------------------------------------------------------ */
436     /*
437      * @see javax.servlet.http.HttpServletRequest#getContextPath()
438      */
439     public String getContextPath()
440     {
441         return _contextPath;
442     }
443 
444     /* ------------------------------------------------------------ */
445     /*
446      * @see javax.servlet.http.HttpServletRequest#getCookies()
447      */
448     public Cookie[] getCookies()
449     {
450         if (_cookiesExtracted)
451             return _cookies == null?null:_cookies.getCookies();
452 
453         _cookiesExtracted = true;
454 
455         Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.COOKIE_BUFFER);
456 
457         // Handle no cookies
458         if (enm != null)
459         {
460             if (_cookies == null)
461                 _cookies = new CookieCutter();
462 
463             while (enm.hasMoreElements())
464             {
465                 String c = (String)enm.nextElement();
466                 _cookies.addCookieField(c);
467             }
468         }
469 
470         return _cookies == null?null:_cookies.getCookies();
471     }
472 
473     /* ------------------------------------------------------------ */
474     /*
475      * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String)
476      */
477     public long getDateHeader(String name)
478     {
479         return _connection.getRequestFields().getDateField(name);
480     }
481 
482     /* ------------------------------------------------------------ */
483     public DispatcherType getDispatcherType()
484     {
485         return _dispatcherType;
486     }
487 
488     /* ------------------------------------------------------------ */
489     /*
490      * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
491      */
492     public String getHeader(String name)
493     {
494         return _connection.getRequestFields().getStringField(name);
495     }
496 
497     /* ------------------------------------------------------------ */
498     /*
499      * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
500      */
501     public Enumeration getHeaderNames()
502     {
503         return _connection.getRequestFields().getFieldNames();
504     }
505 
506     /* ------------------------------------------------------------ */
507     /*
508      * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
509      */
510     public Enumeration getHeaders(String name)
511     {
512         Enumeration e = _connection.getRequestFields().getValues(name);
513         if (e == null)
514             return Collections.enumeration(Collections.EMPTY_LIST);
515         return e;
516     }
517 
518     /* ------------------------------------------------------------ */
519     /**
520      * @return Returns the inputState.
521      */
522     public int getInputState()
523     {
524         return _inputState;
525     }
526 
527     /* ------------------------------------------------------------ */
528     /*
529      * @see javax.servlet.ServletRequest#getInputStream()
530      */
531     public ServletInputStream getInputStream() throws IOException
532     {
533         if (_inputState != __NONE && _inputState != _STREAM)
534             throw new IllegalStateException("READER");
535         _inputState = _STREAM;
536         return _connection.getInputStream();
537     }
538 
539     /* ------------------------------------------------------------ */
540     /*
541      * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String)
542      */
543     public int getIntHeader(String name)
544     {
545         return (int)_connection.getRequestFields().getLongField(name);
546     }
547 
548     /* ------------------------------------------------------------ */
549     /*
550      * @see javax.servlet.ServletRequest#getLocalAddr()
551      */
552     public String getLocalAddr()
553     {
554         return _endp == null?null:_endp.getLocalAddr();
555     }
556 
557     /* ------------------------------------------------------------ */
558     /*
559      * @see javax.servlet.ServletRequest#getLocale()
560      */
561     public Locale getLocale()
562     {
563         Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.ACCEPT_LANGUAGE,HttpFields.__separators);
564 
565         // handle no locale
566         if (enm == null || !enm.hasMoreElements())
567             return Locale.getDefault();
568 
569         // sort the list in quality order
570         List acceptLanguage = HttpFields.qualityList(enm);
571         if (acceptLanguage.size() == 0)
572             return Locale.getDefault();
573 
574         int size = acceptLanguage.size();
575 
576         if (size > 0)
577         {
578             String language = (String)acceptLanguage.get(0);
579             language = HttpFields.valueParameters(language,null);
580             String country = "";
581             int dash = language.indexOf('-');
582             if (dash > -1)
583             {
584                 country = language.substring(dash + 1).trim();
585                 language = language.substring(0,dash).trim();
586             }
587             return new Locale(language,country);
588         }
589 
590         return Locale.getDefault();
591     }
592 
593     /* ------------------------------------------------------------ */
594     /*
595      * @see javax.servlet.ServletRequest#getLocales()
596      */
597     public Enumeration getLocales()
598     {
599 
600         Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.ACCEPT_LANGUAGE,HttpFields.__separators);
601 
602         // handle no locale
603         if (enm == null || !enm.hasMoreElements())
604             return Collections.enumeration(__defaultLocale);
605 
606         // sort the list in quality order
607         List acceptLanguage = HttpFields.qualityList(enm);
608 
609         if (acceptLanguage.size() == 0)
610             return Collections.enumeration(__defaultLocale);
611 
612         Object langs = null;
613         int size = acceptLanguage.size();
614 
615         // convert to locals
616         for (int i = 0; i < size; i++)
617         {
618             String language = (String)acceptLanguage.get(i);
619             language = HttpFields.valueParameters(language,null);
620             String country = "";
621             int dash = language.indexOf('-');
622             if (dash > -1)
623             {
624                 country = language.substring(dash + 1).trim();
625                 language = language.substring(0,dash).trim();
626             }
627             langs = LazyList.ensureSize(langs,size);
628             langs = LazyList.add(langs,new Locale(language,country));
629         }
630 
631         if (LazyList.size(langs) == 0)
632             return Collections.enumeration(__defaultLocale);
633 
634         return Collections.enumeration(LazyList.getList(langs));
635     }
636 
637     /* ------------------------------------------------------------ */
638     /*
639      * @see javax.servlet.ServletRequest#getLocalName()
640      */
641     public String getLocalName()
642     {
643         if (_endp == null)
644             return null;
645         if (_dns)
646             return _endp.getLocalHost();
647 
648         String local = _endp.getLocalAddr();
649         if (local != null && local.indexOf(':') >= 0)
650             local = "[" + local + "]";
651         return local;
652     }
653 
654     /* ------------------------------------------------------------ */
655     /*
656      * @see javax.servlet.ServletRequest#getLocalPort()
657      */
658     public int getLocalPort()
659     {
660         return _endp == null?0:_endp.getLocalPort();
661     }
662 
663     /* ------------------------------------------------------------ */
664     /*
665      * @see javax.servlet.http.HttpServletRequest#getMethod()
666      */
667     public String getMethod()
668     {
669         return _method;
670     }
671 
672     /* ------------------------------------------------------------ */
673     /*
674      * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
675      */
676     public String getParameter(String name)
677     {
678         if (!_paramsExtracted)
679             extractParameters();
680         return (String)_parameters.getValue(name,0);
681     }
682 
683     /* ------------------------------------------------------------ */
684     /*
685      * @see javax.servlet.ServletRequest#getParameterMap()
686      */
687     public Map getParameterMap()
688     {
689         if (!_paramsExtracted)
690             extractParameters();
691 
692         return Collections.unmodifiableMap(_parameters.toStringArrayMap());
693     }
694 
695     /* ------------------------------------------------------------ */
696     /*
697      * @see javax.servlet.ServletRequest#getParameterNames()
698      */
699     public Enumeration getParameterNames()
700     {
701         if (!_paramsExtracted)
702             extractParameters();
703         return Collections.enumeration(_parameters.keySet());
704     }
705 
706     /* ------------------------------------------------------------ */
707     /**
708      * @return Returns the parameters.
709      */
710     public MultiMap<String> getParameters()
711     {
712         return _parameters;
713     }
714 
715     /* ------------------------------------------------------------ */
716     /*
717      * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
718      */
719     public String[] getParameterValues(String name)
720     {
721         if (!_paramsExtracted)
722             extractParameters();
723         List<Object> vals = _parameters.getValues(name);
724         if (vals == null)
725             return null;
726         return vals.toArray(new String[vals.size()]);
727     }
728 
729     /* ------------------------------------------------------------ */
730     /*
731      * @see javax.servlet.http.HttpServletRequest#getPathInfo()
732      */
733     public String getPathInfo()
734     {
735         return _pathInfo;
736     }
737 
738     /* ------------------------------------------------------------ */
739     /*
740      * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
741      */
742     public String getPathTranslated()
743     {
744         if (_pathInfo == null || _context == null)
745             return null;
746         return _context.getRealPath(_pathInfo);
747     }
748 
749     /* ------------------------------------------------------------ */
750     /*
751      * @see javax.servlet.ServletRequest#getProtocol()
752      */
753     public String getProtocol()
754     {
755         return _protocol;
756     }
757 
758     /* ------------------------------------------------------------ */
759     public String getQueryEncoding()
760     {
761         return _queryEncoding;
762     }
763 
764     /* ------------------------------------------------------------ */
765     /*
766      * @see javax.servlet.http.HttpServletRequest#getQueryString()
767      */
768     public String getQueryString()
769     {
770         if (_queryString == null && _uri != null)
771         {
772             if (_queryEncoding == null)
773                 _queryString = _uri.getQuery();
774             else
775                 _queryString = _uri.getQuery(_queryEncoding);
776         }
777         return _queryString;
778     }
779 
780     /* ------------------------------------------------------------ */
781     /*
782      * @see javax.servlet.ServletRequest#getReader()
783      */
784     public BufferedReader getReader() throws IOException
785     {
786         if (_inputState != __NONE && _inputState != __READER)
787             throw new IllegalStateException("STREAMED");
788 
789         if (_inputState == __READER)
790             return _reader;
791 
792         String encoding = getCharacterEncoding();
793         if (encoding == null)
794             encoding = StringUtil.__ISO_8859_1;
795 
796         if (_reader == null || !encoding.equalsIgnoreCase(_readerEncoding))
797         {
798             final ServletInputStream in = getInputStream();
799             _readerEncoding = encoding;
800             _reader = new BufferedReader(new InputStreamReader(in,encoding))
801             {
802                 @Override
803                 public void close() throws IOException
804                 {
805                     in.close();
806                 }
807             };
808         }
809         _inputState = __READER;
810         return _reader;
811     }
812 
813     /* ------------------------------------------------------------ */
814     /*
815      * @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
816      */
817     public String getRealPath(String path)
818     {
819         if (_context == null)
820             return null;
821         return _context.getRealPath(path);
822     }
823 
824     /* ------------------------------------------------------------ */
825     /*
826      * @see javax.servlet.ServletRequest#getRemoteAddr()
827      */
828     public String getRemoteAddr()
829     {
830         if (_remoteAddr != null)
831             return _remoteAddr;
832         return _endp == null?null:_endp.getRemoteAddr();
833     }
834 
835     /* ------------------------------------------------------------ */
836     /*
837      * @see javax.servlet.ServletRequest#getRemoteHost()
838      */
839     public String getRemoteHost()
840     {
841         if (_dns)
842         {
843             if (_remoteHost != null)
844             {
845                 return _remoteHost;
846             }
847             return _endp == null?null:_endp.getRemoteHost();
848         }
849         return getRemoteAddr();
850     }
851 
852     /* ------------------------------------------------------------ */
853     /*
854      * @see javax.servlet.ServletRequest#getRemotePort()
855      */
856     public int getRemotePort()
857     {
858         return _endp == null?0:_endp.getRemotePort();
859     }
860 
861     /* ------------------------------------------------------------ */
862     /*
863      * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
864      */
865     public String getRemoteUser()
866     {
867         Principal p = getUserPrincipal();
868         if (p == null)
869             return null;
870         return p.getName();
871     }
872 
873     /* ------------------------------------------------------------ */
874     /*
875      * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
876      */
877     public RequestDispatcher getRequestDispatcher(String path)
878     {
879         if (path == null || _context == null)
880             return null;
881 
882         // handle relative path
883         if (!path.startsWith("/"))
884         {
885             String relTo = URIUtil.addPaths(_servletPath,_pathInfo);
886             int slash = relTo.lastIndexOf("/");
887             if (slash > 1)
888                 relTo = relTo.substring(0,slash + 1);
889             else
890                 relTo = "/";
891             path = URIUtil.addPaths(relTo,path);
892         }
893 
894         return _context.getRequestDispatcher(path);
895     }
896 
897     /* ------------------------------------------------------------ */
898     /*
899      * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
900      */
901     public String getRequestedSessionId()
902     {
903         return _requestedSessionId;
904     }
905 
906     /* ------------------------------------------------------------ */
907     /*
908      * @see javax.servlet.http.HttpServletRequest#getRequestURI()
909      */
910     public String getRequestURI()
911     {
912         if (_requestURI == null && _uri != null)
913             _requestURI = _uri.getPathAndParam();
914         return _requestURI;
915     }
916 
917     /* ------------------------------------------------------------ */
918     /*
919      * @see javax.servlet.http.HttpServletRequest#getRequestURL()
920      */
921     public StringBuffer getRequestURL()
922     {
923         final StringBuffer url = new StringBuffer(48);
924         synchronized (url)
925         {
926             String scheme = getScheme();
927             int port = getServerPort();
928 
929             url.append(scheme);
930             url.append("://");
931             url.append(getServerName());
932             if (_port > 0 && ((scheme.equalsIgnoreCase(URIUtil.HTTP) && port != 80) || (scheme.equalsIgnoreCase(URIUtil.HTTPS) && port != 443)))
933             {
934                 url.append(':');
935                 url.append(_port);
936             }
937 
938             url.append(getRequestURI());
939             return url;
940         }
941     }
942 
943     /* ------------------------------------------------------------ */
944     public Response getResponse()
945     {
946         return _connection._response;
947     }
948 
949     /* ------------------------------------------------------------ */
950     /**
951      * Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port number, and, but it does not include a
952      * path.
953      * <p>
954      * Because this method returns a <code>StringBuffer</code>, not a string, you can modify the URL easily, for example, to append path and query parameters.
955      *
956      * This method is useful for creating redirect messages and for reporting errors.
957      *
958      * @return "scheme://host:port"
959      */
960     public StringBuilder getRootURL()
961     {
962         StringBuilder url = new StringBuilder(48);
963         String scheme = getScheme();
964         int port = getServerPort();
965 
966         url.append(scheme);
967         url.append("://");
968         url.append(getServerName());
969 
970         if (port > 0 && ((scheme.equalsIgnoreCase("http") && port != 80) || (scheme.equalsIgnoreCase("https") && port != 443)))
971         {
972             url.append(':');
973             url.append(port);
974         }
975         return url;
976     }
977 
978     /* ------------------------------------------------------------ */
979     /*
980      * @see javax.servlet.ServletRequest#getScheme()
981      */
982     public String getScheme()
983     {
984         return _scheme;
985     }
986 
987     /* ------------------------------------------------------------ */
988     /*
989      * @see javax.servlet.ServletRequest#getServerName()
990      */
991     public String getServerName()
992     {
993         // Return already determined host
994         if (_serverName != null)
995             return _serverName;
996 
997         if (_uri == null)
998             throw new IllegalStateException("No uri");
999 
1000         // Return host from absolute URI
1001         _serverName = _uri.getHost();
1002         _port = _uri.getPort();
1003         if (_serverName != null)
1004             return _serverName;
1005 
1006         // Return host from header field
1007         Buffer hostPort = _connection.getRequestFields().get(HttpHeaders.HOST_BUFFER);
1008         if (hostPort != null)
1009         {
1010             loop: for (int i = hostPort.putIndex(); i-- > hostPort.getIndex();)
1011             {
1012                 char ch = (char)(0xff & hostPort.peek(i));
1013                 switch (ch)
1014                 {
1015                     case ']':
1016                         break loop;
1017 
1018                     case ':':
1019                         _serverName = BufferUtil.to8859_1_String(hostPort.peek(hostPort.getIndex(),i - hostPort.getIndex()));
1020                         try
1021                         {
1022                             _port = BufferUtil.toInt(hostPort.peek(i + 1,hostPort.putIndex() - i - 1));
1023                         }
1024                         catch (NumberFormatException e)
1025                         {
1026                             try
1027                             {
1028                                 if (_connection != null)
1029                                     _connection._generator.sendError(HttpStatus.BAD_REQUEST_400,"Bad Host header",null,true);
1030                             }
1031                             catch (IOException e1)
1032                             {
1033                                 throw new RuntimeException(e1);
1034                             }
1035                         }
1036                         return _serverName;
1037                 }
1038             }
1039             if (_serverName == null || _port < 0)
1040             {
1041                 _serverName = BufferUtil.to8859_1_String(hostPort);
1042                 _port = 0;
1043             }
1044 
1045             return _serverName;
1046         }
1047 
1048         // Return host from connection
1049         if (_connection != null)
1050         {
1051             _serverName = getLocalName();
1052             _port = getLocalPort();
1053             if (_serverName != null && !StringUtil.ALL_INTERFACES.equals(_serverName))
1054                 return _serverName;
1055         }
1056 
1057         // Return the local host
1058         try
1059         {
1060             _serverName = InetAddress.getLocalHost().getHostAddress();
1061         }
1062         catch (java.net.UnknownHostException e)
1063         {
1064             LOG.ignore(e);
1065         }
1066         return _serverName;
1067     }
1068 
1069     /* ------------------------------------------------------------ */
1070     /*
1071      * @see javax.servlet.ServletRequest#getServerPort()
1072      */
1073     public int getServerPort()
1074     {
1075         if (_port <= 0)
1076         {
1077             if (_serverName == null)
1078                 getServerName();
1079 
1080             if (_port <= 0)
1081             {
1082                 if (_serverName != null && _uri != null)
1083                     _port = _uri.getPort();
1084                 else
1085                     _port = _endp == null?0:_endp.getLocalPort();
1086             }
1087         }
1088 
1089         if (_port <= 0)
1090         {
1091             if (getScheme().equalsIgnoreCase(URIUtil.HTTPS))
1092                 return 443;
1093             return 80;
1094         }
1095         return _port;
1096     }
1097 
1098     /* ------------------------------------------------------------ */
1099     public ServletContext getServletContext()
1100     {
1101         return _context;
1102     }
1103 
1104     /* ------------------------------------------------------------ */
1105     /*
1106      */
1107     public String getServletName()
1108     {
1109         if (_scope != null)
1110             return _scope.getName();
1111         return null;
1112     }
1113 
1114     /* ------------------------------------------------------------ */
1115     /*
1116      * @see javax.servlet.http.HttpServletRequest#getServletPath()
1117      */
1118     public String getServletPath()
1119     {
1120         if (_servletPath == null)
1121             _servletPath = "";
1122         return _servletPath;
1123     }
1124 
1125     /* ------------------------------------------------------------ */
1126     public ServletResponse getServletResponse()
1127     {
1128         return _connection.getResponse();
1129     }
1130 
1131     /* ------------------------------------------------------------ */
1132     /*
1133      * @see javax.servlet.http.HttpServletRequest#getSession()
1134      */
1135     public HttpSession getSession()
1136     {
1137         return getSession(true);
1138     }
1139 
1140     /* ------------------------------------------------------------ */
1141     /*
1142      * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
1143      */
1144     public HttpSession getSession(boolean create)
1145     {
1146         if (_session != null)
1147         {
1148             if (_sessionManager != null && !_sessionManager.isValid(_session))
1149                 _session = null;
1150             else
1151                 return _session;
1152         }
1153 
1154         if (!create)
1155             return null;
1156 
1157         if (_sessionManager == null)
1158             throw new IllegalStateException("No SessionManager");
1159 
1160         _session = _sessionManager.newHttpSession(this);
1161         HttpCookie cookie = _sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
1162         if (cookie != null)
1163             _connection.getResponse().addCookie(cookie);
1164 
1165         return _session;
1166     }
1167 
1168     /* ------------------------------------------------------------ */
1169     /**
1170      * @return Returns the sessionManager.
1171      */
1172     public SessionManager getSessionManager()
1173     {
1174         return _sessionManager;
1175     }
1176 
1177     /* ------------------------------------------------------------ */
1178     /**
1179      * Get Request TimeStamp
1180      *
1181      * @return The time that the request was received.
1182      */
1183     public long getTimeStamp()
1184     {
1185         return _timeStamp;
1186     }
1187 
1188     /* ------------------------------------------------------------ */
1189     /**
1190      * Get Request TimeStamp
1191      *
1192      * @return The time that the request was received.
1193      */
1194     public Buffer getTimeStampBuffer()
1195     {
1196         if (_timeStampBuffer == null && _timeStamp > 0)
1197             _timeStampBuffer = HttpFields.__dateCache.formatBuffer(_timeStamp);
1198         return _timeStampBuffer;
1199     }
1200 
1201     /* ------------------------------------------------------------ */
1202     /**
1203      * @return Returns the uri.
1204      */
1205     public HttpURI getUri()
1206     {
1207         return _uri;
1208     }
1209 
1210     /* ------------------------------------------------------------ */
1211     public UserIdentity getUserIdentity()
1212     {
1213         if (_authentication instanceof Authentication.Deferred)
1214             setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1215 
1216         if (_authentication instanceof Authentication.User)
1217             return ((Authentication.User)_authentication).getUserIdentity();
1218         return null;
1219     }
1220 
1221     /* ------------------------------------------------------------ */
1222     /**
1223      * @return The resolved user Identity, which may be null if the {@link Authentication} is not {@link Authentication.User} (eg.
1224      *         {@link Authentication.Deferred}).
1225      */
1226     public UserIdentity getResolvedUserIdentity()
1227     {
1228         if (_authentication instanceof Authentication.User)
1229             return ((Authentication.User)_authentication).getUserIdentity();
1230         return null;
1231     }
1232 
1233     /* ------------------------------------------------------------ */
1234     public UserIdentity.Scope getUserIdentityScope()
1235     {
1236         return _scope;
1237     }
1238 
1239     /* ------------------------------------------------------------ */
1240     /*
1241      * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
1242      */
1243     public Principal getUserPrincipal()
1244     {
1245         if (_authentication instanceof Authentication.Deferred)
1246             setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1247 
1248         if (_authentication instanceof Authentication.User)
1249         {
1250             UserIdentity user = ((Authentication.User)_authentication).getUserIdentity();
1251             return user.getUserPrincipal();
1252         }
1253         return null;
1254     }
1255 
1256     /* ------------------------------------------------------------ */
1257     /**
1258      * Get timestamp of the request dispatch
1259      *
1260      * @return timestamp
1261      */
1262     public long getDispatchTime()
1263     {
1264         return _dispatchTime;
1265     }
1266 
1267     /* ------------------------------------------------------------ */
1268     public boolean isHandled()
1269     {
1270         return _handled;
1271     }
1272 
1273     /* ------------------------------------------------------------ */
1274     public boolean isAsyncSupported()
1275     {
1276         return _asyncSupported;
1277     }
1278 
1279     /* ------------------------------------------------------------ */
1280     /*
1281      * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
1282      */
1283     public boolean isRequestedSessionIdFromCookie()
1284     {
1285         return _requestedSessionId != null && _requestedSessionIdFromCookie;
1286     }
1287 
1288     /* ------------------------------------------------------------ */
1289     /*
1290      * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
1291      */
1292     public boolean isRequestedSessionIdFromUrl()
1293     {
1294         return _requestedSessionId != null && !_requestedSessionIdFromCookie;
1295     }
1296 
1297     /* ------------------------------------------------------------ */
1298     /*
1299      * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
1300      */
1301     public boolean isRequestedSessionIdFromURL()
1302     {
1303         return _requestedSessionId != null && !_requestedSessionIdFromCookie;
1304     }
1305 
1306     /* ------------------------------------------------------------ */
1307     /*
1308      * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
1309      */
1310     public boolean isRequestedSessionIdValid()
1311     {
1312         if (_requestedSessionId == null)
1313             return false;
1314 
1315         HttpSession session = getSession(false);
1316         return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session)));
1317     }
1318 
1319     /* ------------------------------------------------------------ */
1320     /*
1321      * @see javax.servlet.ServletRequest#isSecure()
1322      */
1323     public boolean isSecure()
1324     {
1325         return _connection.isConfidential(this);
1326     }
1327 
1328     /* ------------------------------------------------------------ */
1329     /*
1330      * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
1331      */
1332     public boolean isUserInRole(String role)
1333     {
1334         if (_authentication instanceof Authentication.Deferred)
1335             setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1336 
1337         if (_authentication instanceof Authentication.User)
1338             return ((Authentication.User)_authentication).isUserInRole(_scope,role);
1339         return false;
1340     }
1341 
1342     /* ------------------------------------------------------------ */
1343     public HttpSession recoverNewSession(Object key)
1344     {
1345         if (_savedNewSessions == null)
1346             return null;
1347         return _savedNewSessions.get(key);
1348     }
1349 
1350     /* ------------------------------------------------------------ */
1351     protected void recycle()
1352     {
1353         if (_inputState == __READER)
1354         {
1355             try
1356             {
1357                 int r = _reader.read();
1358                 while (r != -1)
1359                     r = _reader.read();
1360             }
1361             catch (Exception e)
1362             {
1363                 LOG.ignore(e);
1364                 _reader = null;
1365             }
1366         }
1367 
1368         setAuthentication(Authentication.NOT_CHECKED);
1369         _async.recycle();
1370         _asyncSupported = true;
1371         _handled = false;
1372         if (_context != null)
1373             throw new IllegalStateException("Request in context!");
1374         if (_attributes != null)
1375             _attributes.clearAttributes();
1376         _characterEncoding = null;
1377         if (_cookies != null)
1378             _cookies.reset();
1379         _cookiesExtracted = false;
1380         _context = null;
1381         _serverName = null;
1382         _method = null;
1383         _pathInfo = null;
1384         _port = 0;
1385         _protocol = HttpVersions.HTTP_1_1;
1386         _queryEncoding = null;
1387         _queryString = null;
1388         _requestedSessionId = null;
1389         _requestedSessionIdFromCookie = false;
1390         _session = null;
1391         _sessionManager = null;
1392         _requestURI = null;
1393         _scope = null;
1394         _scheme = URIUtil.HTTP;
1395         _servletPath = null;
1396         _timeStamp = 0;
1397         _timeStampBuffer = null;
1398         _uri = null;
1399         if (_baseParameters != null)
1400             _baseParameters.clear();
1401         _parameters = null;
1402         _paramsExtracted = false;
1403         _inputState = __NONE;
1404 
1405         if (_savedNewSessions != null)
1406             _savedNewSessions.clear();
1407         _savedNewSessions = null;
1408     }
1409 
1410     /* ------------------------------------------------------------ */
1411     /*
1412      * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
1413      */
1414     public void removeAttribute(String name)
1415     {
1416         Object old_value = _attributes == null?null:_attributes.getAttribute(name);
1417 
1418         if (_attributes != null)
1419             _attributes.removeAttribute(name);
1420 
1421         if (old_value != null)
1422         {
1423             if (_requestAttributeListeners != null)
1424             {
1425                 final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value);
1426                 final int size = LazyList.size(_requestAttributeListeners);
1427                 for (int i = 0; i < size; i++)
1428                 {
1429                     final EventListener listener = (ServletRequestAttributeListener)LazyList.get(_requestAttributeListeners,i);
1430                     if (listener instanceof ServletRequestAttributeListener)
1431                     {
1432                         final ServletRequestAttributeListener l = (ServletRequestAttributeListener)listener;
1433                         l.attributeRemoved(event);
1434                     }
1435                 }
1436             }
1437         }
1438     }
1439 
1440     /* ------------------------------------------------------------ */
1441     public void removeEventListener(final EventListener listener)
1442     {
1443         _requestAttributeListeners = LazyList.remove(_requestAttributeListeners,listener);
1444     }
1445 
1446     /* ------------------------------------------------------------ */
1447     public void saveNewSession(Object key, HttpSession session)
1448     {
1449         if (_savedNewSessions == null)
1450             _savedNewSessions = new HashMap<Object, HttpSession>();
1451         _savedNewSessions.put(key,session);
1452     }
1453 
1454     /* ------------------------------------------------------------ */
1455     public void setAsyncSupported(boolean supported)
1456     {
1457         _asyncSupported = supported;
1458     }
1459 
1460     /* ------------------------------------------------------------ */
1461     /*
1462      * Set a request attribute. if the attribute name is "org.eclipse.jetty.server.server.Request.queryEncoding" then the value is also passed in a call to
1463      * {@link #setQueryEncoding}. <p> if the attribute name is "org.eclipse.jetty.server.server.ResponseBuffer", then the response buffer is flushed with @{link
1464      * #flushResponseBuffer} <p> if the attribute name is "org.eclipse.jetty.io.EndPoint.maxIdleTime", then the value is passed to the associated {@link
1465      * EndPoint#setMaxIdleTime}.
1466      *
1467      * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
1468      */
1469     public void setAttribute(String name, Object value)
1470     {
1471         Object old_value = _attributes == null?null:_attributes.getAttribute(name);
1472 
1473         if (name.startsWith("org.eclipse.jetty."))
1474         {
1475             if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name))
1476                 setQueryEncoding(value == null?null:value.toString());
1477             else if ("org.eclipse.jetty.server.sendContent".equals(name))
1478             {
1479                 try
1480                 {
1481                     ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendContent(value);
1482                 }
1483                 catch (IOException e)
1484                 {
1485                     throw new RuntimeException(e);
1486                 }
1487             }
1488             else if ("org.eclipse.jetty.server.ResponseBuffer".equals(name))
1489             {
1490                 try
1491                 {
1492                     final ByteBuffer byteBuffer = (ByteBuffer)value;
1493                     synchronized (byteBuffer)
1494                     {
1495                         NIOBuffer buffer = byteBuffer.isDirect()?new DirectNIOBuffer(byteBuffer,true):new IndirectNIOBuffer(byteBuffer,true);
1496                         ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendResponse(buffer);
1497                     }
1498                 }
1499                 catch (IOException e)
1500                 {
1501                     throw new RuntimeException(e);
1502                 }
1503             }
1504             else if ("org.eclipse.jetty.io.EndPoint.maxIdleTime".equalsIgnoreCase(name))
1505             {
1506                 try
1507                 {
1508                     getConnection().getEndPoint().setMaxIdleTime(Integer.valueOf(value.toString()));
1509                 }
1510                 catch (IOException e)
1511                 {
1512                     throw new RuntimeException(e);
1513                 }
1514             }
1515         }
1516 
1517         if (_attributes == null)
1518             _attributes = new AttributesMap();
1519         _attributes.setAttribute(name,value);
1520 
1521         if (_requestAttributeListeners != null)
1522         {
1523             final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value == null?value:old_value);
1524             final int size = LazyList.size(_requestAttributeListeners);
1525             for (int i = 0; i < size; i++)
1526             {
1527                 final EventListener listener = (ServletRequestAttributeListener)LazyList.get(_requestAttributeListeners,i);
1528                 if (listener instanceof ServletRequestAttributeListener)
1529                 {
1530                     final ServletRequestAttributeListener l = (ServletRequestAttributeListener)listener;
1531 
1532                     if (old_value == null)
1533                         l.attributeAdded(event);
1534                     else if (value == null)
1535                         l.attributeRemoved(event);
1536                     else
1537                         l.attributeReplaced(event);
1538                 }
1539             }
1540         }
1541     }
1542 
1543     /* ------------------------------------------------------------ */
1544     /*
1545      */
1546     public void setAttributes(Attributes attributes)
1547     {
1548         _attributes = attributes;
1549     }
1550 
1551     /* ------------------------------------------------------------ */
1552 
1553     /* ------------------------------------------------------------ */
1554     /**
1555      * Set the authentication.
1556      *
1557      * @param authentication
1558      *            the authentication to set
1559      */
1560     public void setAuthentication(Authentication authentication)
1561     {
1562         _authentication = authentication;
1563     }
1564 
1565     /* ------------------------------------------------------------ */
1566     /*
1567      * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
1568      */
1569     public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException
1570     {
1571         if (_inputState != __NONE)
1572             return;
1573 
1574         _characterEncoding = encoding;
1575 
1576         // check encoding is supported
1577         if (!StringUtil.isUTF8(encoding))
1578             // noinspection ResultOfMethodCallIgnored
1579             "".getBytes(encoding);
1580     }
1581 
1582     /* ------------------------------------------------------------ */
1583     /*
1584      * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
1585      */
1586     public void setCharacterEncodingUnchecked(String encoding)
1587     {
1588         _characterEncoding = encoding;
1589     }
1590 
1591     /* ------------------------------------------------------------ */
1592     // final so we can safely call this from constructor
1593     protected final void setConnection(AbstractHttpConnection connection)
1594     {
1595         _connection = connection;
1596         _async.setConnection(connection);
1597         _endp = connection.getEndPoint();
1598         _dns = connection.getResolveNames();
1599     }
1600 
1601     /* ------------------------------------------------------------ */
1602     /*
1603      * @see javax.servlet.ServletRequest#getContentType()
1604      */
1605     public void setContentType(String contentType)
1606     {
1607         _connection.getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,contentType);
1608 
1609     }
1610 
1611     /* ------------------------------------------------------------ */
1612     /**
1613      * Set request context
1614      *
1615      * @param context
1616      *            context object
1617      */
1618     public void setContext(Context context)
1619     {
1620         _newContext = _context != context;
1621         _context = context;
1622     }
1623 
1624     /* ------------------------------------------------------------ */
1625     /**
1626      * @return True if this is the first call of {@link #takeNewContext()} since the last
1627      *         {@link #setContext(org.eclipse.jetty.server.handler.ContextHandler.Context)} call.
1628      */
1629     public boolean takeNewContext()
1630     {
1631         boolean nc = _newContext;
1632         _newContext = false;
1633         return nc;
1634     }
1635 
1636     /* ------------------------------------------------------------ */
1637     /**
1638      * Sets the "context path" for this request
1639      *
1640      * @see HttpServletRequest#getContextPath()
1641      */
1642     public void setContextPath(String contextPath)
1643     {
1644         _contextPath = contextPath;
1645     }
1646 
1647     /* ------------------------------------------------------------ */
1648     /**
1649      * @param cookies
1650      *            The cookies to set.
1651      */
1652     public void setCookies(Cookie[] cookies)
1653     {
1654         if (_cookies == null)
1655             _cookies = new CookieCutter();
1656         _cookies.setCookies(cookies);
1657     }
1658 
1659     /* ------------------------------------------------------------ */
1660     public void setDispatcherType(DispatcherType type)
1661     {
1662         _dispatcherType = type;
1663     }
1664 
1665     /* ------------------------------------------------------------ */
1666     public void setHandled(boolean h)
1667     {
1668         _handled = h;
1669     }
1670 
1671     /* ------------------------------------------------------------ */
1672     /**
1673      * @param method
1674      *            The method to set.
1675      */
1676     public void setMethod(String method)
1677     {
1678         _method = method;
1679     }
1680 
1681     /* ------------------------------------------------------------ */
1682     /**
1683      * @param parameters
1684      *            The parameters to set.
1685      */
1686     public void setParameters(MultiMap<String> parameters)
1687     {
1688         _parameters = (parameters == null)?_baseParameters:parameters;
1689         if (_paramsExtracted && _parameters == null)
1690             throw new IllegalStateException();
1691     }
1692 
1693     /* ------------------------------------------------------------ */
1694     /**
1695      * @param pathInfo
1696      *            The pathInfo to set.
1697      */
1698     public void setPathInfo(String pathInfo)
1699     {
1700         _pathInfo = pathInfo;
1701     }
1702 
1703     /* ------------------------------------------------------------ */
1704     /**
1705      * @param protocol
1706      *            The protocol to set.
1707      */
1708     public void setProtocol(String protocol)
1709     {
1710         _protocol = protocol;
1711     }
1712 
1713     /* ------------------------------------------------------------ */
1714     /**
1715      * Set the character encoding used for the query string. This call will effect the return of getQueryString and getParamaters. It must be called before any
1716      * geParameter methods.
1717      *
1718      * The request attribute "org.eclipse.jetty.server.server.Request.queryEncoding" may be set as an alternate method of calling setQueryEncoding.
1719      *
1720      * @param queryEncoding
1721      */
1722     public void setQueryEncoding(String queryEncoding)
1723     {
1724         _queryEncoding = queryEncoding;
1725         _queryString = null;
1726     }
1727 
1728     /* ------------------------------------------------------------ */
1729     /**
1730      * @param queryString
1731      *            The queryString to set.
1732      */
1733     public void setQueryString(String queryString)
1734     {
1735         _queryString = queryString;
1736     }
1737 
1738     /* ------------------------------------------------------------ */
1739     /**
1740      * @param addr
1741      *            The address to set.
1742      */
1743     public void setRemoteAddr(String addr)
1744     {
1745         _remoteAddr = addr;
1746     }
1747 
1748     /* ------------------------------------------------------------ */
1749     /**
1750      * @param host
1751      *            The host to set.
1752      */
1753     public void setRemoteHost(String host)
1754     {
1755         _remoteHost = host;
1756     }
1757 
1758     /* ------------------------------------------------------------ */
1759     /**
1760      * @param requestedSessionId
1761      *            The requestedSessionId to set.
1762      */
1763     public void setRequestedSessionId(String requestedSessionId)
1764     {
1765         _requestedSessionId = requestedSessionId;
1766     }
1767 
1768     /* ------------------------------------------------------------ */
1769     /**
1770      * @param requestedSessionIdCookie
1771      *            The requestedSessionIdCookie to set.
1772      */
1773     public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie)
1774     {
1775         _requestedSessionIdFromCookie = requestedSessionIdCookie;
1776     }
1777 
1778     /* ------------------------------------------------------------ */
1779     /**
1780      * @param requestURI
1781      *            The requestURI to set.
1782      */
1783     public void setRequestURI(String requestURI)
1784     {
1785         _requestURI = requestURI;
1786     }
1787 
1788     /* ------------------------------------------------------------ */
1789     /**
1790      * @param scheme
1791      *            The scheme to set.
1792      */
1793     public void setScheme(String scheme)
1794     {
1795         _scheme = scheme;
1796     }
1797 
1798     /* ------------------------------------------------------------ */
1799     /**
1800      * @param host
1801      *            The host to set.
1802      */
1803     public void setServerName(String host)
1804     {
1805         _serverName = host;
1806     }
1807 
1808     /* ------------------------------------------------------------ */
1809     /**
1810      * @param port
1811      *            The port to set.
1812      */
1813     public void setServerPort(int port)
1814     {
1815         _port = port;
1816     }
1817 
1818     /* ------------------------------------------------------------ */
1819     /**
1820      * @param servletPath
1821      *            The servletPath to set.
1822      */
1823     public void setServletPath(String servletPath)
1824     {
1825         _servletPath = servletPath;
1826     }
1827 
1828     /* ------------------------------------------------------------ */
1829     /**
1830      * @param session
1831      *            The session to set.
1832      */
1833     public void setSession(HttpSession session)
1834     {
1835         _session = session;
1836     }
1837 
1838     /* ------------------------------------------------------------ */
1839     /**
1840      * @param sessionManager
1841      *            The sessionManager to set.
1842      */
1843     public void setSessionManager(SessionManager sessionManager)
1844     {
1845         _sessionManager = sessionManager;
1846     }
1847 
1848     /* ------------------------------------------------------------ */
1849     public void setTimeStamp(long ts)
1850     {
1851         _timeStamp = ts;
1852     }
1853 
1854     /* ------------------------------------------------------------ */
1855     /**
1856      * @param uri
1857      *            The uri to set.
1858      */
1859     public void setUri(HttpURI uri)
1860     {
1861         _uri = uri;
1862     }
1863 
1864     /* ------------------------------------------------------------ */
1865     public void setUserIdentityScope(UserIdentity.Scope scope)
1866     {
1867         _scope = scope;
1868     }
1869 
1870     /* ------------------------------------------------------------ */
1871     /**
1872      * Set timetstamp of request dispatch
1873      *
1874      * @param value
1875      *            timestamp
1876      */
1877     public void setDispatchTime(long value)
1878     {
1879         _dispatchTime = value;
1880     }
1881 
1882     /* ------------------------------------------------------------ */
1883     public AsyncContext startAsync() throws IllegalStateException
1884     {
1885         if (!_asyncSupported)
1886             throw new IllegalStateException("!asyncSupported");
1887         _async.suspend();
1888         return _async;
1889     }
1890 
1891     /* ------------------------------------------------------------ */
1892     public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
1893     {
1894         if (!_asyncSupported)
1895             throw new IllegalStateException("!asyncSupported");
1896         _async.suspend(_context,servletRequest,servletResponse);
1897         return _async;
1898     }
1899 
1900     /* ------------------------------------------------------------ */
1901     @Override
1902     public String toString()
1903     {
1904         return (_handled?"[":"(") + getMethod() + " " + _uri + (_handled?"]@":")@") + hashCode() + " " + super.toString();
1905     }
1906 
1907     /* ------------------------------------------------------------ */
1908     /**
1909      * Merge in a new query string. The query string is merged with the existing parameters and {@link #setParameters(MultiMap)} and
1910      * {@link #setQueryString(String)} are called with the result. The merge is according to the rules of the servlet dispatch forward method.
1911      *
1912      * @param query
1913      *            The query string to merge into the request.
1914      */
1915     public void mergeQueryString(String query)
1916     {
1917         // extract parameters from dispatch query
1918         MultiMap<String> parameters = new MultiMap<String>();
1919         UrlEncoded.decodeTo(query,parameters,getCharacterEncoding());
1920 
1921         boolean merge_old_query = false;
1922 
1923         // Have we evaluated parameters
1924         if (!_paramsExtracted)
1925             extractParameters();
1926 
1927         // Are there any existing parameters?
1928         if (_parameters != null && _parameters.size() > 0)
1929         {
1930             // Merge parameters; new parameters of the same name take precedence.
1931             Iterator<Entry<String, Object>> iter = _parameters.entrySet().iterator();
1932             while (iter.hasNext())
1933             {
1934                 Map.Entry<String, Object> entry = iter.next();
1935                 String name = entry.getKey();
1936 
1937                 // If the names match, we will need to remake the query string
1938                 if (parameters.containsKey(name))
1939                     merge_old_query = true;
1940 
1941                 // Add the old values to the new parameter map
1942                 Object values = entry.getValue();
1943                 for (int i = 0; i < LazyList.size(values); i++)
1944                     parameters.add(name,LazyList.get(values,i));
1945             }
1946         }
1947 
1948         if (_queryString != null && _queryString.length() > 0)
1949         {
1950             if (merge_old_query)
1951             {
1952                 StringBuilder overridden_query_string = new StringBuilder();
1953                 MultiMap<String> overridden_old_query = new MultiMap<String>();
1954                 UrlEncoded.decodeTo(_queryString,overridden_old_query,getCharacterEncoding());
1955 
1956                 MultiMap<String> overridden_new_query = new MultiMap<String>();
1957                 UrlEncoded.decodeTo(query,overridden_new_query,getCharacterEncoding());
1958 
1959                 Iterator<Entry<String, Object>> iter = overridden_old_query.entrySet().iterator();
1960                 while (iter.hasNext())
1961                 {
1962                     Map.Entry<String, Object> entry = iter.next();
1963                     String name = entry.getKey();
1964                     if (!overridden_new_query.containsKey(name))
1965                     {
1966                         Object values = entry.getValue();
1967                         for (int i = 0; i < LazyList.size(values); i++)
1968                         {
1969                             overridden_query_string.append("&").append(name).append("=").append(LazyList.get(values,i));
1970                         }
1971                     }
1972                 }
1973 
1974                 query = query + overridden_query_string;
1975             }
1976             else
1977             {
1978                 query = query + "&" + _queryString;
1979             }
1980         }
1981 
1982         setParameters(parameters);
1983         setQueryString(query);
1984     }
1985 }