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