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 AbstractHttpConnection} 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 AbstractHttpConnection.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 AbstractHttpConnection _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(AbstractHttpConnection 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 AbstractHttpConnection 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         if (_uri == null)
1008             throw new IllegalStateException("No uri");
1009 
1010         // Return host from absolute URI
1011         _serverName = _uri.getHost();
1012         _port = _uri.getPort();
1013         if (_serverName != null) 
1014             return _serverName;
1015 
1016         // Return host from header field
1017         Buffer hostPort = _connection.getRequestFields().get(HttpHeaders.HOST_BUFFER);
1018         if (hostPort!=null)
1019         {
1020             loop:
1021             for (int i=hostPort.putIndex();i-->hostPort.getIndex();)   
1022             {
1023                 char ch=(char)(0xff&hostPort.peek(i));
1024                 switch(ch)
1025                 {
1026                     case ']':
1027                         break loop;
1028 
1029                     case ':':
1030                         _serverName=BufferUtil.to8859_1_String(hostPort.peek(hostPort.getIndex(), i-hostPort.getIndex()));
1031                         _port=BufferUtil.toInt(hostPort.peek(i+1, hostPort.putIndex()-i-1));
1032                         return _serverName;
1033                 }
1034             }
1035             if (_serverName==null || _port<0)
1036             {
1037                 _serverName=BufferUtil.to8859_1_String(hostPort);
1038                 _port = 0;
1039             }
1040             
1041             return _serverName;
1042         }
1043 
1044         // Return host from connection
1045         if (_connection != null)
1046         {
1047             _serverName = getLocalName();
1048             _port = getLocalPort();
1049             if (_serverName != null && !StringUtil.ALL_INTERFACES.equals(_serverName)) 
1050                 return _serverName;
1051         }
1052 
1053         // Return the local host
1054         try
1055         {
1056             _serverName = InetAddress.getLocalHost().getHostAddress();
1057         }
1058         catch (java.net.UnknownHostException e)
1059         {
1060             LOG.ignore(e);
1061         }
1062         return _serverName;
1063     }
1064 
1065     /* ------------------------------------------------------------ */
1066     /* 
1067      * @see javax.servlet.ServletRequest#getServerPort()
1068      */
1069     public int getServerPort()
1070     {
1071         if (_port<=0)
1072         {
1073             if (_serverName==null)
1074                 getServerName();
1075         
1076             if (_port<=0)
1077             {
1078                 if (_serverName!=null && _uri!=null)
1079                     _port = _uri.getPort();
1080                 else
1081                     _port = _endp==null?0:_endp.getLocalPort();
1082             }
1083         }
1084         
1085         if (_port<=0)
1086         {
1087             if (getScheme().equalsIgnoreCase(URIUtil.HTTPS))
1088                 return 443;
1089             return 80;
1090         }
1091         return _port;
1092     }
1093 
1094     /* ------------------------------------------------------------ */
1095     public ServletContext getServletContext()
1096     {
1097         return _context;
1098     }
1099 
1100     /* ------------------------------------------------------------ */
1101     /* 
1102      */
1103     public String getServletName()
1104     {
1105         if (_scope!=null)
1106             return _scope.getName();
1107         return null;
1108     }
1109 
1110     /* ------------------------------------------------------------ */
1111     /* 
1112      * @see javax.servlet.http.HttpServletRequest#getServletPath()
1113      */
1114     public String getServletPath()
1115     {
1116         if (_servletPath==null)
1117             _servletPath="";
1118         return _servletPath;
1119     }
1120 
1121     /* ------------------------------------------------------------ */
1122     public ServletResponse getServletResponse()
1123     {
1124         return _connection.getResponse();
1125     }
1126 
1127     /* ------------------------------------------------------------ */
1128     /* 
1129      * @see javax.servlet.http.HttpServletRequest#getSession()
1130      */
1131     public HttpSession getSession()
1132     {
1133         return getSession(true);
1134     }
1135 
1136     /* ------------------------------------------------------------ */
1137     /* 
1138      * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
1139      */
1140     public HttpSession getSession(boolean create)
1141     {   
1142         if (_session != null )
1143         {
1144             if (_sessionManager!=null && !_sessionManager.isValid(_session))
1145                 _session=null;
1146             else
1147                 return _session;
1148         }
1149         
1150         if (!create)
1151             return null;
1152         
1153         if (_sessionManager==null)
1154             throw new IllegalStateException("No SessionManager");
1155 
1156         _session=_sessionManager.newHttpSession(this);
1157         HttpCookie cookie=_sessionManager.getSessionCookie(_session,getContextPath(),isSecure());
1158         if (cookie!=null)
1159             _connection.getResponse().addCookie(cookie);
1160         
1161         return _session;
1162     }
1163     
1164 
1165     /* ------------------------------------------------------------ */
1166     /**
1167      * @return Returns the sessionManager.
1168      */
1169     public SessionManager getSessionManager()
1170     {
1171         return _sessionManager;
1172     }
1173     
1174     /* ------------------------------------------------------------ */
1175     /**
1176      * Get Request TimeStamp
1177      * 
1178      * @return The time that the request was received.
1179      */
1180     public long getTimeStamp()
1181     {
1182         return _timeStamp;
1183     }
1184     
1185     /* ------------------------------------------------------------ */
1186     /**
1187      * Get Request TimeStamp
1188      * 
1189      * @return The time that the request was received.
1190      */
1191     public Buffer getTimeStampBuffer()
1192     {
1193         if (_timeStampBuffer == null && _timeStamp > 0)
1194                 _timeStampBuffer = HttpFields.__dateCache.formatBuffer(_timeStamp);
1195         return _timeStampBuffer;
1196     }
1197     
1198     /* ------------------------------------------------------------ */
1199     /**
1200      * @return Returns the uri.
1201      */
1202     public HttpURI getUri()
1203     {
1204         return _uri;
1205     }
1206 
1207     /* ------------------------------------------------------------ */
1208     public UserIdentity getUserIdentity()
1209     {
1210         if (_authentication instanceof Authentication.Deferred)
1211             setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1212         
1213         if (_authentication instanceof Authentication.User)
1214             return ((Authentication.User)_authentication).getUserIdentity();
1215         return null;
1216     }
1217 
1218     /* ------------------------------------------------------------ */
1219     /**
1220      * @return The resolved user Identity, which may be null if the 
1221      * {@link Authentication} is not {@link Authentication.User} 
1222      * (eg. {@link Authentication.Deferred}).
1223      */
1224     public UserIdentity getResolvedUserIdentity()
1225     {
1226         if (_authentication instanceof Authentication.User)
1227             return ((Authentication.User)_authentication).getUserIdentity();
1228         return null;
1229     }
1230     
1231     /* ------------------------------------------------------------ */
1232     public UserIdentity.Scope getUserIdentityScope()
1233     {
1234         return _scope;
1235     }
1236     
1237     /* ------------------------------------------------------------ */
1238     /* 
1239      * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
1240      */
1241     public Principal getUserPrincipal()
1242     {
1243         if (_authentication instanceof Authentication.Deferred)
1244             setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1245         
1246         if (_authentication instanceof Authentication.User)
1247         {
1248             UserIdentity user = ((Authentication.User)_authentication).getUserIdentity();
1249             return user.getUserPrincipal();
1250         }
1251         return null;
1252     }
1253     
1254     /* ------------------------------------------------------------ */
1255     /** Get timestamp of the request dispatch
1256      * 
1257      * @return timestamp
1258      */
1259     public long getDispatchTime()
1260     {
1261         return _dispatchTime;
1262     }
1263 
1264     /* ------------------------------------------------------------ */
1265     public boolean isAsyncStarted()
1266     {
1267         return _async.isAsyncStarted();
1268     }
1269     
1270     /* ------------------------------------------------------------ */
1271     public boolean isAsyncSupported()
1272     {
1273         return _asyncSupported;
1274     }
1275 
1276     /* ------------------------------------------------------------ */
1277     public boolean isHandled()
1278     {
1279         return _handled;
1280     }
1281     
1282     /* ------------------------------------------------------------ */
1283     /* 
1284      * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
1285      */
1286     public boolean isRequestedSessionIdFromCookie()
1287     {
1288         return _requestedSessionId!=null && _requestedSessionIdFromCookie;
1289     }
1290     
1291     /* ------------------------------------------------------------ */
1292     /* 
1293      * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
1294      */
1295     public boolean isRequestedSessionIdFromUrl()
1296     {
1297         return _requestedSessionId!=null && !_requestedSessionIdFromCookie;
1298     }
1299     
1300     /* ------------------------------------------------------------ */
1301     /* 
1302      * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
1303      */
1304     public boolean isRequestedSessionIdFromURL()
1305     {
1306         return _requestedSessionId!=null && !_requestedSessionIdFromCookie;
1307     }
1308     
1309     /* ------------------------------------------------------------ */
1310     /* 
1311      * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
1312      */
1313     public boolean isRequestedSessionIdValid()
1314     {	
1315         if (_requestedSessionId==null)
1316             return false;
1317         
1318         HttpSession session=getSession(false);
1319         return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session)));
1320     }
1321     
1322     /* ------------------------------------------------------------ */
1323     /* 
1324      * @see javax.servlet.ServletRequest#isSecure()
1325      */
1326     public boolean isSecure()
1327     {
1328         return _connection.isConfidential(this);
1329     }
1330     
1331     /* ------------------------------------------------------------ */
1332     /* 
1333      * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
1334      */
1335     public boolean isUserInRole(String role)
1336     {
1337         if (_authentication instanceof Authentication.Deferred)
1338             setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
1339         
1340         if (_authentication instanceof Authentication.User)
1341             return ((Authentication.User)_authentication).isUserInRole(_scope,role);
1342         return false;
1343     }
1344     
1345     /* ------------------------------------------------------------ */
1346     public HttpSession recoverNewSession(Object key)
1347     {
1348         if (_savedNewSessions==null)
1349             return null;
1350         return _savedNewSessions.get(key);
1351     }
1352     
1353     /* ------------------------------------------------------------ */
1354     protected void recycle()
1355     {
1356         if (_inputState==__READER)
1357         {
1358             try
1359             {
1360                 int r=_reader.read();
1361                 while(r!=-1)
1362                     r=_reader.read();
1363             }
1364             catch(Exception e)
1365             {
1366                 LOG.ignore(e);
1367                 _reader=null;
1368             }
1369         }
1370         
1371         setAuthentication(Authentication.NOT_CHECKED);
1372     	_async.recycle();
1373         _asyncSupported=true;
1374         _handled=false;
1375         if (_context!=null)
1376             throw new IllegalStateException("Request in context!");
1377         if(_attributes!=null)
1378             _attributes.clearAttributes();
1379         _characterEncoding=null;
1380         if (_cookies!=null)
1381             _cookies.reset();
1382         _cookiesExtracted=false;
1383         _context=null;
1384         _serverName=null;
1385         _method=null;
1386         _pathInfo=null;
1387         _port=0;
1388         _protocol=HttpVersions.HTTP_1_1;
1389         _queryEncoding=null;
1390         _queryString=null;
1391         _requestedSessionId=null;
1392         _requestedSessionIdFromCookie=false;
1393         _session=null;
1394         _sessionManager=null;
1395         _requestURI=null;
1396         _scope=null;
1397         _scheme=URIUtil.HTTP;
1398         _servletPath=null;
1399         _timeStamp=0;
1400         _timeStampBuffer=null;
1401         _uri=null;
1402         if (_baseParameters!=null)
1403             _baseParameters.clear();
1404         _parameters=null;
1405         _paramsExtracted=false;
1406         _inputState=__NONE;
1407         
1408         if (_savedNewSessions!=null)
1409             _savedNewSessions.clear();
1410         _savedNewSessions=null;
1411         _multiPartInputStream = null;
1412     }
1413     
1414     /* ------------------------------------------------------------ */
1415     /* 
1416      * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
1417      */
1418     public void removeAttribute(String name)
1419     {
1420         Object old_value=_attributes==null?null:_attributes.getAttribute(name);
1421         
1422         if (_attributes!=null)
1423             _attributes.removeAttribute(name);
1424         
1425         if (old_value!=null)
1426         {
1427             if (_requestAttributeListeners!=null)
1428             {
1429                 final ServletRequestAttributeEvent event =
1430                     new ServletRequestAttributeEvent(_context,this,name, old_value);
1431                 final int size=LazyList.size(_requestAttributeListeners);
1432                 for(int i=0;i<size;i++)
1433                 {
1434                     final EventListener listener = (ServletRequestAttributeListener)LazyList.get(_requestAttributeListeners,i);
1435                     if (listener instanceof ServletRequestAttributeListener)
1436                     {
1437                         final ServletRequestAttributeListener l = (ServletRequestAttributeListener)listener;
1438                         l.attributeRemoved(event);
1439                     }
1440                 }
1441             }
1442         }
1443     }
1444     
1445     /* ------------------------------------------------------------ */
1446     public void removeEventListener(final EventListener listener) 
1447     {
1448         _requestAttributeListeners= LazyList.remove(_requestAttributeListeners, listener);
1449     }
1450     /* ------------------------------------------------------------ */
1451     public void saveNewSession(Object key,HttpSession session)
1452     {
1453         if (_savedNewSessions==null)
1454             _savedNewSessions=new HashMap<Object,HttpSession>();
1455         _savedNewSessions.put(key,session);
1456     }
1457     /* ------------------------------------------------------------ */
1458     public void setAsyncSupported(boolean supported)
1459     {
1460         _asyncSupported=supported;
1461     }
1462     
1463     /* ------------------------------------------------------------ */
1464     /* 
1465      * Set a request attribute.
1466      * if the attribute name is "org.eclipse.jetty.server.server.Request.queryEncoding" then
1467      * the value is also passed in a call to {@link #setQueryEncoding}.
1468      * <p>
1469      * if the attribute name is "org.eclipse.jetty.server.server.ResponseBuffer", then
1470      * the response buffer is flushed with @{link #flushResponseBuffer}
1471      * <p>
1472      * if the attribute name is "org.eclipse.jetty.io.EndPoint.maxIdleTime", then the 
1473      * value is passed to the associated {@link EndPoint#setMaxIdleTime}.
1474      * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
1475      */
1476     public void setAttribute(String name, Object value)
1477     {
1478         Object old_value=_attributes==null?null:_attributes.getAttribute(name);
1479         
1480         if (name.startsWith("org.eclipse.jetty."))
1481         {
1482             if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name))
1483                 setQueryEncoding(value==null?null:value.toString());
1484             else if("org.eclipse.jetty.server.sendContent".equals(name))
1485             {
1486                 try 
1487                 {
1488                     ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendContent(value); 
1489                 } 
1490                 catch (IOException e)
1491                 {
1492                     throw new RuntimeException(e);
1493                 }
1494             }
1495             else if("org.eclipse.jetty.server.ResponseBuffer".equals(name))
1496             {
1497                 try
1498                 {
1499                     final ByteBuffer byteBuffer=(ByteBuffer)value;
1500                     synchronized (byteBuffer)
1501                     {
1502                         NIOBuffer buffer = byteBuffer.isDirect()
1503                         ?new DirectNIOBuffer(byteBuffer,true)
1504                         :new IndirectNIOBuffer(byteBuffer,true);
1505                         ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendResponse(buffer);
1506                     }
1507                 }
1508                 catch (IOException e)
1509                 {
1510                     throw new RuntimeException(e);
1511                 }
1512             }
1513             else if ("org.eclipse.jetty.io.EndPoint.maxIdleTime".equalsIgnoreCase(name))
1514             {
1515                 try
1516                 {
1517                     getConnection().getEndPoint().setMaxIdleTime(Integer.valueOf(value.toString()));
1518                 }
1519                 catch(IOException e)
1520                 {
1521                     throw new RuntimeException(e);
1522                 }
1523             }
1524         }
1525         
1526         if (_attributes==null)
1527             _attributes=new AttributesMap();
1528         _attributes.setAttribute(name, value);
1529         
1530         if (_requestAttributeListeners!=null)
1531         {
1532             final ServletRequestAttributeEvent event =
1533                 new ServletRequestAttributeEvent(_context,this,name, old_value==null?value:old_value);
1534             final int size=LazyList.size(_requestAttributeListeners);
1535             for(int i=0;i<size;i++)
1536             {
1537                 final EventListener listener = (ServletRequestAttributeListener)LazyList.get(_requestAttributeListeners,i);
1538                 if (listener instanceof ServletRequestAttributeListener)
1539                 {
1540                     final ServletRequestAttributeListener l = (ServletRequestAttributeListener)listener;
1541 
1542                     if (old_value==null)
1543                         l.attributeAdded(event);
1544                     else if (value==null)
1545                         l.attributeRemoved(event);
1546                     else
1547                         l.attributeReplaced(event);
1548                 }
1549             }
1550         }
1551     }
1552     
1553     /* ------------------------------------------------------------ */
1554     /* 
1555      */
1556     public void setAttributes(Attributes attributes)
1557     {
1558         _attributes=attributes;
1559     }
1560     
1561     /* ------------------------------------------------------------ */
1562 
1563     
1564     /* ------------------------------------------------------------ */
1565     /** Set the authentication.
1566      * @param authentication the authentication to set
1567      */
1568     public void setAuthentication(Authentication authentication)
1569     {
1570         _authentication = authentication;
1571     }
1572 
1573     /* ------------------------------------------------------------ */
1574     /* 
1575      * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
1576      */
1577     public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException
1578     {
1579         if (_inputState!=__NONE) 
1580             return;
1581 
1582         _characterEncoding=encoding;
1583 
1584         // check encoding is supported
1585         if (!StringUtil.isUTF8(encoding))
1586             //noinspection ResultOfMethodCallIgnored
1587             "".getBytes(encoding);
1588     }
1589 
1590     /* ------------------------------------------------------------ */
1591     /* 
1592      * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
1593      */
1594     public void setCharacterEncodingUnchecked(String encoding)
1595     {
1596         _characterEncoding=encoding;
1597     }
1598 
1599     /* ------------------------------------------------------------ */
1600     //final so we can safely call this from constructor
1601     protected final void setConnection(AbstractHttpConnection connection)
1602     {
1603         _connection=connection;
1604     	_async.setConnection(connection);
1605         _endp=connection.getEndPoint();
1606         _dns=connection.getResolveNames();
1607     }
1608 
1609     /* ------------------------------------------------------------ */
1610     /* 
1611      * @see javax.servlet.ServletRequest#getContentType()
1612      */
1613     public void setContentType(String contentType)
1614     {
1615         _connection.getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,contentType);
1616         
1617     }
1618 
1619     /* ------------------------------------------------------------ */
1620     /**
1621      * Set request context
1622      * 
1623      * @param context context object
1624      */
1625     public void setContext(Context context)
1626     {
1627         _newContext=_context!=context;
1628         _context=context;
1629     }
1630     
1631     /* ------------------------------------------------------------ */
1632     /**
1633      * @return True if this is the first call of {@link #takeNewContext()} 
1634      * since the last {@link #setContext(org.eclipse.jetty.server.handler.ContextHandler.Context)} call.
1635      */
1636     public boolean takeNewContext()
1637     {
1638         boolean nc=_newContext;
1639         _newContext=false;
1640         return nc;
1641     }
1642     
1643     /* ------------------------------------------------------------ */
1644     /**
1645      * Sets the "context path" for this request
1646      * @see HttpServletRequest#getContextPath()
1647      */
1648     public void setContextPath(String contextPath)
1649     {
1650         _contextPath = contextPath;
1651     }
1652 
1653     /* ------------------------------------------------------------ */
1654     /**
1655      * @param cookies The cookies to set.
1656      */
1657     public void setCookies(Cookie[] cookies)
1658     {
1659         if (_cookies==null)
1660             _cookies=new CookieCutter();
1661         _cookies.setCookies(cookies);
1662     }
1663 
1664     /* ------------------------------------------------------------ */
1665     public void setDispatcherType(DispatcherType type)
1666     {
1667     	_dispatcherType=type;
1668     }
1669     
1670     /* ------------------------------------------------------------ */
1671     public void setHandled(boolean h)
1672     {
1673         _handled=h;
1674     }
1675     
1676     /* ------------------------------------------------------------ */
1677     /**
1678      * @param method The method to set.
1679      */
1680     public void setMethod(String method)
1681     {
1682         _method = method;
1683     }
1684 
1685     /* ------------------------------------------------------------ */
1686     /**
1687      * @param parameters The parameters to set.
1688      */
1689     public void setParameters(MultiMap<String> parameters)
1690     {
1691         _parameters= (parameters==null)?_baseParameters:parameters;
1692         if (_paramsExtracted && _parameters==null)
1693             throw new IllegalStateException();
1694     }
1695 
1696     /* ------------------------------------------------------------ */
1697     /**
1698      * @param pathInfo The pathInfo to set.
1699      */
1700     public void setPathInfo(String pathInfo)
1701     {
1702         _pathInfo = pathInfo;
1703     }
1704     
1705     /* ------------------------------------------------------------ */
1706     /**
1707      * @param protocol The protocol to set.
1708      */
1709     public void setProtocol(String protocol)
1710     {
1711         _protocol = protocol;
1712     }
1713 
1714     /* ------------------------------------------------------------ */
1715     /** Set the character encoding used for the query string.
1716      * This call will effect the return of getQueryString and getParamaters.
1717      * It must be called before any geParameter methods.
1718      * 
1719      * The request attribute "org.eclipse.jetty.server.server.Request.queryEncoding"
1720      * may be set as an alternate method of calling setQueryEncoding.
1721      * 
1722      * @param queryEncoding
1723      */
1724     public void setQueryEncoding(String queryEncoding)
1725     {
1726         _queryEncoding=queryEncoding;
1727         _queryString=null;
1728     }
1729     
1730     /* ------------------------------------------------------------ */
1731     /**
1732      * @param queryString The queryString to set.
1733      */
1734     public void setQueryString(String queryString)
1735     {
1736         _queryString = queryString;
1737     }
1738     
1739     /* ------------------------------------------------------------ */
1740     /**
1741      * @param addr The address to set.
1742      */
1743     public void setRemoteAddr(String addr)
1744     {
1745         _remoteAddr = addr;
1746     }
1747 
1748     /* ------------------------------------------------------------ */
1749     /**
1750      * @param host The host to set.
1751      */
1752     public void setRemoteHost(String host)
1753     {
1754         _remoteHost = host;
1755     }
1756 
1757     /* ------------------------------------------------------------ */
1758     /**
1759      * @param requestedSessionId The requestedSessionId to set.
1760      */
1761     public void setRequestedSessionId(String requestedSessionId)
1762     {
1763         _requestedSessionId = requestedSessionId;
1764     }
1765     
1766     /* ------------------------------------------------------------ */
1767     /**
1768      * @param requestedSessionIdCookie The requestedSessionIdCookie to set.
1769      */
1770     public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie)
1771     {
1772         _requestedSessionIdFromCookie = requestedSessionIdCookie;
1773     }
1774 
1775     /* ------------------------------------------------------------ */
1776     /**
1777      * @param requestURI The requestURI to set.
1778      */
1779     public void setRequestURI(String requestURI)
1780     {
1781         _requestURI = requestURI;
1782     }
1783 
1784     /* ------------------------------------------------------------ */
1785     /**
1786      * @param scheme The scheme to set.
1787      */
1788     public void setScheme(String scheme)
1789     {
1790         _scheme = scheme;
1791     }
1792 
1793     /* ------------------------------------------------------------ */
1794     /**
1795      * @param host The host to set.
1796      */
1797     public void setServerName(String host)
1798     {
1799         _serverName = host;
1800     }
1801     
1802     /* ------------------------------------------------------------ */
1803     /**
1804      * @param port The port to set.
1805      */
1806     public void setServerPort(int port)
1807     {
1808         _port = port;
1809     }
1810 
1811     /* ------------------------------------------------------------ */
1812     /**
1813      * @param servletPath The servletPath to set.
1814      */
1815     public void setServletPath(String servletPath)
1816     {
1817         _servletPath = servletPath;
1818     }
1819 
1820     /* ------------------------------------------------------------ */
1821     /**
1822      * @param session The session to set.
1823      */
1824     public void setSession(HttpSession session)
1825     {
1826         _session = session;
1827     }
1828 
1829     /* ------------------------------------------------------------ */
1830     /**
1831      * @param sessionManager The sessionManager to set.
1832      */
1833     public void setSessionManager(SessionManager sessionManager)
1834     {
1835         _sessionManager = sessionManager;
1836     }
1837 
1838     /* ------------------------------------------------------------ */
1839     public void setTimeStamp(long ts)
1840     {
1841         _timeStamp = ts;
1842     }
1843 
1844     /* ------------------------------------------------------------ */
1845     /**
1846      * @param uri The uri to set.
1847      */
1848     public void setUri(HttpURI uri)
1849     {
1850         _uri = uri;
1851     }
1852 
1853     /* ------------------------------------------------------------ */
1854     public void setUserIdentityScope(UserIdentity.Scope scope)
1855     {
1856         _scope=scope;
1857     }
1858 
1859     /* ------------------------------------------------------------ */
1860     /** Set timetstamp of request dispatch
1861      * 
1862      * @param value timestamp
1863      */
1864     public void setDispatchTime(long value)
1865     {
1866         _dispatchTime = value;
1867     }
1868 
1869     /* ------------------------------------------------------------ */
1870     public AsyncContext startAsync() throws IllegalStateException
1871     {
1872         if (!_asyncSupported)
1873             throw new IllegalStateException("!asyncSupported");
1874         _async.suspend(_context,this,_connection._response);  
1875         return _async;
1876     }
1877 
1878     /* ------------------------------------------------------------ */
1879     public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
1880     {
1881         if (!_asyncSupported)
1882             throw new IllegalStateException("!asyncSupported");
1883         _async.suspend(_context,servletRequest,servletResponse);
1884         return _async;
1885     }
1886 
1887     /* ------------------------------------------------------------ */
1888     @Override
1889     public String toString()
1890     {
1891         return (_handled?"[":"(")+getMethod()+" "+_uri+(_handled?"]@":")@")+hashCode()+" "+super.toString();
1892     }
1893 
1894     /* ------------------------------------------------------------ */
1895     public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
1896     {
1897         if (_authentication instanceof Authentication.Deferred)
1898         {
1899         	setAuthentication(((Authentication.Deferred)_authentication).authenticate(this,response));
1900             return !(_authentication instanceof Authentication.ResponseSent);        
1901         }
1902         response.sendError(HttpStatus.UNAUTHORIZED_401);
1903         return false;
1904     }
1905 
1906     /* ------------------------------------------------------------ */
1907     public Part getPart(String name) throws IOException, ServletException
1908     {        
1909         if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
1910             return null;
1911         
1912         if (_multiPartInputStream == null)
1913         { 
1914             _multiPartInputStream = new MultiPartInputStream(getInputStream(), 
1915                                                              getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT), 
1916                                                              (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
1917         }
1918         return _multiPartInputStream.getPart(name);
1919     }
1920 
1921     /* ------------------------------------------------------------ */
1922     public Collection<Part> getParts() throws IOException, ServletException
1923     {
1924         if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
1925             return Collections.emptyList();
1926         
1927         if (_multiPartInputStream == null)
1928         {
1929             _multiPartInputStream = new MultiPartInputStream(getInputStream(), 
1930                                                              getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT), 
1931                                                              (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
1932         }
1933         return _multiPartInputStream.getParts();
1934     }
1935 
1936     /* ------------------------------------------------------------ */
1937     public void login(String username, String password) throws ServletException
1938     {
1939         if (_authentication instanceof Authentication.Deferred) 
1940         {
1941             _authentication=((Authentication.Deferred)_authentication).login(username,password);
1942             if (_authentication == null)
1943                 throw new ServletException();
1944         } 
1945         else 
1946         {
1947             throw new ServletException("Authenticated as "+_authentication);
1948         }
1949     }
1950 
1951     /* ------------------------------------------------------------ */
1952     public void logout() throws ServletException
1953     {
1954         if (_authentication instanceof Authentication.User)
1955             ((Authentication.User)_authentication).logout();
1956         _authentication=Authentication.UNAUTHENTICATED;
1957     }
1958     
1959     /* ------------------------------------------------------------ */
1960     /** Merge in a new query string.
1961      * The query string is merged with the existing parameters and {@link #setParameters(MultiMap)} and {@link #setQueryString(String)} are called with the result.
1962      * The merge is according to the rules of the servlet dispatch forward method.
1963      * @param query The query string to merge into the request.
1964      */
1965     public void mergeQueryString(String query)
1966     {
1967         // extract parameters from dispatch query
1968         MultiMap<String> parameters=new MultiMap<String>();
1969         UrlEncoded.decodeTo(query,parameters,getCharacterEncoding());
1970      
1971         boolean merge_old_query = false;
1972 
1973         // Have we evaluated parameters
1974         if (!_paramsExtracted) 
1975             extractParameters();
1976         
1977         // Are there any existing parameters?
1978         if (_parameters!=null && _parameters.size()>0)
1979         {
1980             // Merge parameters; new parameters of the same name take precedence.
1981             Iterator<Entry<String,Object>> iter = _parameters.entrySet().iterator();
1982             while (iter.hasNext())
1983             {
1984                 Map.Entry<String,Object> entry = iter.next();
1985                 String name=entry.getKey();
1986                 
1987                 // If the names match, we will need to remake the query string
1988                 if (parameters.containsKey(name))
1989                     merge_old_query = true;
1990 
1991                 // Add the old values to the new parameter map
1992                 Object values=entry.getValue();
1993                 for (int i=0;i<LazyList.size(values);i++)
1994                     parameters.add(name, LazyList.get(values, i));
1995             }
1996         }
1997         
1998         if (_queryString != null && _queryString.length()>0)
1999         {
2000             if ( merge_old_query )
2001             {
2002                 StringBuilder overridden_query_string = new StringBuilder();
2003                 MultiMap<String> overridden_old_query = new MultiMap<String>();
2004                 UrlEncoded.decodeTo(_queryString,overridden_old_query,getCharacterEncoding());
2005 
2006                 MultiMap<String> overridden_new_query = new MultiMap<String>(); 
2007                 UrlEncoded.decodeTo(query,overridden_new_query,getCharacterEncoding());
2008 
2009                 Iterator<Entry<String,Object>> iter = overridden_old_query.entrySet().iterator();
2010                 while (iter.hasNext())
2011                 {
2012                     Map.Entry<String,Object> entry = iter.next();
2013                     String name=entry.getKey();
2014                     if(!overridden_new_query.containsKey(name))
2015                     {
2016                         Object values=entry.getValue();
2017                         for (int i=0;i<LazyList.size(values);i++)
2018                         {
2019                             overridden_query_string.append("&").append(name).append("=").append(LazyList.get(values, i));
2020                         }
2021                     }
2022                 }
2023                 
2024                 query = query + overridden_query_string;
2025             }
2026             else 
2027             {
2028                 query=query+"&"+_queryString;
2029             }
2030        }
2031 
2032        setParameters(parameters);
2033        setQueryString(query);
2034     }
2035 }
2036