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