//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.ireland.jnetty.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.security.Principal;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.CookieDecoder;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.UrlEncoded;
import org.ireland.jnetty.dispatch.HttpInvocation;
import org.ireland.jnetty.http.io.ByteBufServletInputStream;
import org.ireland.jnetty.server.session.HttpSessionImpl;
import org.ireland.jnetty.server.session.SessionManager;
import org.ireland.jnetty.util.StringParser;
import org.ireland.jnetty.util.http.ContentTypeUtil;
import org.ireland.jnetty.webapp.WebApp;
/* ------------------------------------------------------------ */
/**
* Jetty HttpServletRequestImpl.
* <p>
* Implements {@link javax.servlet.http.HttpServletRequest} from the <code>javax.servlet.http</code> package.
* </p>
* <p>
* request object to be as lightweight as possible and not actually implement any significant behavior. For example
* <ul>
*
* <li>The {@link HttpServletRequestImpl#getContextPath()} method will return null, until the request has been passed to
* a {@link ContextHandler} which matches the {@link HttpServletRequestImpl#getPathInfo()} with a context path and calls
* {@link HttpServletRequestImpl#setContextPath(String)} as a result.</li>
*
* <li>the HTTP session methods will all return null sessions until such time as a request has been passed to a
* {@link org.eclipse.jetty.server.session.SessionHandler} which checks for session cookies and enables the ability to
* create new sessions.</li>
*
* <li>The {@link HttpServletRequestImpl#getServletPath()} method will return null until the request has been passed to
* a <code>org.eclipse.jetty.servlet.ServletHandler</code> and the pathInfo matched against the servlet URL patterns and
* {@link HttpServletRequestImpl#setServletPath(String)} called as a result.</li>
* </ul>
*
* A request instance is created for each connection accepted by the server and recycled for each HTTP request received
* via that connection. An effort is made to avoid reparsing headers and cookies that are likely to be the same for
* requests from the same connection.
*
* <p>
* The form content that a request can process is limited to protect from Denial of Service attacks. The size in bytes
* is limited by {@link ContextHandler#getMaxFormContentSize()} or if there is no context then the
* "org.eclipse.jetty.server.Request.maxFormContentSize" {@link Server} attribute. The number of parameters keys is
* limited by {@link ContextHandler#getMaxFormKeys()} or if there is no context then the
* "org.eclipse.jetty.server.Request.maxFormKeys" {@link Server} attribute.
*
*
*/
public class HttpServletRequestImpl implements HttpServletRequest
{
/**
* Logger available to subclasses.
*/
protected static final Log LOG = LogFactory.getLog(HttpServletRequestImpl.class);
/**
* The default Locale if none are specified.
*/
protected static final Locale defaultLocale = Locale.getDefault();
private static final Collection<Locale> __defaultLocale = Collections.singleton(Locale.getDefault());
// Util
/**
* The string parser we will use for parsing request lines.
*/
private StringParser parser;
//
private final ServletContext servletContext;
//the HttpInvocation of this Request()
private HttpInvocation _invocation;
// Netty
private final SocketChannel socketChannel;
private final ChannelHandlerContext ctx;
private final FullHttpResponse response;
private final HttpServletResponseImpl _httpResponse;
// request
private final FullHttpRequest request;
// request-header
private final HttpHeaders headers;
// request-body
private final HttpContent body;
// the content of HttpServletRequestImpl Body,as byte array. normaly,please use HttpContent body
private byte[] bodyContent;
// Netty<<
/**
* ServletInputStream.
*/
protected ServletInputStream inputStream;
/**
* @see javax.servlet.ServletRequest#getInputStream() Using body as a stream flag.
* 将请求体用作InputStream使用的标志,不能同时将请求体作为Reader使用
*/
protected boolean usingInputStream = false;
/**
* @see javax.servlet.ServletRequest#getReader() Using body as reader flag.
* 将请求体用作Reader使用的标志,不能同时将请求体作为InputStream使用
*/
protected boolean usingReader = false;
private List<ServletRequestAttributeListener> _requestAttributeListeners;
private boolean _secure;
private boolean _asyncSupported = true;
private boolean _newContext;
private boolean _cookiesExtracted = false;
private boolean _handled = false;
private boolean _paramsExtracted;
/**
* The attributes associated with this HttpServletRequestImpl, keyed by attribute name.
*/
protected Map<String, Object> _attributes;
private String _contentType;
private String _characterEncoding;
/**
* Cookies parsed flag.
*/
protected boolean cookiesParsed = false;
// rawUri = contextPath + servletPath + pathInfo +?+ queryString
// 如: /myweb
private String _contextPath = "";
// 如: /myservlet
private String _servletPath;
// 如: /page.do 或 null
private String _pathInfo = null;
// 如: name=jack&pwd=123
private String _queryString;
/**
* Request QueryString Extracted flag.
*/
private boolean _queryStringExtracted;
private DispatcherType _dispatcherType;
private HttpMethod _httpMethod;
// Parameters from query string and form HttpServletRequestImpl Body(application/x-www-form-urlencoded [POST |PUT])
private Map<String, List<String>> _parameters;
private int _port;
private HttpVersion _httpVersion = HttpVersion.HTTP_1_1;
private String _queryEncoding;
private BufferedReader _reader;
private String _readerEncoding;
private InetSocketAddress _remote;
private String _requestedSessionId;
private String _requestURI;
private String _scheme = "http";
private String _serverName;
private HttpSessionImpl _session;
private SessionManager _sessionManager;
//true: has try to Extracte the sessionid
private boolean _sessionIdExtracted;
private boolean _isSessionIdFromCookie;
private long _timeStamp;
private long _dispatchTime;
/**
* The set of cookies associated with this HttpServletRequestImpl.
*/
protected Cookie[] cookies = null;
/**
* The preferred Locales associated with this HttpServletRequestImpl.
*/
protected List<Locale> _locales;
/**
* Parse _locales.
*/
protected boolean localesParsed = false;
/* ------------------------------------------------------------ */
public HttpServletRequestImpl(WebApp webApp, ServletContext servletContext, SocketChannel socketChannel, ChannelHandlerContext ctx,
FullHttpResponse response, FullHttpRequest request, HttpServletResponseImpl httpResponse)
{
this.servletContext = servletContext;
this._sessionManager = webApp.getSessionManager();
this.socketChannel = socketChannel;
this.ctx = ctx;
this.response = response;
this.request = request;
_httpResponse = httpResponse;
this.headers = request.headers();
this.body = request;
}
/* ------------------------------------------------------------ */
public void addEventListener(final EventListener listener)
{
if (listener instanceof ServletRequestAttributeListener)
{
if (_requestAttributeListeners == null)
_requestAttributeListeners = new ArrayList<ServletRequestAttributeListener>();
_requestAttributeListeners.add((ServletRequestAttributeListener) listener);
}
if (listener instanceof AsyncListener)
throw new IllegalArgumentException(listener.getClass().toString());
}
/* ------------------------------------------------------------ */
/**
* Extract Parameters from query string and form HttpServletRequestImpl Body(application/x-www-form-urlencoded [POST
* | PUT])
*/
public void extractParameters()
{
if (_paramsExtracted)
return;
_paramsExtracted = true;
if(_parameters == null)
_parameters = new HashMap<String, List<String>>();
// Handle query string
if (_queryEncoding == null)
{
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());
_parameters.putAll(queryStringDecoder.parameters());
}
else
{
try
{
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri(), Charset.forName(_queryEncoding));
_parameters.putAll(queryStringDecoder.parameters());
}
catch (UnsupportedCharsetException e)
{
if (LOG.isDebugEnabled())
LOG.warn(e);
else
LOG.warn(e.toString());
}
}
// handle form _content (application/x-www-form-urlencoded)
String encoding = getCharacterEncoding();
String content_type = getContentType();
if (content_type != null && content_type.length() > 0)
{
content_type = ContentTypeUtil.getContentTypeWithoutCharset(content_type);
// application/x-www-form-urlencoded( POST or PUT )
if (HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED.equals(content_type)
&& (HttpMethod.POST.name().equals(getMethod()) || HttpMethod.PUT.name().equals(getMethod())))
{
int content_length = getContentLength();
if (content_length > 0)
{
try
{
Charset bodyCharset = Charset.forName(encoding);
String bodyContent = new String(getRowBodyContent(), bodyCharset);
// Add form params to query params
QueryStringDecoder queryStringDecoder = new QueryStringDecoder(bodyContent, bodyCharset,false);
if (_parameters == null)
_parameters = queryStringDecoder.parameters();
else//merge
{
Map<String, List<String>> map = queryStringDecoder.parameters();
for (Entry<String, List<String>> e : map.entrySet())
{
if (!_parameters.containsKey(e.getKey()))
{
_parameters.put(e.getKey(), e.getValue());
}
else// parameter with the same name exist,merge
{
List<String> value = _parameters.get(e.getKey());
if (value == null)
_parameters.put(e.getKey(), e.getValue());
else
{
value.addAll(e.getValue()); // merge
_parameters.put(e.getKey(), value);
}
}
}
}
}
catch (Exception e)
{
if (LOG.isDebugEnabled())
e.printStackTrace();
else
LOG.warn(e.toString());
}
}
}
}
}
/**
*
* @return the content of HttpServletRequestImpl Body,as byte array. this method will not change the read / write
* index of body
*/
private byte[] getRowBodyContent()
{
// get [0,writerIndex) of body.date();
if (bodyContent == null)
{
int content_length = body.content().writerIndex(); // [0,writerIndex)
int old_readerIndex = body.content().readerIndex();// resver the old_readrIndex
byte[] data = new byte[content_length];
body.content().readerIndex(0);
body.content().readBytes(data, 0, content_length);
body.content().readerIndex(old_readerIndex); // recover the readerIndex
bodyContent = data;
}
return bodyContent;
}
/* ------------------------------------------------------------ */
@Override
public AsyncContext getAsyncContext()
{
/*
* HttpChannelState continuation = getHttpChannelState(); if (continuation.isInitial() &&
* !continuation.isAsync()) throw new IllegalStateException(continuation.getStatusString()); return
* continuation;
*/
// throw new UnsupportedOperationException();
return null;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
*/
@Override
// OK
public Object getAttribute(String name)
{
return (_attributes == null) ? null : _attributes.get(name);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getAttributeNames()
*/
@Override
// OK
public Enumeration<String> getAttributeNames()
{
// Take a copy to prevent ConncurrentModificationExceptions if used to
// remove attributes
Set<String> names = new HashSet<String>();
names.addAll(_attributes.keySet());
return Collections.enumeration(names);
}
/* ------------------------------------------------------------ */
/*
*/
public Map<String, Object> getAttributes()
{
if (_attributes == null)
_attributes = new HashMap();
return _attributes;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getAuthType()
*/
@Override
public String getAuthType()
{
return null;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getCharacterEncoding()
*/
@Override
// OK
public String getCharacterEncoding()
{
if (_characterEncoding == null)
{
_characterEncoding = ContentTypeUtil.getCharsetFromContentType(getContentType());
}
return _characterEncoding;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the connection.
*/
public SocketChannel getHttpChannel()
{
return socketChannel;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getContentLength()
*/
@Override
// OK
public int getContentLength()
{
long length = HttpHeaders.getContentLength(request, -1);
return (int) ((length <= Integer.MAX_VALUE) ? length : -1);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getContentType()
*
* example: "text/css;charset=UTF-8"
*/
@Override
// OK
public String getContentType()
{
if (_contentType == null)
_contentType = getHeader(HttpHeaders.Names.CONTENT_TYPE);
return _contentType;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getContextPath()
*/
@Override
public String getContextPath()
{
if (servletContext == null)
return "";
return servletContext.getContextPath();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getCookies()
*/
@Override
// OK
public Cookie[] getCookies()
{
if (!_cookiesExtracted)
extracteCookie();
return cookies;
}
/**
* Extracte cookies.
*/
protected void extracteCookie()
{
_cookiesExtracted = true;
// Decode the cookie.
String cookieString = headers.get(HttpHeaders.Names.COOKIE);
if (cookieString != null)
{
Set<io.netty.handler.codec.http.Cookie> _cookies = CookieDecoder.decode(cookieString);
this.cookies = new Cookie[_cookies.size()];
int i = 0;
// Convent netty's Cookie to Servlet's Cookie
for (io.netty.handler.codec.http.Cookie c : _cookies)
{
Cookie cookie = new Cookie(c.getName(), c.getValue());
cookie.setComment(c.getComment());
if(c.getDomain() != null)
cookie.setDomain(c.getDomain());
cookie.setHttpOnly(c.isHttpOnly());
cookie.setMaxAge((int) c.getMaxAge());
cookie.setPath(c.getPath());
cookie.setSecure(c.isSecure());
cookie.setVersion(c.getVersion());
this.cookies[i] = cookie;
i++;
}
}
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String)
*/
@Override
// OK
public long getDateHeader(String name)
{
Date date = HttpHeaders.getDateHeader(request, name, null);
return (date == null) ? -1 : date.getTime();
}
/* ------------------------------------------------------------ */
@Override
// OK
public DispatcherType getDispatcherType()
{
return _dispatcherType;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
*/
@Override
// ok
public String getHeader(String name)
{
return headers.get(name);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getHeaderNames()
*/
@Override
// OK
public Enumeration<String> getHeaderNames()
{
return Collections.enumeration(headers.names());
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String)
*/
@Override
// OK
public Enumeration<String> getHeaders(String name)
{
List<String> e = headers.getAll(name);
if (e == null)
return Collections.enumeration(Collections.<String> emptyList());
return Collections.enumeration(e);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getInputStream()
*/
@Override
// OK
public ServletInputStream getInputStream() throws IOException
{
if (usingReader)
{
throw new IllegalStateException("Already using Reader");
}
usingInputStream = true;
if (inputStream == null)
{
inputStream = new ByteBufServletInputStream(body.content());
}
return inputStream;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String)
*/
@Override
// OK
public int getIntHeader(String name)
{
return HttpHeaders.getIntHeader(request, name, -1);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getLocale()
*/
@Override
public Locale getLocale()
{
if (!localesParsed)
{
parseLocales();
}
if (_locales.size() > 0)
{
return _locales.get(0);
}
return defaultLocale;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getLocales()
*/
@Override
public Enumeration<Locale> getLocales()
{
if (!localesParsed)
{
parseLocales();
}
if (_locales.size() > 0)
{
return Collections.enumeration(_locales);
}
List<Locale> results = new LinkedList<Locale>();
results.add(defaultLocale);
return Collections.enumeration(results);
}
/**
* Parse request _locales.
*/
protected void parseLocales()
{
localesParsed = true;
Enumeration<String> values = getHeaders(HttpHeaders.Names.ACCEPT_LANGUAGE);
while (values.hasMoreElements())
{
String value = values.nextElement();
parseLocalesHeader(value);
}
}
/**
* Parse accept-language header value.
*/
protected void parseLocalesHeader(String value)
{
if (parser == null)
parser = new StringParser();
// Store the accumulated languages that have been requested in
// a local collection, sorted by the quality value (so we can
// add Locales in descending order). The values will be ArrayLists
// containing the corresponding Locales to be added
TreeMap<Double, ArrayList<Locale>> locales = new TreeMap<Double, ArrayList<Locale>>();
// Preprocess the value to remove all whitespace
int white = value.indexOf(' ');
if (white < 0)
{
white = value.indexOf('\t');
}
if (white >= 0)
{
StringBuilder sb = new StringBuilder();
int len = value.length();
for (int i = 0; i < len; i++)
{
char ch = value.charAt(i);
if ((ch != ' ') && (ch != '\t'))
{
sb.append(ch);
}
}
parser.setString(sb.toString());
}
else
{
parser.setString(value);
}
// Process each comma-delimited language specification
int length = parser.getLength();
while (true)
{
// Extract the next comma-delimited entry
int start = parser.getIndex();
if (start >= length)
{
break;
}
int end = parser.findChar(',');
String entry = parser.extract(start, end).trim();
parser.advance(); // For the following entry
// Extract the quality factor for this entry
double quality = 1.0;
int semi = entry.indexOf(";q=");
if (semi >= 0)
{
try
{
String strQuality = entry.substring(semi + 3);
if (strQuality.length() <= 5)
{
quality = Double.parseDouble(strQuality);
}
else
{
quality = 0.0;
}
}
catch (NumberFormatException e)
{
quality = 0.0;
}
entry = entry.substring(0, semi);
}
// Skip entries we are not going to keep track of
if (quality < 0.00005)
{
continue; // Zero (or effectively zero) quality factors
}
if ("*".equals(entry))
{
continue; // FIXME - "*" entries are not handled
}
// Extract the language and country for this entry
String language = null;
String country = null;
String variant = null;
int dash = entry.indexOf('-');
if (dash < 0)
{
language = entry;
country = "";
variant = "";
}
else
{
language = entry.substring(0, dash);
country = entry.substring(dash + 1);
int vDash = country.indexOf('-');
if (vDash > 0)
{
String cTemp = country.substring(0, vDash);
variant = country.substring(vDash + 1);
country = cTemp;
}
else
{
variant = "";
}
}
if (!isAlpha(language) || !isAlpha(country) || !isAlpha(variant))
{
continue;
}
// Add a new Locale to the list of Locales for this quality level
Locale locale = new Locale(language, country, variant);
Double key = new Double(-quality); // Reverse the order
ArrayList<Locale> values = locales.get(key);
if (values == null)
{
values = new ArrayList<Locale>();
locales.put(key, values);
}
values.add(locale);
}
// Process the quality values in highest->lowest order (due to
// negating the Double value when creating the key)
for (ArrayList<Locale> list : locales.values())
{
for (Locale locale : list)
{
addLocale(locale);
}
}
}
protected static final boolean isAlpha(String value)
{
for (int i = 0; i < value.length(); i++)
{
char c = value.charAt(i);
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
{
return false;
}
}
return true;
}
/**
* Add a Locale to the set of preferred Locales for this HttpServletRequestImpl. The first added Locale will be the
* first one returned by getLocales().
*
* @param locale
* The new preferred Locale
*/
public void addLocale(Locale locale)
{
if (_locales == null)
_locales = new LinkedList<Locale>();
_locales.add(locale);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getLocalAddr()
*/
@Override
// OK
public String getLocalAddr()
{
InetSocketAddress local = socketChannel.localAddress();
if (local == null)
return "";
InetAddress address = local.getAddress();
if (address == null)
return local.getHostString();
return address.getHostAddress();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getLocalName()
*/
@Override
// ok
public String getLocalName()
{
InetSocketAddress local = socketChannel.localAddress();
return local.getHostString();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getLocalPort()
*/
@Override
// OK
public int getLocalPort()
{
InetSocketAddress local = socketChannel.localAddress();
return local.getPort();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getMethod()
*/
@Override
// OK
public String getMethod()
{
return request.getMethod().toString();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getParameter(java.lang.String)
*/
@Override
// OK
public String getParameter(String name)
{
if (!_paramsExtracted)
extractParameters();
List<String> list = _parameters.get(name);
if (list == null || list.isEmpty())
return null;
return list.get(0);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getParameterMap()
*/
@Override
// OK
public Map<String, String[]> getParameterMap()
{
if (!_paramsExtracted)
extractParameters();
HashMap<String, String[]> map = new HashMap<String, String[]>(_parameters.size() * 3 / 2);
for (Map.Entry<String, List<String>> entry : _parameters.entrySet())
{
String[] a = null;
if (entry.getValue() != null)
{
a = new String[entry.getValue().size()];
a = entry.getValue().toArray(a);
}
map.put(entry.getKey(), a);
}
return Collections.unmodifiableMap(map);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getParameterNames()
*/
@Override
// OK
public Enumeration<String> getParameterNames()
{
if (!_paramsExtracted)
extractParameters();
return Collections.enumeration(_parameters.keySet());
}
/* ------------------------------------------------------------ */
/**
* @return Returns the parameters.
*/
/*
* public MultiMap<String> getParameters() { return _parameters; }
*/
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
*/
@Override
// ok
public String[] getParameterValues(String name)
{
if (!_paramsExtracted)
extractParameters();
List<String> vals = _parameters.get(name);
if (vals == null)
return null;
return vals.toArray(new String[vals.size()]);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getPathInfo()
*/
@Override
public String getPathInfo()
{
if (_invocation != null)
return _invocation.getFilterChainInvocation().getPathInfo();
else
return null;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getPathTranslated()
*/
@Override
public String getPathTranslated()
{
if (_pathInfo == null || servletContext == null)
return null;
return servletContext.getRealPath(_pathInfo);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getProtocol()
*/
@Override
// OK
public String getProtocol()
{
return _httpVersion.toString();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getProtocol()
*/
public HttpVersion getHttpVersion()
{
return _httpVersion;
}
/* ------------------------------------------------------------ */
public String getQueryEncoding()
{
return _queryEncoding;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getQueryString()
*/
@Override
public String getQueryString()
{
if (_invocation != null)
return _invocation.getQueryString();
else
return null;
}
/**
* 从原生的uri中分离出不带参数的RequestURI和参数QueryString
*
* @return
*/
boolean parseRequestURIAndQueryString()
{
if (_queryString == null || _requestURI == null)
{
if (_queryEncoding == null)
{
String uri = request.getUri();
int p = uri.indexOf('?');
if (p != -1)
_queryString = uri.substring(p + 1);
// 同时也设置requestURI
if (p == -1)
_requestURI = uri;
else
_requestURI = uri.substring(0, p);
}
else
{
// TODO: what about other queryEncoding?
}
}
_queryStringExtracted = true;
return true;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getReader()
*/
@Override
// ok
public BufferedReader getReader() throws IOException
{
if (usingInputStream)
{
throw new IllegalStateException("using InputStream already");
}
usingReader = true;
String encoding = getCharacterEncoding();
if (encoding == null)
encoding = "ISO-8859-1";
if (_reader == null || !encoding.equalsIgnoreCase(_readerEncoding))
{
final ServletInputStream in = getInputStream();
_readerEncoding = encoding;
_reader = new BufferedReader(new InputStreamReader(in, encoding))
{
@Override
public void close() throws IOException
{
in.close();
}
};
}
return _reader;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
*/
@Deprecated
@Override
public String getRealPath(String path)
{
if (servletContext == null)
return null;
return servletContext.getRealPath(path);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getRemoteAddr()
*/
@Override
// OK
public String getRemoteAddr()
{
InetSocketAddress remote = _remote;
if (remote == null)
remote = socketChannel.remoteAddress();
if (remote == null)
return "";
InetAddress address = remote.getAddress();
if (address == null)
return remote.getHostString();
return address.getHostAddress();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getRemoteHost()
*/
@Override
// OK
public String getRemoteHost()
{
InetSocketAddress remote = _remote;
if (remote == null)
remote = socketChannel.remoteAddress();
return remote == null ? "" : remote.getHostString();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getRemotePort()
*/
@Override
// OK
public int getRemotePort()
{
InetSocketAddress remote = _remote;
if (remote == null)
remote = socketChannel.remoteAddress();
return remote == null ? 0 : remote.getPort();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getRemoteUser()
*/
@Override
// ok
public String getRemoteUser()
{
Principal p = getUserPrincipal();
if (p == null)
return null;
return p.getName();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
*/
@Override
public RequestDispatcher getRequestDispatcher(String path)
{
if (path == null || servletContext == null)
return null;
// handle relative path
if (!path.startsWith("/"))
{
String relTo = URIUtil.addPaths(_servletPath, _pathInfo);
int slash = relTo.lastIndexOf("/");
if (slash > 1)
relTo = relTo.substring(0, slash + 1);
else
relTo = "/";
path = URIUtil.addPaths(relTo, path);
}
return servletContext.getRequestDispatcher(path);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
*/
@Override
public String getRequestedSessionId()
{
return _requestedSessionId;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getRequestURI()
*/
@Override
public String getRequestURI()
{
if (_invocation != null)
return _invocation.getFilterChainInvocation().getRequestURI();
else
return "";
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getRequestURL()
*/
@Override
public StringBuffer getRequestURL()
{
final StringBuffer url = new StringBuffer(48);
String scheme = getScheme();
int port = getServerPort();
url.append(scheme);
url.append("://");
url.append(getServerName());
if (_port > 0 && ((scheme.equalsIgnoreCase(URIUtil.HTTP) && port != 80) || (scheme.equalsIgnoreCase(URIUtil.HTTPS) && port != 443)))
{
url.append(':');
url.append(_port);
}
url.append(getRequestURI());
return url;
}
/* ------------------------------------------------------------ */
/**
* 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 path.
* <p>
* 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.
*
* This method is useful for creating redirect messages and for reporting errors.
*
* @return "scheme://host:port"
*/
public StringBuilder getRootURL()
{
StringBuilder url = new StringBuilder(48);
String scheme = getScheme();
int port = getServerPort();
url.append(scheme);
url.append("://");
url.append(getServerName());
if (port > 0 && ((scheme.equalsIgnoreCase("http") && port != 80) || (scheme.equalsIgnoreCase("https") && port != 443)))
{
url.append(':');
url.append(port);
}
return url;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getScheme()
*/
@Override
public String getScheme()
{
return _scheme;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getServerName()
*/
@Override
// OK
public String getServerName()
{
if (_serverName == null)
{
parseServerNameAndServerPort();
}
return _serverName;
}
/**
* 1:Return host from header field "Host"
*
* OR:2:Return host from connection
*
* 3:Return the local host
*/
private void parseServerNameAndServerPort()
{
// Return host from header field
String hostPort = getHeader(HttpHeaders.Names.HOST);
if (hostPort != null)
{
loop: for (int i = hostPort.length(); i-- > 0;)
{
char ch = (char) (0xff & hostPort.charAt(i));
switch (ch)
{
case ']':
break loop;
case ':':
_serverName = hostPort.substring(0, i);
try
{
_port = Integer.parseInt(hostPort.substring(i + 1));
}
catch (NumberFormatException e)
{
LOG.warn(e);
}
return;
}
}
if (_serverName == null || _port < 0)
{
_serverName = hostPort;
_port = 0;
}
return;
}
// Return host from connection
if (socketChannel != null)
{
_serverName = getLocalName();
_port = getLocalPort();
if (_serverName != null && !"0.0.0.0".equals(_serverName))
return;
}
// Return the local host
try
{
_serverName = InetAddress.getLocalHost().getHostAddress();
}
catch (java.net.UnknownHostException e)
{
LOG.debug(e);
}
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getServerPort()
*/
@Override
public int getServerPort()
{
if (_port <= 0)
{
if (_serverName == null)
parseServerNameAndServerPort();
if (_port <= 0)
{
InetSocketAddress local = socketChannel.localAddress();
_port = local == null ? 0 : local.getPort();
}
}
if (_port <= 0)
{
if (getScheme().equalsIgnoreCase("https"))
return 443;
return 80;
}
return _port;
}
/* ------------------------------------------------------------ */
@Override
// ok
public ServletContext getServletContext()
{
return servletContext;
}
/* ------------------------------------------------------------ */
/*
*/
/*
* public String getServletName() { if (_scope != null) return _scope.getName(); return null; }
*/
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getServletPath()
*/
@Override
public String getServletPath()
{
if (_invocation != null)
return _invocation.getFilterChainInvocation().getServletPath();
else
return "";
}
/* ------------------------------------------------------------ */
/**
* 从请求的cookie或URL里提取SessionId
* @return
*/
protected String extracteSessionId()
{
String sessionId = findSessionIdFromCookie();
_sessionIdExtracted = true;
return sessionId;
}
/**
* Returns the session id in the HTTP request cookies. Because the webApp might use the cookie to change the page
* contents, the caching sets vary: JSESSIONID.
*/
protected String findSessionIdFromCookie()
{
Cookie cookie = getCookie("JSESSIONID");
if (cookie != null)
{
_isSessionIdFromCookie = true;
return cookie.getValue();
}
else
return null;
}
/**
* 查找特定名称的cookie
* Returns the named cookie from the browser
*/
public Cookie getCookie(String name)
{
Cookie[] cookies = getCookies();
if (cookies == null)
return null;
for (Cookie cookie : cookies)
{
if (cookie.getName().equals(name))
{
return cookie;
}
}
return null;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getSession()
*/
@Override
public HttpSession getSession()
{
return getSession(true);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getSession(boolean)
*/
@Override
public HttpSession getSession(boolean create)
{
if (_session != null)
{
if (_sessionManager.isValid(_session))
return _session;
else
// Session无效
{
_session.invalidate();
_session = null;
}
}
//如果未从COOKIE或URL中解释SESSIONID,则try to extract sessionId from cookie OR URL
if(!_sessionIdExtracted)
{
String sessionId = extracteSessionId();
if(sessionId != null)
{
HttpSessionImpl session = _sessionManager.getSession(sessionId);
if (session != null && _sessionManager.isValid(session))
{
_session = session;
return _session;
}
}
}
if (!create)
return null;
// 创建一个Session
if (_sessionManager == null)
throw new IllegalStateException("No SessionManager");
_session = _sessionManager.createNewSession(this);
Cookie cookie = _sessionManager.getSessionCookie(_session, getContextPath(), isSecure());
if (cookie != null)
{
_httpResponse.addCookie(cookie);
}
return _session;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the sessionManager.
*/
public SessionManager getSessionManager()
{
return _sessionManager;
}
/* ------------------------------------------------------------ */
/**
* Get HttpServletRequestImpl TimeStamp
*
* @return The time that the request was received.
*/
public long getTimeStamp()
{
return _timeStamp;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
*/
@Override
public Principal getUserPrincipal()
{
/*
* if (_authentication instanceof Authentication.Deferred)
* setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
*
* if (_authentication instanceof Authentication.User) { UserIdentity user =
* ((Authentication.User)_authentication).getUserIdentity(); return user.getUserPrincipal(); }
*
* return null;
*/
return null;
}
/* ------------------------------------------------------------ */
/**
* Get timestamp of the request dispatch
*
* @return timestamp
*/
public long getDispatchTime()
{
return _dispatchTime;
}
/* ------------------------------------------------------------ */
public boolean isHandled()
{
return _handled;
}
@Override
public boolean isAsyncStarted()
{
//TODO:NOT support now
return false;
}
/* ------------------------------------------------------------ */
@Override
public boolean isAsyncSupported()
{
return _asyncSupported;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie()
*/
@Override
public boolean isRequestedSessionIdFromCookie()
{
return _requestedSessionId != null && _isSessionIdFromCookie;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl()
*/
@Override
public boolean isRequestedSessionIdFromUrl()
{
return _requestedSessionId != null && !_isSessionIdFromCookie;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL()
*/
@Override
public boolean isRequestedSessionIdFromURL()
{
return _requestedSessionId != null && !_isSessionIdFromCookie;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
*/
@Override
public boolean isRequestedSessionIdValid()
{
if (_requestedSessionId == null)
return false;
HttpSession session = getSession(false);
return (session != null);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#isSecure()
*/
@Override
public boolean isSecure()
{
return _secure;
}
/* ------------------------------------------------------------ */
public void setSecure(boolean secure)
{
_secure = secure;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
*/
@Override
public boolean isUserInRole(String role)
{
/*
* if (_authentication instanceof Authentication.Deferred)
* setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
*
* if (_authentication instanceof Authentication.User) return
* ((Authentication.User)_authentication).isUserInRole(_scope,role); return false;
*/
//TODO:
return false;
}
/* ------------------------------------------------------------ */
protected void recycle()
{
_asyncSupported = true;
_handled = false;
if (servletContext != null)
throw new IllegalStateException("HttpServletRequestImpl in context!");
if (_attributes != null)
_attributes.clear();
_characterEncoding = null;
_contextPath = null;
_cookiesExtracted = false;
_serverName = null;
_pathInfo = null;
_port = 0;
_httpVersion = HttpVersion.HTTP_1_1;
_queryEncoding = null;
_queryString = null;
_requestedSessionId = null;
_isSessionIdFromCookie = false;
_session = null;
_sessionManager = null;
_requestURI = null;
// _scope = null;
_scheme = URIUtil.HTTP;
_servletPath = null;
_timeStamp = 0;
// _uri = null;
if (_parameters != null)
_parameters.clear();
_parameters = null;
_paramsExtracted = false;
_remote = null;
headers.clear();
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
*/
@Override
// OK
public void removeAttribute(String name)
{
if (_attributes == null)
return;
//
boolean found = _attributes.containsKey(name);
if (found)
{
Object value = _attributes.get(name);
_attributes.remove(name);
// Notify interested application event listeners
notifyAttributeRemoved(name, value);
}
}
/* ------------------------------------------------------------ */
public void removeEventListener(final EventListener listener)
{
if (_requestAttributeListeners != null)
_requestAttributeListeners.remove(listener);
}
/* ------------------------------------------------------------ */
public void setAsyncSupported(boolean supported)
{
_asyncSupported = supported;
}
/* ------------------------------------------------------------ */
/*
* 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 {@link #setQueryEncoding}. <p> if the attribute name is
* "org.eclipse.jetty.server.server.ResponseBuffer", then the response buffer is flushed with @{link
* #flushResponseBuffer} <p> if the attribute name is "org.eclipse.jetty.io.EndPoint.maxIdleTime", then the value is
* passed to the associated {@link EndPoint#setIdleTimeout}.
*
* @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object)
*/
@Override
// OK
public void setAttribute(String name, Object value)
{
// Name cannot be null
if (name == null)
{
throw new IllegalArgumentException("Name cannot be null");
}
// Null value is the same as removeAttribute()
if (value == null)
{
removeAttribute(name);
return;
}
if (_attributes == null)
_attributes = new HashMap<String, Object>();
Object oldValue = _attributes.put(name, value);
// Notify interested ServletRequestAttributeListeners
if (oldValue == null)
notifyAttributeAdded(name, value);
else
notifyAttributeReplaced(name, oldValue);
}
/* ------------------------------------------------------------ */
/**
* Notify interested ServletRequestAttributeListeners that attribute has been assigned a value.
*
* 发布属性增加事件
*
*/
private void notifyAttributeAdded(String name, Object value)
{
if (_requestAttributeListeners != null && !_requestAttributeListeners.isEmpty())
{
final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(servletContext, this, name, value);
for (ServletRequestAttributeListener listener : _requestAttributeListeners)
{
listener.attributeAdded(event);
}
}
}
/**
* Notify interested ServletRequestAttributeListeners that attribute has been Replaced.
*
* 发布属性被取代事件
*/
private void notifyAttributeReplaced(String name, Object oldValue)
{
if (_requestAttributeListeners != null && !_requestAttributeListeners.isEmpty())
{
final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(servletContext, this, name, oldValue);
for (ServletRequestAttributeListener listener : _requestAttributeListeners)
{
listener.attributeReplaced(event);
}
}
}
/* ------------------------------------------------------------ */
/**
* Notify interested listeners that attribute has been removed. 发布属性被删除事件
*/
private void notifyAttributeRemoved(String name, Object value)
{
if (_requestAttributeListeners != null && !_requestAttributeListeners.isEmpty())
{
final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(servletContext, this, name, value);
for (ServletRequestAttributeListener listener : _requestAttributeListeners)
{
listener.attributeRemoved(event);
}
}
}
/* ------------------------------------------------------------ */
/*
*/
public void setAttributes(Map<String, Object> attributes)
{
_attributes = attributes;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
*/
@Override
// OK
public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException
{
if (usingReader)
{
return;
}
_characterEncoding = encoding;
// check encoding is supported
if (!"UTF-8".equalsIgnoreCase(encoding))
Charset.forName(encoding);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String)
*/
public void setCharacterEncodingUnchecked(String encoding)
{
_characterEncoding = encoding;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getContentType()
*/
public void setContentType(String contentType)
{
headers.set(HttpHeaders.Names.CONTENT_TYPE, contentType);
}
/* ------------------------------------------------------------ */
/**
* Set request context
*
* @param context
* context object
*/
/*
* public void setContext(DefalutServletContext context) { _newContext = servletContext != context; servletContext =
* context; }
*/
/* ------------------------------------------------------------ */
/**
* @return True if this is the first call of {@link #takeNewContext()} since the last
* {@link #setContext(org.eclipse.jetty.server.handler.ContextHandler.Context)} call.
*/
public boolean takeNewContext()
{
boolean nc = _newContext;
_newContext = false;
return nc;
}
/* ------------------------------------------------------------ */
/**
* Sets the "context path" for this request
*
* @see HttpServletRequest#getContextPath()
*/
public void setContextPath(String contextPath)
{
_contextPath = contextPath;
}
/* ------------------------------------------------------------ */
/**
* @param cookies
* The cookies to set.
*/
public void setCookies(Cookie[] cookies)
{
this.cookies = cookies;
}
/* ------------------------------------------------------------ */
public void setDispatcherType(DispatcherType type)
{
_dispatcherType = type;
}
/* ------------------------------------------------------------ */
public void setHandled(boolean h)
{
_handled = h;
}
/* ------------------------------------------------------------ */
/**
* @param method
* The method to set.
*/
public void setMethod(HttpMethod httpMethod)
{
_httpMethod = httpMethod;
}
/* ------------------------------------------------------------ */
public boolean isHead()
{
return HttpMethod.HEAD == _httpMethod;
}
/* ------------------------------------------------------------ */
/**
* @param parameters
* The parameters to set.
*/
public void setParameters(Map<String, List<String>> parameters)
{
_parameters = (parameters == null) ? _parameters : parameters;
if (_paramsExtracted && _parameters == null)
throw new IllegalStateException();
}
/* ------------------------------------------------------------ */
/**
* @param pathInfo
* The pathInfo to set.
*/
public void setPathInfo(String pathInfo)
{
_pathInfo = pathInfo;
}
/* ------------------------------------------------------------ */
/**
* @param version
* The protocol to set.
*/
public void setHttpVersion(HttpVersion version)
{
_httpVersion = version;
}
/* ------------------------------------------------------------ */
/**
* 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 geParameter methods.
*
* The request attribute "org.eclipse.jetty.server.server.Request.queryEncoding" may be set as an alternate method
* of calling setQueryEncoding.
*
* @param queryEncoding
*/
public void setQueryEncoding(String queryEncoding)
{
_queryEncoding = queryEncoding;
_queryString = null;
}
/* ------------------------------------------------------------ */
/**
* @param queryString
* The queryString to set.
*/
public void setQueryString(String queryString)
{
_queryString = queryString;
_queryEncoding = null; // assume utf-8
}
/* ------------------------------------------------------------ */
/**
* @param addr
* The address to set.
*/
public void setRemoteAddr(InetSocketAddress addr)
{
_remote = addr;
}
/* ------------------------------------------------------------ */
/**
* @param requestedSessionId
* The requestedSessionId to set.
*/
public void setRequestedSessionId(String requestedSessionId)
{
_requestedSessionId = requestedSessionId;
}
/* ------------------------------------------------------------ */
/**
* @param requestedSessionIdCookie
* The requestedSessionIdCookie to set.
*/
public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie)
{
_isSessionIdFromCookie = requestedSessionIdCookie;
}
/* ------------------------------------------------------------ */
/**
* @param requestURI
* The requestURI to set.
*/
public void setRequestURI(String requestURI)
{
_requestURI = requestURI;
}
/* ------------------------------------------------------------ */
/**
* @param scheme
* The scheme to set.
*/
public void setScheme(String scheme)
{
_scheme = scheme;
}
/* ------------------------------------------------------------ */
/**
* @param host
* The host to set.
*/
public void setServerName(String host)
{
_serverName = host;
}
/* ------------------------------------------------------------ */
/**
* @param port
* The port to set.
*/
public void setServerPort(int port)
{
_port = port;
}
/* ------------------------------------------------------------ */
/**
* @param servletPath
* The servletPath to set.
*/
public void setServletPath(String servletPath)
{
_servletPath = servletPath;
}
/* ------------------------------------------------------------ */
/**
* @param session
* The session to set.
*/
public void setSession(HttpSessionImpl session)
{
_session = session;
}
/* ------------------------------------------------------------ */
/**
* @param sessionManager
* The sessionManager to set.
*/
public void setSessionManager(SessionManager sessionManager)
{
_sessionManager = sessionManager;
}
/* ------------------------------------------------------------ */
public void setTimeStamp(long ts)
{
_timeStamp = ts;
}
/* ------------------------------------------------------------ */
/**
* Set timetstamp of request dispatch
*
* @param value
* timestamp
*/
public void setDispatchTime(long value)
{
_dispatchTime = value;
}
/* ------------------------------------------------------------ */
@Override
public AsyncContext startAsync() throws IllegalStateException
{
/*
* if (!_asyncSupported) throw new IllegalStateException("!asyncSupported"); HttpChannelState state =
* getHttpChannelState(); state.startAsync(); return state;
*/
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
{
/*
* if (!_asyncSupported) throw new IllegalStateException("!asyncSupported"); HttpChannelState state =
* getHttpChannelState(); state.startAsync(servletContext, servletRequest, servletResponse); return state;
*/
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return (_handled ? "[" : "(") + getMethod() + " " + request.getUri() + (_handled ? "]@" : ")@") + hashCode() + " " + super.toString();
}
/* ------------------------------------------------------------ */
@Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
@Override
public Part getPart(String name) throws IOException, ServletException
{
/*
* if (getContentType() == null || !getContentType().startsWith("multipart/form-data")) throw new
* ServletException("Content-Type != multipart/form-data");
*
* if (_multiPartInputStream == null) { MultipartConfigElement config =
* (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT);
*
* if (config == null) throw new IllegalStateException("No multipart config for servlet");
*
* _multiPartInputStream = new MultiPartInputStreamParser(getInputStream(), getContentType(),config,
* (servletContext != null?(File)servletContext.getAttribute("javax.servlet.context.tempdir"):null));
* setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream); setAttribute(__MULTIPART_CONTEXT,
* servletContext); Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing for (Part
* p:parts) { MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart)p; if
* (mp.getContentDispositionFilename() == null && mp.getFile() == null) { //Servlet Spec 3.0 pg 23, parts
* without filenames must be put into init params String charset = null; if (mp.getContentType() != null)
* charset = MimeTypes.getCharsetFromContentType(mp.getContentType());
*
* String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset); getParameter(""); //cause
* params to be evaluated getParameters().add(mp.getName(), content); } } } return
* _multiPartInputStream.getPart(name);
*/
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
@Override
public Collection<Part> getParts() throws IOException, ServletException
{
/*
* if (getContentType() == null || !getContentType().startsWith("multipart/form-data")) throw new
* ServletException("Content-Type != multipart/form-data");
*
* if (_multiPartInputStream == null) { MultipartConfigElement config =
* (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT);
*
* if (config == null) throw new IllegalStateException("No multipart config for servlet");
*
* _multiPartInputStream = new MultiPartInputStreamParser(getInputStream(), getContentType(), config,
* (servletContext != null?(File)servletContext.getAttribute("javax.servlet.context.tempdir"):null));
*
* setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream); setAttribute(__MULTIPART_CONTEXT,
* servletContext); Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing for (Part
* p:parts) { MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart)p; if
* (mp.getContentDispositionFilename() == null && mp.getFile() == null) { //Servlet Spec 3.0 pg 23, parts
* without filenames must be put into init params String charset = null; if (mp.getContentType() != null)
* charset = MimeTypes.getCharsetFromContentType(mp.getContentType());
*
* String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset); getParameter(""); //cause
* params to be evaluated getParameters().add(mp.getName(), content); } } } return
* _multiPartInputStream.getParts();
*/
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
@Override
public void login(String username, String password) throws ServletException
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
@Override
public void logout() throws ServletException
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
/**
* Merge in a new query string. The query string is merged with the existing parameters and
* {@link #setParameters(MultiMap)} and {@link #setQueryString(String)} are called with the result. The merge is
* according to the rules of the servlet dispatch forward method.
*
* @param query
* The query string to merge into the request.
*/
/*
* public void mergeQueryString(String query) { // extract parameters from dispatch query MultiMap<String>
* parameters = new MultiMap<>(); UrlEncoded.decodeTo(query,parameters, StringUtil.__UTF8_CHARSET,-1); //have to
* assume UTF-8 because we can't know otherwise
*
* boolean merge_old_query = false;
*
* // Have we evaluated parameters if (!_paramsExtracted) extractParameters();
*
* // Are there any existing parameters? if (_parameters != null && _parameters.size() > 0) { // Merge parameters;
* new parameters of the same name take precedence. merge_old_query = parameters.addAllValues(_parameters); }
*
* if (_queryString != null && _queryString.length() > 0) { if (merge_old_query) { StringBuilder
* overridden_query_string = new StringBuilder(); MultiMap<String> overridden_old_query = new MultiMap<>();
* UrlEncoded.decodeTo(_queryString,overridden_old_query,getQueryEncoding(),-1);//decode using any queryencoding set
* for the request
*
*
* MultiMap<String> overridden_new_query = new MultiMap<>();
* UrlEncoded.decodeTo(query,overridden_new_query,StringUtil.__UTF8_CHARSET,-1); //have to assume utf8 as we cannot
* know otherwise
*
* for(String name: overridden_old_query.keySet()) { if (!overridden_new_query.containsKey(name)) { List<String>
* values = overridden_old_query.get(name); for(String v: values) {
* overridden_query_string.append("&").append(name).append("=").append(v); } } }
*
* query = query + overridden_query_string; } else { query = query + "&" + _queryString; } }
*
* setParameters(parameters); setQueryString(query); }
*/
public FullHttpRequest getFullHttpRequest()
{
return request;
}
public Map<String, List<String>> getParameters()
{
return _parameters;
}
/* ------------------------------------------------------------ */
/**
* Merge in a new query string. The query string is merged with the existing parameters and
* {@link #setParameters(MultiMap)} and {@link #setQueryString(String)} are called with the result. The merge is
* according to the rules of the servlet dispatch forward method.
*
* @param query
* The query string to merge into the request.
*/
public void mergeQueryString(String query)
{
/*
* // extract parameters from dispatch query MultiMap<String> parameters = new MultiMap<>();
* UrlEncoded.decodeTo(query,parameters, StringUtil.__UTF8_CHARSET,-1); //have to assume UTF-8 because we can't
* know otherwise
*
* boolean merge_old_query = false;
*
* // Have we evaluated parameters if (!_paramsExtracted) extractParameters();
*
* // Are there any existing parameters? if (_parameters != null && _parameters.size() > 0) { // Merge
* parameters; new parameters of the same name take precedence. merge_old_query =
* parameters.addAllValues(_parameters); }
*
* if (_queryString != null && _queryString.length() > 0) { if (merge_old_query) { StringBuilder
* overridden_query_string = new StringBuilder(); MultiMap<String> overridden_old_query = new MultiMap<>();
* UrlEncoded.decodeTo(_queryString,overridden_old_query,getQueryEncoding(),-1);//decode using any queryencoding
* set for the request
*
*
* MultiMap<String> overridden_new_query = new MultiMap<>();
* UrlEncoded.decodeTo(query,overridden_new_query,StringUtil.__UTF8_CHARSET,-1); //have to assume utf8 as we
* cannot know otherwise
*
* for(String name: overridden_old_query.keySet()) { if (!overridden_new_query.containsKey(name)) { List<String>
* values = overridden_old_query.get(name); for(String v: values) {
* overridden_query_string.append("&").append(name).append("=").append(v); } } }
*
* query = query + overridden_query_string; } else { query = query + "&" + _queryString; } }
*
* setParameters(parameters); setQueryString(query);
*/
}
public HttpInvocation getInvocation()
{
return _invocation;
}
public void setInvocation(HttpInvocation invocation)
{
this._invocation = invocation;
}
}