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