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