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