View Javadoc

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