Mercurial Hosting > luan
diff src/org/eclipse/jetty/server/Request.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 09d518d313b7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/eclipse/jetty/server/Request.java Wed Sep 07 21:15:48 2016 -0600 @@ -0,0 +1,2204 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 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.eclipse.jetty.server; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.InetAddress; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; + +import javax.servlet.AsyncContext; +import javax.servlet.AsyncEvent; +import javax.servlet.AsyncListener; +import javax.servlet.DispatcherType; +import javax.servlet.MultipartConfigElement; +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 org.eclipse.jetty.continuation.Continuation; +import org.eclipse.jetty.continuation.ContinuationListener; +import org.eclipse.jetty.http.HttpCookie; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeaders; +import org.eclipse.jetty.http.HttpMethods; +import org.eclipse.jetty.http.HttpParser; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.http.HttpVersions; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.io.Buffer; +import org.eclipse.jetty.io.BufferUtil; +import org.eclipse.jetty.io.ByteArrayBuffer; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.io.nio.DirectNIOBuffer; +import org.eclipse.jetty.io.nio.IndirectNIOBuffer; +import org.eclipse.jetty.io.nio.NIOBuffer; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.ContextHandler.Context; +import org.eclipse.jetty.util.Attributes; +import org.eclipse.jetty.util.AttributesMap; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.LazyList; +import org.eclipse.jetty.util.MultiException; +import org.eclipse.jetty.util.MultiMap; +import org.eclipse.jetty.util.MultiPartInputStream; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.URIUtil; +import org.eclipse.jetty.util.UrlEncoded; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/* ------------------------------------------------------------ */ +/** + * Jetty Request. + * <p> + * Implements {@link javax.servlet.http.HttpServletRequest} from the <code>javax.servlet.http</code> package. + * </p> + * <p> + * 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 + * request object to be as lightweight as possible and not actually implement any significant behavior. For example + * <ul> + * + * <li>The {@link Request#getContextPath()} method will return null, until the request has been passed to a {@link ContextHandler} which matches the + * {@link Request#getPathInfo()} with a context path and calls {@link Request#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 Request#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 Request#setServletPath(String)} called as a result.</li> + * </ul> + * + * A request instance is created for each {@link AbstractHttpConnection} 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 Request implements HttpServletRequest +{ + public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.multipartConfig"; + public static final String __MULTIPART_INPUT_STREAM = "org.eclipse.multiPartInputStream"; + public static final String __MULTIPART_CONTEXT = "org.eclipse.multiPartContext"; + private static final Logger LOG = Log.getLogger(Request.class); + + private static final String __ASYNC_FWD = "org.eclipse.asyncfwd"; + private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault()); + private static final int __NONE = 0, _STREAM = 1, __READER = 2; + + public static class MultiPartCleanerListener implements ServletRequestListener + { + + @Override + public void requestDestroyed(ServletRequestEvent sre) + { + //Clean up any tmp files created by MultiPartInputStream + MultiPartInputStream mpis = (MultiPartInputStream)sre.getServletRequest().getAttribute(__MULTIPART_INPUT_STREAM); + if (mpis != null) + { + ContextHandler.Context context = (ContextHandler.Context)sre.getServletRequest().getAttribute(__MULTIPART_CONTEXT); + + //Only do the cleanup if we are exiting from the context in which a servlet parsed the multipart files + if (context == sre.getServletContext()) + { + try + { + mpis.deleteParts(); + } + catch (MultiException e) + { + sre.getServletContext().log("Errors deleting multipart tmp files", e); + } + } + } + } + + @Override + public void requestInitialized(ServletRequestEvent sre) + { + //nothing to do, multipart config set up by ServletHolder.handle() + } + + } + + + /* ------------------------------------------------------------ */ + public static Request getRequest(HttpServletRequest request) + { + if (request instanceof Request) + return (Request)request; + + return AbstractHttpConnection.getCurrentConnection().getRequest(); + } + protected final AsyncContinuation _async = new AsyncContinuation(); + private boolean _asyncSupported = true; + private volatile Attributes _attributes; + private Authentication _authentication; + private MultiMap<String> _baseParameters; + private String _characterEncoding; + protected AbstractHttpConnection _connection; + private ContextHandler.Context _context; + private boolean _newContext; + private String _contextPath; + private CookieCutter _cookies; + private boolean _cookiesExtracted = false; + private DispatcherType _dispatcherType; + private boolean _dns = false; + private EndPoint _endp; + private boolean _handled = false; + private int _inputState = __NONE; + private String _method; + private MultiMap<String> _parameters; + private boolean _paramsExtracted; + private String _pathInfo; + private int _port; + private String _protocol = HttpVersions.HTTP_1_1; + private String _queryEncoding; + private String _queryString; + private BufferedReader _reader; + private String _readerEncoding; + private String _remoteAddr; + private String _remoteHost; + private Object _requestAttributeListeners; + private String _requestedSessionId; + private boolean _requestedSessionIdFromCookie = false; + private String _requestURI; + private Map<Object, HttpSession> _savedNewSessions; + private String _scheme = URIUtil.HTTP; + private UserIdentity.Scope _scope; + private String _serverName; + private String _servletPath; + private HttpSession _session; + private SessionManager _sessionManager; + private long _timeStamp; + private long _dispatchTime; + + private Buffer _timeStampBuffer; + private HttpURI _uri; + + private MultiPartInputStream _multiPartInputStream; //if the request is a multi-part mime + + /* ------------------------------------------------------------ */ + public Request() + { + } + + /* ------------------------------------------------------------ */ + public Request(AbstractHttpConnection connection) + { + setConnection(connection); + } + + /* ------------------------------------------------------------ */ + public void addEventListener(final EventListener listener) + { + if (listener instanceof ServletRequestAttributeListener) + _requestAttributeListeners = LazyList.add(_requestAttributeListeners,listener); + if (listener instanceof ContinuationListener) + throw new IllegalArgumentException(listener.getClass().toString()); + if (listener instanceof AsyncListener) + throw new IllegalArgumentException(listener.getClass().toString()); + } + + /* ------------------------------------------------------------ */ + /** + * Extract Parameters from query string and/or form _content. + */ + public void extractParameters() + { + if (_baseParameters == null) + _baseParameters = new MultiMap(16); + + if (_paramsExtracted) + { + if (_parameters == null) + _parameters = _baseParameters; + return; + } + + _paramsExtracted = true; + + try + { + // Handle query string + if (_uri != null && _uri.hasQuery()) + { + if (_queryEncoding == null) + _uri.decodeQueryTo(_baseParameters); + else + { + try + { + _uri.decodeQueryTo(_baseParameters,_queryEncoding); + } + catch (UnsupportedEncodingException e) + { + if (LOG.isDebugEnabled()) + LOG.warn(e); + else + LOG.warn(e.toString()); + } + } + } + + // handle any _content. + String encoding = getCharacterEncoding(); + String content_type = getContentType(); + if (content_type != null && content_type.length() > 0) + { + content_type = HttpFields.valueParameters(content_type,null); + + if (MimeTypes.FORM_ENCODED.equalsIgnoreCase(content_type) && _inputState == __NONE + && (HttpMethods.POST.equals(getMethod()) || HttpMethods.PUT.equals(getMethod()))) + { + int content_length = getContentLength(); + if (content_length != 0) + { + try + { + int maxFormContentSize = -1; + int maxFormKeys = -1; + + if (_context != null) + { + maxFormContentSize = _context.getContextHandler().getMaxFormContentSize(); + maxFormKeys = _context.getContextHandler().getMaxFormKeys(); + } + + if (maxFormContentSize < 0) + { + Object obj = _connection.getConnector().getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize"); + if (obj == null) + maxFormContentSize = 200000; + else if (obj instanceof Number) + { + Number size = (Number)obj; + maxFormContentSize = size.intValue(); + } + else if (obj instanceof String) + { + maxFormContentSize = Integer.valueOf((String)obj); + } + } + + if (maxFormKeys < 0) + { + Object obj = _connection.getConnector().getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormKeys"); + if (obj == null) + maxFormKeys = 1000; + else if (obj instanceof Number) + { + Number keys = (Number)obj; + maxFormKeys = keys.intValue(); + } + else if (obj instanceof String) + { + maxFormKeys = Integer.valueOf((String)obj); + } + } + + if (content_length > maxFormContentSize && maxFormContentSize > 0) + { + throw new IllegalStateException("Form too large " + content_length + ">" + maxFormContentSize); + } + InputStream in = getInputStream(); + + // Add form params to query params + UrlEncoded.decodeTo(in,_baseParameters,encoding,content_length < 0?maxFormContentSize:-1,maxFormKeys); + } + catch (IOException e) + { + if (LOG.isDebugEnabled()) + LOG.warn(e); + else + LOG.warn(e.toString()); + } + } + } + + } + + if (_parameters == null) + _parameters = _baseParameters; + else if (_parameters != _baseParameters) + { + // Merge parameters (needed if parameters extracted after a forward). + Iterator iter = _baseParameters.entrySet().iterator(); + while (iter.hasNext()) + { + Map.Entry entry = (Map.Entry)iter.next(); + String name = (String)entry.getKey(); + Object values = entry.getValue(); + for (int i = 0; i < LazyList.size(values); i++) + _parameters.add(name,LazyList.get(values,i)); + } + } + + if (content_type != null && content_type.length()>0 && content_type.startsWith("multipart/form-data") && getAttribute(__MULTIPART_CONFIG_ELEMENT)!=null) + { + try + { + getParts(); + } + catch (IOException e) + { + if (LOG.isDebugEnabled()) + LOG.warn(e); + else + LOG.warn(e.toString()); + } + catch (ServletException e) + { + if (LOG.isDebugEnabled()) + LOG.warn(e); + else + LOG.warn(e.toString()); + } + } + } + finally + { + // ensure params always set (even if empty) after extraction + if (_parameters == null) + _parameters = _baseParameters; + } + } + + /* ------------------------------------------------------------ */ + public AsyncContext getAsyncContext() + { + if (_async.isInitial() && !_async.isAsyncStarted()) + throw new IllegalStateException(_async.getStatusString()); + return _async; + } + + /* ------------------------------------------------------------ */ + public AsyncContinuation getAsyncContinuation() + { + return _async; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getAttribute(java.lang.String) + */ + public Object getAttribute(String name) + { + if ("org.eclipse.jetty.io.EndPoint.maxIdleTime".equalsIgnoreCase(name)) + return new Long(getConnection().getEndPoint().getMaxIdleTime()); + + Object attr = (_attributes == null)?null:_attributes.getAttribute(name); + if (attr == null && Continuation.ATTRIBUTE.equals(name)) + return _async; + return attr; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getAttributeNames() + */ + public Enumeration getAttributeNames() + { + if (_attributes == null) + return Collections.enumeration(Collections.EMPTY_LIST); + + return AttributesMap.getAttributeNamesCopy(_attributes); + } + + /* ------------------------------------------------------------ */ + /* + */ + public Attributes getAttributes() + { + if (_attributes == null) + _attributes = new AttributesMap(); + return _attributes; + } + + /* ------------------------------------------------------------ */ + /** + * Get the authentication. + * + * @return the authentication + */ + public Authentication getAuthentication() + { + return _authentication; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getAuthType() + */ + public String getAuthType() + { + if (_authentication instanceof Authentication.Deferred) + setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); + + if (_authentication instanceof Authentication.User) + return ((Authentication.User)_authentication).getAuthMethod(); + return null; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getCharacterEncoding() + */ + public String getCharacterEncoding() + { + return _characterEncoding; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the connection. + */ + public AbstractHttpConnection getConnection() + { + return _connection; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getContentLength() + */ + public int getContentLength() + { + return (int)_connection.getRequestFields().getLongField(HttpHeaders.CONTENT_LENGTH_BUFFER); + } + + public long getContentRead() + { + if (_connection == null || _connection.getParser() == null) + return -1; + + return ((HttpParser)_connection.getParser()).getContentRead(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getContentType() + */ + public String getContentType() + { + return _connection.getRequestFields().getStringField(HttpHeaders.CONTENT_TYPE_BUFFER); + } + + /* ------------------------------------------------------------ */ + /** + * @return The current {@link Context context} used for this request, or <code>null</code> if {@link #setContext} has not yet been called. + */ + public Context getContext() + { + return _context; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getContextPath() + */ + public String getContextPath() + { + return _contextPath; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getCookies() + */ + public Cookie[] getCookies() + { + if (_cookiesExtracted) + return _cookies == null?null:_cookies.getCookies(); + + _cookiesExtracted = true; + + Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.COOKIE_BUFFER); + + // Handle no cookies + if (enm != null) + { + if (_cookies == null) + _cookies = new CookieCutter(); + + while (enm.hasMoreElements()) + { + String c = (String)enm.nextElement(); + _cookies.addCookieField(c); + } + } + + return _cookies == null?null:_cookies.getCookies(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String) + */ + public long getDateHeader(String name) + { + return _connection.getRequestFields().getDateField(name); + } + + /* ------------------------------------------------------------ */ + public DispatcherType getDispatcherType() + { + return _dispatcherType; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String) + */ + public String getHeader(String name) + { + return _connection.getRequestFields().getStringField(name); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getHeaderNames() + */ + public Enumeration getHeaderNames() + { + return _connection.getRequestFields().getFieldNames(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String) + */ + public Enumeration getHeaders(String name) + { + Enumeration e = _connection.getRequestFields().getValues(name); + if (e == null) + return Collections.enumeration(Collections.EMPTY_LIST); + return e; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the inputState. + */ + public int getInputState() + { + return _inputState; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getInputStream() + */ + public ServletInputStream getInputStream() throws IOException + { + if (_inputState != __NONE && _inputState != _STREAM) + throw new IllegalStateException("READER"); + _inputState = _STREAM; + return _connection.getInputStream(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String) + */ + public int getIntHeader(String name) + { + return (int)_connection.getRequestFields().getLongField(name); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocalAddr() + */ + public String getLocalAddr() + { + return _endp == null?null:_endp.getLocalAddr(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocale() + */ + public Locale getLocale() + { + Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.ACCEPT_LANGUAGE,HttpFields.__separators); + + // handle no locale + if (enm == null || !enm.hasMoreElements()) + return Locale.getDefault(); + + // sort the list in quality order + List acceptLanguage = HttpFields.qualityList(enm); + if (acceptLanguage.size() == 0) + return Locale.getDefault(); + + int size = acceptLanguage.size(); + + if (size > 0) + { + String language = (String)acceptLanguage.get(0); + language = HttpFields.valueParameters(language,null); + String country = ""; + int dash = language.indexOf('-'); + if (dash > -1) + { + country = language.substring(dash + 1).trim(); + language = language.substring(0,dash).trim(); + } + return new Locale(language,country); + } + + return Locale.getDefault(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocales() + */ + public Enumeration getLocales() + { + + Enumeration enm = _connection.getRequestFields().getValues(HttpHeaders.ACCEPT_LANGUAGE,HttpFields.__separators); + + // handle no locale + if (enm == null || !enm.hasMoreElements()) + return Collections.enumeration(__defaultLocale); + + // sort the list in quality order + List acceptLanguage = HttpFields.qualityList(enm); + + if (acceptLanguage.size() == 0) + return Collections.enumeration(__defaultLocale); + + Object langs = null; + int size = acceptLanguage.size(); + + // convert to locals + for (int i = 0; i < size; i++) + { + String language = (String)acceptLanguage.get(i); + language = HttpFields.valueParameters(language,null); + String country = ""; + int dash = language.indexOf('-'); + if (dash > -1) + { + country = language.substring(dash + 1).trim(); + language = language.substring(0,dash).trim(); + } + langs = LazyList.ensureSize(langs,size); + langs = LazyList.add(langs,new Locale(language,country)); + } + + if (LazyList.size(langs) == 0) + return Collections.enumeration(__defaultLocale); + + return Collections.enumeration(LazyList.getList(langs)); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocalName() + */ + public String getLocalName() + { + if (_endp == null) + return null; + if (_dns) + return _endp.getLocalHost(); + + String local = _endp.getLocalAddr(); + if (local != null && local.indexOf(':') >= 0) + local = "[" + local + "]"; + return local; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getLocalPort() + */ + public int getLocalPort() + { + return _endp == null?0:_endp.getLocalPort(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getMethod() + */ + public String getMethod() + { + return _method; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getParameter(java.lang.String) + */ + public String getParameter(String name) + { + if (!_paramsExtracted) + extractParameters(); + return (String)_parameters.getValue(name,0); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getParameterMap() + */ + public Map getParameterMap() + { + if (!_paramsExtracted) + extractParameters(); + + return Collections.unmodifiableMap(_parameters.toStringArrayMap()); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getParameterNames() + */ + public Enumeration 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) + */ + public String[] getParameterValues(String name) + { + if (!_paramsExtracted) + extractParameters(); + List<Object> vals = _parameters.getValues(name); + if (vals == null) + return null; + return vals.toArray(new String[vals.size()]); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getPathInfo() + */ + public String getPathInfo() + { + return _pathInfo; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getPathTranslated() + */ + public String getPathTranslated() + { + if (_pathInfo == null || _context == null) + return null; + return _context.getRealPath(_pathInfo); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getProtocol() + */ + public String getProtocol() + { + return _protocol; + } + + /* ------------------------------------------------------------ */ + public String getQueryEncoding() + { + return _queryEncoding; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getQueryString() + */ + public String getQueryString() + { + if (_queryString == null && _uri != null) + { + if (_queryEncoding == null) + _queryString = _uri.getQuery(); + else + _queryString = _uri.getQuery(_queryEncoding); + } + return _queryString; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getReader() + */ + public BufferedReader getReader() throws IOException + { + if (_inputState != __NONE && _inputState != __READER) + throw new IllegalStateException("STREAMED"); + + if (_inputState == __READER) + return _reader; + + String encoding = getCharacterEncoding(); + if (encoding == null) + encoding = StringUtil.__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(); + } + }; + } + _inputState = __READER; + return _reader; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRealPath(java.lang.String) + */ + public String getRealPath(String path) + { + if (_context == null) + return null; + return _context.getRealPath(path); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRemoteAddr() + */ + public String getRemoteAddr() + { + if (_remoteAddr != null) + return _remoteAddr; + return _endp == null?null:_endp.getRemoteAddr(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRemoteHost() + */ + public String getRemoteHost() + { + if (_dns) + { + if (_remoteHost != null) + { + return _remoteHost; + } + return _endp == null?null:_endp.getRemoteHost(); + } + return getRemoteAddr(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRemotePort() + */ + public int getRemotePort() + { + return _endp == null?0:_endp.getRemotePort(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getRemoteUser() + */ + public String getRemoteUser() + { + Principal p = getUserPrincipal(); + if (p == null) + return null; + return p.getName(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String) + */ + public RequestDispatcher getRequestDispatcher(String path) + { + if (path == null || _context == 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 _context.getRequestDispatcher(path); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId() + */ + public String getRequestedSessionId() + { + return _requestedSessionId; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getRequestURI() + */ + public String getRequestURI() + { + if (_requestURI == null && _uri != null) + _requestURI = _uri.getPathAndParam(); + return _requestURI; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getRequestURL() + */ + public StringBuffer getRequestURL() + { + final StringBuffer url = new StringBuffer(48); + synchronized (url) + { + 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; + } + } + + /* ------------------------------------------------------------ */ + public Response getResponse() + { + return _connection._response; + } + + /* ------------------------------------------------------------ */ + /** + * 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() + */ + public String getScheme() + { + return _scheme; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getServerName() + */ + public String getServerName() + { + // Return already determined host + if (_serverName != null) + return _serverName; + + if (_uri == null) + throw new IllegalStateException("No uri"); + + // Return host from absolute URI + _serverName = _uri.getHost(); + _port = _uri.getPort(); + if (_serverName != null) + return _serverName; + + // Return host from header field + Buffer hostPort = _connection.getRequestFields().get(HttpHeaders.HOST_BUFFER); + if (hostPort != null) + { + loop: for (int i = hostPort.putIndex(); i-- > hostPort.getIndex();) + { + char ch = (char)(0xff & hostPort.peek(i)); + switch (ch) + { + case ']': + break loop; + + case ':': + _serverName = BufferUtil.to8859_1_String(hostPort.peek(hostPort.getIndex(),i - hostPort.getIndex())); + try + { + _port = BufferUtil.toInt(hostPort.peek(i + 1,hostPort.putIndex() - i - 1)); + } + catch (NumberFormatException e) + { + try + { + if (_connection != null) + _connection._generator.sendError(HttpStatus.BAD_REQUEST_400,"Bad Host header",null,true); + } + catch (IOException e1) + { + throw new RuntimeException(e1); + } + } + return _serverName; + } + } + if (_serverName == null || _port < 0) + { + _serverName = BufferUtil.to8859_1_String(hostPort); + _port = 0; + } + + return _serverName; + } + + // Return host from connection + if (_connection != null) + { + _serverName = getLocalName(); + _port = getLocalPort(); + if (_serverName != null && !StringUtil.ALL_INTERFACES.equals(_serverName)) + return _serverName; + } + + // Return the local host + try + { + _serverName = InetAddress.getLocalHost().getHostAddress(); + } + catch (java.net.UnknownHostException e) + { + LOG.ignore(e); + } + return _serverName; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getServerPort() + */ + public int getServerPort() + { + if (_port <= 0) + { + if (_serverName == null) + getServerName(); + + if (_port <= 0) + { + if (_serverName != null && _uri != null) + _port = _uri.getPort(); + else + _port = _endp == null?0:_endp.getLocalPort(); + } + } + + if (_port <= 0) + { + if (getScheme().equalsIgnoreCase(URIUtil.HTTPS)) + return 443; + return 80; + } + return _port; + } + + /* ------------------------------------------------------------ */ + public ServletContext getServletContext() + { + return _context; + } + + /* ------------------------------------------------------------ */ + /* + */ + public String getServletName() + { + if (_scope != null) + return _scope.getName(); + return null; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getServletPath() + */ + public String getServletPath() + { + if (_servletPath == null) + _servletPath = ""; + return _servletPath; + } + + /* ------------------------------------------------------------ */ + public ServletResponse getServletResponse() + { + return _connection.getResponse(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getSession() + */ + public HttpSession getSession() + { + return getSession(true); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getSession(boolean) + */ + public HttpSession getSession(boolean create) + { + if (_session != null) + { + if (_sessionManager != null && !_sessionManager.isValid(_session)) + _session = null; + else + return _session; + } + + if (!create) + return null; + + if (_sessionManager == null) + throw new IllegalStateException("No SessionManager"); + + _session = _sessionManager.newHttpSession(this); + HttpCookie cookie = _sessionManager.getSessionCookie(_session,getContextPath(),isSecure()); + if (cookie != null) + _connection.getResponse().addCookie(cookie); + + return _session; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the sessionManager. + */ + public SessionManager getSessionManager() + { + return _sessionManager; + } + + /* ------------------------------------------------------------ */ + /** + * Get Request TimeStamp + * + * @return The time that the request was received. + */ + public long getTimeStamp() + { + return _timeStamp; + } + + /* ------------------------------------------------------------ */ + /** + * Get Request TimeStamp + * + * @return The time that the request was received. + */ + public Buffer getTimeStampBuffer() + { + if (_timeStampBuffer == null && _timeStamp > 0) + _timeStampBuffer = HttpFields.__dateCache.formatBuffer(_timeStamp); + return _timeStampBuffer; + } + + /* ------------------------------------------------------------ */ + /** + * @return Returns the uri. + */ + public HttpURI getUri() + { + return _uri; + } + + /* ------------------------------------------------------------ */ + public UserIdentity getUserIdentity() + { + if (_authentication instanceof Authentication.Deferred) + setAuthentication(((Authentication.Deferred)_authentication).authenticate(this)); + + if (_authentication instanceof Authentication.User) + return ((Authentication.User)_authentication).getUserIdentity(); + return null; + } + + /* ------------------------------------------------------------ */ + /** + * @return The resolved user Identity, which may be null if the {@link Authentication} is not {@link Authentication.User} (eg. + * {@link Authentication.Deferred}). + */ + public UserIdentity getResolvedUserIdentity() + { + if (_authentication instanceof Authentication.User) + return ((Authentication.User)_authentication).getUserIdentity(); + return null; + } + + /* ------------------------------------------------------------ */ + public UserIdentity.Scope getUserIdentityScope() + { + return _scope; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#getUserPrincipal() + */ + 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; + } + + /* ------------------------------------------------------------ */ + /** + * Get timestamp of the request dispatch + * + * @return timestamp + */ + public long getDispatchTime() + { + return _dispatchTime; + } + + /* ------------------------------------------------------------ */ + public boolean isHandled() + { + return _handled; + } + + public boolean isAsyncStarted() + { + return _async.isAsyncStarted(); + } + + + /* ------------------------------------------------------------ */ + public boolean isAsyncSupported() + { + return _asyncSupported; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie() + */ + public boolean isRequestedSessionIdFromCookie() + { + return _requestedSessionId != null && _requestedSessionIdFromCookie; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl() + */ + public boolean isRequestedSessionIdFromUrl() + { + return _requestedSessionId != null && !_requestedSessionIdFromCookie; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL() + */ + public boolean isRequestedSessionIdFromURL() + { + return _requestedSessionId != null && !_requestedSessionIdFromCookie; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid() + */ + public boolean isRequestedSessionIdValid() + { + if (_requestedSessionId == null) + return false; + + HttpSession session = getSession(false); + return (session != null && _sessionManager.getSessionIdManager().getClusterId(_requestedSessionId).equals(_sessionManager.getClusterId(session))); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#isSecure() + */ + public boolean isSecure() + { + return _connection.isConfidential(this); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String) + */ + 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; + } + + /* ------------------------------------------------------------ */ + public HttpSession recoverNewSession(Object key) + { + if (_savedNewSessions == null) + return null; + return _savedNewSessions.get(key); + } + + /* ------------------------------------------------------------ */ + protected void recycle() + { + if (_inputState == __READER) + { + try + { + int r = _reader.read(); + while (r != -1) + r = _reader.read(); + } + catch (Exception e) + { + LOG.ignore(e); + _reader = null; + } + } + + setAuthentication(Authentication.NOT_CHECKED); + _async.recycle(); + _asyncSupported = true; + _handled = false; + if (_context != null) + throw new IllegalStateException("Request in context!"); + if (_attributes != null) + _attributes.clearAttributes(); + _characterEncoding = null; + _contextPath = null; + if (_cookies != null) + _cookies.reset(); + _cookiesExtracted = false; + _context = null; + _serverName = null; + _method = null; + _pathInfo = null; + _port = 0; + _protocol = HttpVersions.HTTP_1_1; + _queryEncoding = null; + _queryString = null; + _requestedSessionId = null; + _requestedSessionIdFromCookie = false; + _session = null; + _sessionManager = null; + _requestURI = null; + _scope = null; + _scheme = URIUtil.HTTP; + _servletPath = null; + _timeStamp = 0; + _timeStampBuffer = null; + _uri = null; + if (_baseParameters != null) + _baseParameters.clear(); + _parameters = null; + _paramsExtracted = false; + _inputState = __NONE; + + if (_savedNewSessions != null) + _savedNewSessions.clear(); + _savedNewSessions=null; + _multiPartInputStream = null; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String) + */ + public void removeAttribute(String name) + { + Object old_value = _attributes == null?null:_attributes.getAttribute(name); + + if (_attributes != null) + _attributes.removeAttribute(name); + + if (old_value != null) + { + if (_requestAttributeListeners != null) + { + final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value); + final int size = LazyList.size(_requestAttributeListeners); + for (int i = 0; i < size; i++) + { + final EventListener listener = (ServletRequestAttributeListener)LazyList.get(_requestAttributeListeners,i); + if (listener instanceof ServletRequestAttributeListener) + { + final ServletRequestAttributeListener l = (ServletRequestAttributeListener)listener; + l.attributeRemoved(event); + } + } + } + } + } + + /* ------------------------------------------------------------ */ + public void removeEventListener(final EventListener listener) + { + _requestAttributeListeners = LazyList.remove(_requestAttributeListeners,listener); + } + + /* ------------------------------------------------------------ */ + public void saveNewSession(Object key, HttpSession session) + { + if (_savedNewSessions == null) + _savedNewSessions = new HashMap<Object, HttpSession>(); + _savedNewSessions.put(key,session); + } + + /* ------------------------------------------------------------ */ + 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#setMaxIdleTime}. + * + * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object) + */ + public void setAttribute(String name, Object value) + { + Object old_value = _attributes == null?null:_attributes.getAttribute(name); + + if (name.startsWith("org.eclipse.jetty.")) + { + if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name)) + setQueryEncoding(value == null?null:value.toString()); + else if ("org.eclipse.jetty.server.sendContent".equals(name)) + { + try + { + ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendContent(value); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + else if ("org.eclipse.jetty.server.ResponseBuffer".equals(name)) + { + try + { + final ByteBuffer byteBuffer = (ByteBuffer)value; + synchronized (byteBuffer) + { + NIOBuffer buffer = byteBuffer.isDirect()?new DirectNIOBuffer(byteBuffer,true):new IndirectNIOBuffer(byteBuffer,true); + ((AbstractHttpConnection.Output)getServletResponse().getOutputStream()).sendResponse(buffer); + } + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + else if ("org.eclipse.jetty.io.EndPoint.maxIdleTime".equalsIgnoreCase(name)) + { + try + { + getConnection().getEndPoint().setMaxIdleTime(Integer.valueOf(value.toString())); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + } + + if (_attributes == null) + _attributes = new AttributesMap(); + _attributes.setAttribute(name,value); + + if (_requestAttributeListeners != null) + { + final ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(_context,this,name,old_value == null?value:old_value); + final int size = LazyList.size(_requestAttributeListeners); + for (int i = 0; i < size; i++) + { + final EventListener listener = (ServletRequestAttributeListener)LazyList.get(_requestAttributeListeners,i); + if (listener instanceof ServletRequestAttributeListener) + { + final ServletRequestAttributeListener l = (ServletRequestAttributeListener)listener; + + if (old_value == null) + l.attributeAdded(event); + else if (value == null) + l.attributeRemoved(event); + else + l.attributeReplaced(event); + } + } + } + } + + /* ------------------------------------------------------------ */ + /* + */ + public void setAttributes(Attributes attributes) + { + _attributes = attributes; + } + + /* ------------------------------------------------------------ */ + + /* ------------------------------------------------------------ */ + /** + * Set the authentication. + * + * @param authentication + * the authentication to set + */ + public void setAuthentication(Authentication authentication) + { + _authentication = authentication; + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String) + */ + public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException + { + if (_inputState != __NONE) + return; + + _characterEncoding = encoding; + + // check encoding is supported + if (!StringUtil.isUTF8(encoding)) + // noinspection ResultOfMethodCallIgnored + "".getBytes(encoding); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String) + */ + public void setCharacterEncodingUnchecked(String encoding) + { + _characterEncoding = encoding; + } + + /* ------------------------------------------------------------ */ + // final so we can safely call this from constructor + protected final void setConnection(AbstractHttpConnection connection) + { + _connection = connection; + _async.setConnection(connection); + _endp = connection.getEndPoint(); + _dns = connection.getResolveNames(); + } + + /* ------------------------------------------------------------ */ + /* + * @see javax.servlet.ServletRequest#getContentType() + */ + public void setContentType(String contentType) + { + _connection.getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,contentType); + + } + + /* ------------------------------------------------------------ */ + /** + * Set request context + * + * @param context + * context object + */ + public void setContext(Context context) + { + _newContext = _context != context; + _context = 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) + { + if (_cookies == null) + _cookies = new CookieCutter(); + _cookies.setCookies(cookies); + } + + /* ------------------------------------------------------------ */ + public void setDispatcherType(DispatcherType type) + { + _dispatcherType = type; + } + + /* ------------------------------------------------------------ */ + public void setHandled(boolean h) + { + _handled = h; + } + + /* ------------------------------------------------------------ */ + /** + * @param method + * The method to set. + */ + public void setMethod(String method) + { + _method = method; + } + + /* ------------------------------------------------------------ */ + /** + * @param parameters + * The parameters to set. + */ + public void setParameters(MultiMap<String> parameters) + { + _parameters = (parameters == null)?_baseParameters:parameters; + if (_paramsExtracted && _parameters == null) + throw new IllegalStateException(); + } + + /* ------------------------------------------------------------ */ + /** + * @param pathInfo + * The pathInfo to set. + */ + public void setPathInfo(String pathInfo) + { + _pathInfo = pathInfo; + } + + /* ------------------------------------------------------------ */ + /** + * @param protocol + * The protocol to set. + */ + public void setProtocol(String protocol) + { + _protocol = protocol; + } + + /* ------------------------------------------------------------ */ + /** + * 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(String addr) + { + _remoteAddr = addr; + } + + /* ------------------------------------------------------------ */ + /** + * @param host + * The host to set. + */ + public void setRemoteHost(String host) + { + _remoteHost = host; + } + + /* ------------------------------------------------------------ */ + /** + * @param requestedSessionId + * The requestedSessionId to set. + */ + public void setRequestedSessionId(String requestedSessionId) + { + _requestedSessionId = requestedSessionId; + } + + /* ------------------------------------------------------------ */ + /** + * @param requestedSessionIdCookie + * The requestedSessionIdCookie to set. + */ + public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie) + { + _requestedSessionIdFromCookie = 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(HttpSession session) + { + _session = session; + } + + /* ------------------------------------------------------------ */ + /** + * @param sessionManager + * The sessionManager to set. + */ + public void setSessionManager(SessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /* ------------------------------------------------------------ */ + public void setTimeStamp(long ts) + { + _timeStamp = ts; + } + + /* ------------------------------------------------------------ */ + /** + * @param uri + * The uri to set. + */ + public void setUri(HttpURI uri) + { + _uri = uri; + } + + /* ------------------------------------------------------------ */ + public void setUserIdentityScope(UserIdentity.Scope scope) + { + _scope = scope; + } + + /* ------------------------------------------------------------ */ + /** + * Set timetstamp of request dispatch + * + * @param value + * timestamp + */ + public void setDispatchTime(long value) + { + _dispatchTime = value; + } + + /* ------------------------------------------------------------ */ + public AsyncContext startAsync() throws IllegalStateException + { + if (!_asyncSupported) + throw new IllegalStateException("!asyncSupported"); + _async.startAsync(); + return _async; + } + + /* ------------------------------------------------------------ */ + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException + { + if (!_asyncSupported) + throw new IllegalStateException("!asyncSupported"); + _async.startAsync(_context,servletRequest,servletResponse); + return _async; + } + + /* ------------------------------------------------------------ */ + @Override + public String toString() + { + return (_handled?"[":"(") + getMethod() + " " + _uri + (_handled?"]@":")@") + hashCode() + " " + super.toString(); + } + + /* ------------------------------------------------------------ */ + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException + { + if (_authentication instanceof Authentication.Deferred) + { + setAuthentication(((Authentication.Deferred)_authentication).authenticate(this,response)); + return !(_authentication instanceof Authentication.ResponseSent); + } + response.sendError(HttpStatus.UNAUTHORIZED_401); + return false; + } + + /* ------------------------------------------------------------ */ + public Part getPart(String name) throws IOException, ServletException + { + getParts(); + return _multiPartInputStream.getPart(name); + } + + /* ------------------------------------------------------------ */ + 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) + _multiPartInputStream = (MultiPartInputStream)getAttribute(__MULTIPART_INPUT_STREAM); + + if (_multiPartInputStream == null) + { + MultipartConfigElement config = (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT); + + if (config == null) + throw new IllegalStateException("No multipart config for servlet"); + + _multiPartInputStream = new MultiPartInputStream(getInputStream(), + getContentType(), config, + (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null)); + + setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream); + setAttribute(__MULTIPART_CONTEXT, _context); + Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing + for (Part p:parts) + { + MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p; + if (mp.getContentDispositionFilename() == 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(new ByteArrayBuffer(mp.getContentType())); + + ByteArrayOutputStream os = null; + InputStream is = mp.getInputStream(); //get the bytes regardless of being in memory or in temp file + try + { + os = new ByteArrayOutputStream(); + IO.copy(is, os); + String content=new String(os.toByteArray(),charset==null?StringUtil.__UTF8:charset); + getParameter(""); //cause params to be evaluated + getParameters().add(mp.getName(), content); + } + finally + { + IO.close(os); + IO.close(is); + } + } + } + } + + return _multiPartInputStream.getParts(); + } + + /* ------------------------------------------------------------ */ + public void login(String username, String password) throws ServletException + { + if (_authentication instanceof Authentication.Deferred) + { + _authentication=((Authentication.Deferred)_authentication).login(username,password,this); + if (_authentication == null) + throw new ServletException(); + } + else + { + throw new ServletException("Authenticated as "+_authentication); + } + } + + /* ------------------------------------------------------------ */ + public void logout() throws ServletException + { + if (_authentication instanceof Authentication.User) + ((Authentication.User)_authentication).logout(); + _authentication=Authentication.UNAUTHENTICATED; + } + + /* ------------------------------------------------------------ */ + /** + * 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<String>(); + UrlEncoded.decodeTo(query,parameters, StringUtil.__UTF8); //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. + Iterator<Entry<String, Object>> iter = _parameters.entrySet().iterator(); + while (iter.hasNext()) + { + Map.Entry<String, Object> entry = iter.next(); + String name = entry.getKey(); + + // If the names match, we will need to remake the query string + if (parameters.containsKey(name)) + merge_old_query = true; + + // Add the old values to the new parameter map + Object values = entry.getValue(); + for (int i = 0; i < LazyList.size(values); i++) + parameters.add(name,LazyList.get(values,i)); + } + } + + if (_queryString != null && _queryString.length() > 0) + { + if (merge_old_query) + { + StringBuilder overridden_query_string = new StringBuilder(); + MultiMap<String> overridden_old_query = new MultiMap<String>(); + UrlEncoded.decodeTo(_queryString,overridden_old_query,getQueryEncoding());//decode using any queryencoding set for the request + + + MultiMap<String> overridden_new_query = new MultiMap<String>(); + UrlEncoded.decodeTo(query,overridden_new_query,StringUtil.__UTF8); //have to assume utf8 as we cannot know otherwise + + Iterator<Entry<String, Object>> iter = overridden_old_query.entrySet().iterator(); + while (iter.hasNext()) + { + Map.Entry<String, Object> entry = iter.next(); + String name = entry.getKey(); + if (!overridden_new_query.containsKey(name)) + { + Object values = entry.getValue(); + for (int i = 0; i < LazyList.size(values); i++) + { + overridden_query_string.append("&").append(name).append("=").append((Object)LazyList.get(values,i)); + } + } + } + + query = query + overridden_query_string; + } + else + { + query = query + "&" + _queryString; + } + } + + setParameters(parameters); + setQueryString(query); + } +}