View Javadoc

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